Merge remote-tracking branch 'qemu-kvm/uq/master' into stable-1.5
* qemu-kvm/uq/master:
kvm-stub: fix compilation
kvm: shorten the parameter list for get_real_device()
kvm: i386: fix LAPIC TSC deadline timer save/restore
kvm-all.c: max_cpus should not exceed KVM vcpu limit
kvm: Simplify kvm_handle_io
kvm: x86: fix setting IA32_FEATURE_CONTROL with nested VMX disabled
kvm: add KVM_IRQFD_FLAG_RESAMPLE support
kvm: migrate vPMU state
target-i386: remove tabs from target-i386/cpu.h
Initialize IA32_FEATURE_CONTROL MSR in reset and migration
Conflicts:
target-i386/cpu.h
target-i386/kvm.c
aliguori: fixup trivial conflicts due to whitespace and added cpu
argument
Signed-off-by: Anthony Liguori <anthony@codemonkey.ws>
diff --git a/.gitignore b/.gitignore
index 0fe114d..d2c5c2f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,7 +45,10 @@
qemu-monitor.texi
vscclient
QMP/qmp-commands.txt
+test-bitops
test-coroutine
+test-int128
+test-opts-visitor
test-qmp-input-visitor
test-qmp-output-visitor
test-string-input-visitor
diff --git a/.mailmap b/.mailmap
index 9797802..7b91a95 100644
--- a/.mailmap
+++ b/.mailmap
@@ -2,7 +2,7 @@
# into proper addresses so that they are counted properly in git shortlog output.
#
Andrzej Zaborowski <balrogg@gmail.com> balrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>
-Anthony Liguori <aliguori@us.ibm.com> aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
+Anthony Liguori <anthony@codemonkey.ws> aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>
Aurelien Jarno <aurelien@aurel32.net> aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>
Blue Swirl <blauwirbel@gmail.com> blueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>
Edgar E. Iglesias <edgar.iglesias@gmail.com> edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162>
diff --git a/LICENSE b/LICENSE
index acae9a3..da70e94 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,16 +1,21 @@
The following points clarify the QEMU license:
-1) QEMU as a whole is released under the GNU General Public License
+1) QEMU as a whole is released under the GNU General Public License,
+version 2.
2) Parts of QEMU have specific licenses which are compatible with the
-GNU General Public License. Hence each source file contains its own
-licensing information.
+GNU General Public License, version 2. Hence each source file contains
+its own licensing information. Source files with no licensing information
+are released under the GNU General Public License, version 2 or (at your
+option) any later version.
-Many hardware device emulation sources are released under the BSD license.
+As of July 2013, contributions under version 2 of the GNU General Public
+License (and no later version) are only accepted for the following files
+or directories: bsd-user/, linux-user/, hw/misc/vfio.c, hw/xen/xen_pt*.
3) The Tiny Code Generator (TCG) is released under the BSD license
(see license headers in files).
4) QEMU is a trademark of Fabrice Bellard.
-Fabrice Bellard.
+Fabrice Bellard and the QEMU team
diff --git a/MAINTAINERS b/MAINTAINERS
index 93ad19d..d128ed0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -50,7 +50,7 @@
General Project Administration
------------------------------
-M: Anthony Liguori <aliguori@us.ibm.com>
+M: Anthony Liguori <anthony@codemonkey.ws>
M: Paul Brook <paul@codesourcery.com>
Guest CPU cores (TCG):
@@ -80,6 +80,7 @@
S: Maintained
F: target-lm32/
F: hw/lm32/
+F: hw/char/lm32_*
M68K
M: Paul Brook <paul@codesourcery.com>
@@ -224,7 +225,7 @@
Exynos
M: Evgeny Voevodin <e.voevodin@samsung.com>
M: Maksim Kozlov <m.kozlov@samsung.com>
-M: Igor Mitsyanko <i.mitsyanko@samsung.com>
+M: Igor Mitsyanko <i.mitsyanko@gmail.com>
M: Dmitry Solodkiy <d.solodkiy@samsung.com>
S: Maintained
F: hw/*/exynos*
@@ -508,7 +509,7 @@
X86 Machines
------------
PC
-M: Anthony Liguori <aliguori@us.ibm.com>
+M: Anthony Liguori <anthony@codemonkey.ws>
S: Supported
F: hw/i386/pc.[ch]
F: hw/i386/pc_piix.c
@@ -592,7 +593,7 @@
F: hw/*/*vhost*
virtio
-M: Anthony Liguori <aliguori@us.ibm.com>
+M: Anthony Liguori <anthony@codemonkey.ws>
S: Supported
F: hw/*/virtio*
@@ -650,7 +651,7 @@
F: hw/block/
Character Devices
-M: Anthony Liguori <aliguori@us.ibm.com>
+M: Anthony Liguori <anthony@codemonkey.ws>
S: Maintained
F: qemu-char.c
@@ -688,7 +689,7 @@
F: hw/display/qxl*
Graphics
-M: Anthony Liguori <aliguori@us.ibm.com>
+M: Anthony Liguori <anthony@codemonkey.ws>
S: Maintained
F: ui/
@@ -698,7 +699,7 @@
F: ui/cocoa.m
Main loop
-M: Anthony Liguori <aliguori@us.ibm.com>
+M: Anthony Liguori <anthony@codemonkey.ws>
S: Supported
F: vl.c
@@ -710,7 +711,7 @@
F: hmp-commands.hx
Network device layer
-M: Anthony Liguori <aliguori@us.ibm.com>
+M: Anthony Liguori <anthony@codemonkey.ws>
M: Stefan Hajnoczi <stefanha@redhat.com>
S: Maintained
F: net/
@@ -851,8 +852,9 @@
Stable 0.15
L: qemu-stable@nongnu.org
+M: Andreas Färber <afaerber@suse.de>
T: git git://git.qemu.org/qemu-stable-0.15.git
-S: Orphan
+S: Supported
Stable 0.14
L: qemu-stable@nongnu.org
diff --git a/Makefile b/Makefile
index c06bfab..806946e 100644
--- a/Makefile
+++ b/Makefile
@@ -167,11 +167,10 @@
bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
-version.o: $(SRC_PATH)/version.rc config-host.h | version.lo
-version.lo: $(SRC_PATH)/version.rc config-host.h
-
-version-obj-$(CONFIG_WIN32) += version.o
-version-lobj-$(CONFIG_WIN32) += version.lo
+$(BUILD_DIR)/version.o: $(SRC_PATH)/version.rc $(BUILD_DIR)/config-host.h | $(BUILD_DIR)/version.lo
+ $(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<," RC version.o")
+$(BUILD_DIR)/version.lo: $(SRC_PATH)/version.rc $(BUILD_DIR)/config-host.h
+ $(call quiet-command,$(WINDRES) -I$(BUILD_DIR) -o $@ $<," RC version.lo")
Makefile: $(version-obj-y) $(version-lobj-y)
@@ -437,6 +436,61 @@
qemu-img.texi qemu-nbd.texi qemu-options.texi \
qemu-monitor.texi qemu-img-cmds.texi
+ifdef CONFIG_WIN32
+
+INSTALLER = qemu-setup-$(VERSION)$(EXESUF)
+
+nsisflags = -V2 -NOCD
+
+ifneq ($(wildcard $(SRC_PATH)/dll),)
+ifeq ($(ARCH),x86_64)
+# 64 bit executables
+DLL_PATH = $(SRC_PATH)/dll/w64
+nsisflags += -DW64
+else
+# 32 bit executables
+DLL_PATH = $(SRC_PATH)/dll/w32
+endif
+endif
+
+.PHONY: installer
+installer: $(INSTALLER)
+
+INSTDIR=/tmp/qemu-nsis
+
+$(INSTALLER): $(SRC_PATH)/qemu.nsi
+ make install prefix=${INSTDIR}
+ifdef SIGNCODE
+ (cd ${INSTDIR}; \
+ for i in *.exe; do \
+ $(SIGNCODE) $${i}; \
+ done \
+ )
+endif # SIGNCODE
+ (cd ${INSTDIR}; \
+ for i in qemu-system-*.exe; do \
+ arch=$${i%.exe}; \
+ arch=$${arch#qemu-system-}; \
+ echo Section \"$$arch\" Section_$$arch; \
+ echo SetOutPath \"\$$INSTDIR\"; \
+ echo File \"\$${BINDIR}\\$$i\"; \
+ echo SectionEnd; \
+ done \
+ ) >${INSTDIR}/system-emulations.nsh
+ makensis $(nsisflags) \
+ $(if $(BUILD_DOCS),-DCONFIG_DOCUMENTATION="y") \
+ $(if $(CONFIG_GTK),-DCONFIG_GTK="y") \
+ -DBINDIR="${INSTDIR}" \
+ $(if $(DLL_PATH),-DDLLDIR="$(DLL_PATH)") \
+ -DSRCDIR="$(SRC_PATH)" \
+ -DOUTFILE="$(INSTALLER)" \
+ $(SRC_PATH)/qemu.nsi
+ rm -r ${INSTDIR}
+ifdef SIGNCODE
+ $(SIGNCODE) $(INSTALLER)
+endif # SIGNCODE
+endif # CONFIG_WIN
+
# Add a dependency on the generated files, so that they are always
# rebuilt before other object files
ifneq ($(filter-out %clean,$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail))
diff --git a/Makefile.objs b/Makefile.objs
index 9928542..f46a4cd 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -99,6 +99,11 @@
common-obj-y += disas/
######################################################################
+# Resource file for Windows executables
+version-obj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.o
+version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo
+
+######################################################################
# guest agent
# FIXME: a few definitions from qapi-types.o/qapi-visit.o are needed
diff --git a/VERSION b/VERSION
index 88eb60e..0a8112b 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.5.50
+1.6.50
diff --git a/aio-posix.c b/aio-posix.c
index b68eccd..bd06f33 100644
--- a/aio-posix.c
+++ b/aio-posix.c
@@ -23,7 +23,6 @@
GPollFD pfd;
IOHandler *io_read;
IOHandler *io_write;
- AioFlushHandler *io_flush;
int deleted;
int pollfds_idx;
void *opaque;
@@ -47,7 +46,6 @@
int fd,
IOHandler *io_read,
IOHandler *io_write,
- AioFlushHandler *io_flush,
void *opaque)
{
AioHandler *node;
@@ -84,7 +82,6 @@
/* Update handler with latest information */
node->io_read = io_read;
node->io_write = io_write;
- node->io_flush = io_flush;
node->opaque = opaque;
node->pollfds_idx = -1;
@@ -97,12 +94,10 @@
void aio_set_event_notifier(AioContext *ctx,
EventNotifier *notifier,
- EventNotifierHandler *io_read,
- AioFlushEventNotifierHandler *io_flush)
+ EventNotifierHandler *io_read)
{
aio_set_fd_handler(ctx, event_notifier_get_fd(notifier),
- (IOHandler *)io_read, NULL,
- (AioFlushHandler *)io_flush, notifier);
+ (IOHandler *)io_read, NULL, notifier);
}
bool aio_pending(AioContext *ctx)
@@ -147,7 +142,11 @@
(revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
node->io_read) {
node->io_read(node->opaque);
- progress = true;
+
+ /* aio_notify() does not count as progress */
+ if (node->opaque != &ctx->notifier) {
+ progress = true;
+ }
}
if (!node->deleted &&
(revents & (G_IO_OUT | G_IO_ERR)) &&
@@ -166,6 +165,10 @@
g_free(tmp);
}
}
+
+ /* Run our timers */
+ progress |= timerlistgroup_run_timers(&ctx->tlg);
+
return progress;
}
@@ -173,7 +176,7 @@
{
AioHandler *node;
int ret;
- bool busy, progress;
+ bool progress;
progress = false;
@@ -200,20 +203,8 @@
g_array_set_size(ctx->pollfds, 0);
/* fill pollfds */
- busy = false;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
node->pollfds_idx = -1;
-
- /* If there aren't pending AIO operations, don't invoke callbacks.
- * Otherwise, if there are no AIO requests, qemu_aio_wait() would
- * wait indefinitely.
- */
- if (!node->deleted && node->io_flush) {
- if (node->io_flush(node->opaque) == 0) {
- continue;
- }
- busy = true;
- }
if (!node->deleted && node->pfd.events) {
GPollFD pfd = {
.fd = node->pfd.fd,
@@ -226,15 +217,15 @@
ctx->walking_handlers--;
- /* No AIO operations? Get us out of here */
- if (!busy) {
+ /* early return if we only have the aio_notify() fd */
+ if (ctx->pollfds->len == 1) {
return progress;
}
/* wait until next event */
- ret = g_poll((GPollFD *)ctx->pollfds->data,
- ctx->pollfds->len,
- blocking ? -1 : 0);
+ ret = qemu_poll_ns((GPollFD *)ctx->pollfds->data,
+ ctx->pollfds->len,
+ blocking ? timerlistgroup_deadline_ns(&ctx->tlg) : 0);
/* if we have any readable fds, dispatch event */
if (ret > 0) {
@@ -245,11 +236,12 @@
node->pfd.revents = pfd->revents;
}
}
- if (aio_dispatch(ctx)) {
- progress = true;
- }
}
- assert(progress || busy);
- return true;
+ /* Run dispatch even if there were no readable fds to run timers */
+ if (aio_dispatch(ctx)) {
+ progress = true;
+ }
+
+ return progress;
}
diff --git a/aio-win32.c b/aio-win32.c
index 38723bf..f9cfbb7 100644
--- a/aio-win32.c
+++ b/aio-win32.c
@@ -23,7 +23,6 @@
struct AioHandler {
EventNotifier *e;
EventNotifierHandler *io_notify;
- AioFlushEventNotifierHandler *io_flush;
GPollFD pfd;
int deleted;
QLIST_ENTRY(AioHandler) node;
@@ -31,8 +30,7 @@
void aio_set_event_notifier(AioContext *ctx,
EventNotifier *e,
- EventNotifierHandler *io_notify,
- AioFlushEventNotifierHandler *io_flush)
+ EventNotifierHandler *io_notify)
{
AioHandler *node;
@@ -73,7 +71,6 @@
}
/* Update handler with latest information */
node->io_notify = io_notify;
- node->io_flush = io_flush;
}
aio_notify(ctx);
@@ -96,8 +93,9 @@
{
AioHandler *node;
HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
- bool busy, progress;
+ bool progress;
int count;
+ int timeout;
progress = false;
@@ -111,6 +109,9 @@
progress = true;
}
+ /* Run timers */
+ progress |= timerlistgroup_run_timers(&ctx->tlg);
+
/*
* Then dispatch any pending callbacks from the GSource.
*
@@ -126,7 +127,11 @@
if (node->pfd.revents && node->io_notify) {
node->pfd.revents = 0;
node->io_notify(node->e);
- progress = true;
+
+ /* aio_notify() does not count as progress */
+ if (node->e != &ctx->notifier) {
+ progress = true;
+ }
}
tmp = node;
@@ -147,19 +152,8 @@
ctx->walking_handlers++;
/* fill fd sets */
- busy = false;
count = 0;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
- /* If there aren't pending AIO operations, don't invoke callbacks.
- * Otherwise, if there are no AIO requests, qemu_aio_wait() would
- * wait indefinitely.
- */
- if (!node->deleted && node->io_flush) {
- if (node->io_flush(node->e) == 0) {
- continue;
- }
- busy = true;
- }
if (!node->deleted && node->io_notify) {
events[count++] = event_notifier_get_handle(node->e);
}
@@ -167,15 +161,18 @@
ctx->walking_handlers--;
- /* No AIO operations? Get us out of here */
- if (!busy) {
+ /* early return if we only have the aio_notify() fd */
+ if (count == 1) {
return progress;
}
/* wait until next event */
while (count > 0) {
- int timeout = blocking ? INFINITE : 0;
- int ret = WaitForMultipleObjects(count, events, FALSE, timeout);
+ int ret;
+
+ timeout = blocking ?
+ qemu_timeout_ns_to_ms(timerlistgroup_deadline_ns(&ctx->tlg)) : 0;
+ ret = WaitForMultipleObjects(count, events, FALSE, timeout);
/* if we have any signaled events, dispatch event */
if ((DWORD) (ret - WAIT_OBJECT_0) >= count) {
@@ -196,7 +193,11 @@
event_notifier_get_handle(node->e) == events[ret - WAIT_OBJECT_0] &&
node->io_notify) {
node->io_notify(node->e);
- progress = true;
+
+ /* aio_notify() does not count as progress */
+ if (node->e != &ctx->notifier) {
+ progress = true;
+ }
}
tmp = node;
@@ -214,6 +215,14 @@
events[ret - WAIT_OBJECT_0] = events[--count];
}
- assert(progress || busy);
- return true;
+ if (blocking) {
+ /* Run the timers a second time. We do this because otherwise aio_wait
+ * will not note progress - and will stop a drain early - if we have
+ * a timer that was not ready to run entering g_poll but is ready
+ * after g_poll. This will only do anything if a timer has expired.
+ */
+ progress |= timerlistgroup_run_timers(&ctx->tlg);
+ }
+
+ return progress;
}
diff --git a/arch_init.c b/arch_init.c
index 68a7ab7..0471cd5 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -342,7 +342,8 @@
{
unsigned long base = mr->ram_addr >> TARGET_PAGE_BITS;
unsigned long nr = base + (start >> TARGET_PAGE_BITS);
- unsigned long size = base + (int128_get64(mr->size) >> TARGET_PAGE_BITS);
+ uint64_t mr_size = TARGET_PAGE_ALIGN(memory_region_size(mr));
+ unsigned long size = base + (mr_size >> TARGET_PAGE_BITS);
unsigned long next;
@@ -392,7 +393,7 @@
}
if (!start_time) {
- start_time = qemu_get_clock_ms(rt_clock);
+ start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
}
trace_migration_bitmap_sync_start();
@@ -410,7 +411,7 @@
trace_migration_bitmap_sync_end(migration_dirty_pages
- num_dirty_pages_init);
num_dirty_pages_period += migration_dirty_pages - num_dirty_pages_init;
- end_time = qemu_get_clock_ms(rt_clock);
+ end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
/* more than 1 second = 1000 millisecons */
if (end_time > start_time + 1000) {
@@ -672,7 +673,7 @@
ram_control_before_iterate(f, RAM_CONTROL_ROUND);
- t0 = qemu_get_clock_ns(rt_clock);
+ t0 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
i = 0;
while ((ret = qemu_file_rate_limit(f)) == 0) {
int bytes_sent;
@@ -691,7 +692,7 @@
iterations
*/
if ((i & 63) == 0) {
- uint64_t t1 = (qemu_get_clock_ns(rt_clock) - t0) / 1000000;
+ uint64_t t1 = (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - t0) / 1000000;
if (t1 > MAX_WAIT) {
DPRINTF("big wait: %" PRIu64 " milliseconds, %d iterations\n",
t1, i);
@@ -1125,8 +1126,8 @@
acpi_table_add(opts, &err);
if (err) {
- fprintf(stderr, "Wrong acpi table provided: %s\n",
- error_get_pretty(err));
+ error_report("Wrong acpi table provided: %s",
+ error_get_pretty(err));
error_free(err);
exit(1);
}
@@ -1217,11 +1218,11 @@
}
if (!t0) {
- t0 = qemu_get_clock_ns(rt_clock);
+ t0 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
return;
}
- t1 = qemu_get_clock_ns(rt_clock);
+ t1 = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
/* If it has been more than 40 ms since the last time the guest
* was throttled then do it again.
diff --git a/async.c b/async.c
index 5ce3633..5fb3fa6 100644
--- a/async.c
+++ b/async.c
@@ -150,7 +150,10 @@
{
AioContext *ctx = (AioContext *) source;
QEMUBH *bh;
+ int deadline;
+ /* We assume there is no timeout already supplied */
+ *timeout = -1;
for (bh = ctx->first_bh; bh; bh = bh->next) {
if (!bh->deleted && bh->scheduled) {
if (bh->idle) {
@@ -166,6 +169,14 @@
}
}
+ deadline = qemu_timeout_ns_to_ms(timerlistgroup_deadline_ns(&ctx->tlg));
+ if (deadline == 0) {
+ *timeout = 0;
+ return true;
+ } else {
+ *timeout = qemu_soonest_timeout(*timeout, deadline);
+ }
+
return false;
}
@@ -180,7 +191,7 @@
return true;
}
}
- return aio_pending(ctx);
+ return aio_pending(ctx) || (timerlistgroup_deadline_ns(&ctx->tlg) == 0);
}
static gboolean
@@ -201,10 +212,11 @@
AioContext *ctx = (AioContext *) source;
thread_pool_free(ctx->thread_pool);
- aio_set_event_notifier(ctx, &ctx->notifier, NULL, NULL);
+ aio_set_event_notifier(ctx, &ctx->notifier, NULL);
event_notifier_cleanup(&ctx->notifier);
qemu_mutex_destroy(&ctx->bh_lock);
g_array_free(ctx->pollfds, TRUE);
+ timerlistgroup_deinit(&ctx->tlg);
}
static GSourceFuncs aio_source_funcs = {
@@ -233,6 +245,11 @@
event_notifier_set(&ctx->notifier);
}
+static void aio_timerlist_notify(void *opaque)
+{
+ aio_notify(opaque);
+}
+
AioContext *aio_context_new(void)
{
AioContext *ctx;
@@ -243,7 +260,8 @@
event_notifier_init(&ctx->notifier, false);
aio_set_event_notifier(ctx, &ctx->notifier,
(EventNotifierHandler *)
- event_notifier_test_and_clear, NULL);
+ event_notifier_test_and_clear);
+ timerlistgroup_init(&ctx->tlg, aio_timerlist_notify, ctx);
return ctx;
}
diff --git a/audio/audio.c b/audio/audio.c
index 02bb886..af4cdf6 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1124,10 +1124,10 @@
static void audio_reset_timer (AudioState *s)
{
if (audio_is_timer_needed ()) {
- qemu_mod_timer (s->ts, qemu_get_clock_ns (vm_clock) + 1);
+ timer_mod (s->ts, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 1);
}
else {
- qemu_del_timer (s->ts);
+ timer_del (s->ts);
}
}
@@ -1834,7 +1834,7 @@
QLIST_INIT (&s->cap_head);
atexit (audio_atexit);
- s->ts = qemu_new_timer_ns (vm_clock, audio_timer, s);
+ s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
if (!s->ts) {
hw_error("Could not create audio timer\n");
}
diff --git a/audio/noaudio.c b/audio/noaudio.c
index 9f23aa2..cb38662 100644
--- a/audio/noaudio.c
+++ b/audio/noaudio.c
@@ -46,7 +46,7 @@
int64_t ticks;
int64_t bytes;
- now = qemu_get_clock_ns (vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ticks = now - no->old_ticks;
bytes = muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
bytes = audio_MIN (bytes, INT_MAX);
@@ -102,7 +102,7 @@
int samples = 0;
if (dead) {
- int64_t now = qemu_get_clock_ns (vm_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
int64_t ticks = now - no->old_ticks;
int64_t bytes =
muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
index bc24557..5af436c 100644
--- a/audio/spiceaudio.c
+++ b/audio/spiceaudio.c
@@ -81,7 +81,7 @@
static void rate_start (SpiceRateCtl *rate)
{
memset (rate, 0, sizeof (*rate));
- rate->start_ticks = qemu_get_clock_ns (vm_clock);
+ rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate)
@@ -91,7 +91,7 @@
int64_t bytes;
int64_t samples;
- now = qemu_get_clock_ns (vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ticks = now - rate->start_ticks;
bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ());
samples = (bytes - rate->bytes_sent) >> info->shift;
diff --git a/audio/wavaudio.c b/audio/wavaudio.c
index 950fa8f..6846a1a 100644
--- a/audio/wavaudio.c
+++ b/audio/wavaudio.c
@@ -52,7 +52,7 @@
int rpos, decr, samples;
uint8_t *dst;
struct st_sample *src;
- int64_t now = qemu_get_clock_ns (vm_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
int64_t ticks = now - wav->old_ticks;
int64_t bytes =
muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
diff --git a/backends/baum.c b/backends/baum.c
index 62aa784..1132899 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -314,9 +314,9 @@
return 0; \
if (*cur++ != ESC) { \
DPRINTF("Broken packet %#2x, tossing\n", req); \
- if (qemu_timer_pending(baum->cellCount_timer)) { \
- qemu_del_timer(baum->cellCount_timer); \
- baum_cellCount_timer_cb(baum); \
+ if (timer_pending(baum->cellCount_timer)) { \
+ timer_del(baum->cellCount_timer); \
+ baum_cellCount_timer_cb(baum); \
} \
return (cur - 2 - buf); \
} \
@@ -334,7 +334,7 @@
int i;
/* Allow 100ms to complete the DisplayData packet */
- qemu_mod_timer(baum->cellCount_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(baum->cellCount_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
get_ticks_per_sec() / 10);
for (i = 0; i < baum->x * baum->y ; i++) {
EAT(c);
@@ -348,7 +348,7 @@
c = '?';
text[i] = c;
}
- qemu_del_timer(baum->cellCount_timer);
+ timer_del(baum->cellCount_timer);
memset(zero, 0, sizeof(zero));
@@ -553,7 +553,7 @@
{
BaumDriverState *baum = chr->opaque;
- qemu_free_timer(baum->cellCount_timer);
+ timer_free(baum->cellCount_timer);
if (baum->brlapi) {
brlapi__closeConnection(baum->brlapi);
g_free(baum->brlapi);
@@ -588,7 +588,7 @@
goto fail_handle;
}
- baum->cellCount_timer = qemu_new_timer_ns(vm_clock, baum_cellCount_timer_cb, baum);
+ baum->cellCount_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, baum_cellCount_timer_cb, baum);
if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
brlapi_perror("baum_init: brlapi_getDisplaySize");
@@ -614,7 +614,7 @@
return chr;
fail:
- qemu_free_timer(baum->cellCount_timer);
+ timer_free(baum->cellCount_timer);
brlapi__closeConnection(handle);
fail_handle:
g_free(handle);
diff --git a/block.c b/block.c
index 6cd39fa..a387c1a 100644
--- a/block.c
+++ b/block.c
@@ -127,11 +127,11 @@
{
bs->io_limits_enabled = false;
- while (qemu_co_queue_next(&bs->throttled_reqs));
+ do {} while (qemu_co_enter_next(&bs->throttled_reqs));
if (bs->block_timer) {
- qemu_del_timer(bs->block_timer);
- qemu_free_timer(bs->block_timer);
+ timer_del(bs->block_timer);
+ timer_free(bs->block_timer);
bs->block_timer = NULL;
}
@@ -143,13 +143,12 @@
{
BlockDriverState *bs = opaque;
- qemu_co_queue_next(&bs->throttled_reqs);
+ qemu_co_enter_next(&bs->throttled_reqs);
}
void bdrv_io_limits_enable(BlockDriverState *bs)
{
- qemu_co_queue_init(&bs->throttled_reqs);
- bs->block_timer = qemu_new_timer_ns(vm_clock, bdrv_block_timer, bs);
+ bs->block_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, bdrv_block_timer, bs);
bs->io_limits_enabled = true;
}
@@ -181,8 +180,8 @@
*/
while (bdrv_exceed_io_limits(bs, nb_sectors, is_write, &wait_time)) {
- qemu_mod_timer(bs->block_timer,
- wait_time + qemu_get_clock_ns(vm_clock));
+ timer_mod(bs->block_timer,
+ wait_time + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
qemu_co_queue_wait_insert_head(&bs->throttled_reqs);
}
@@ -306,6 +305,7 @@
bdrv_iostatus_disable(bs);
notifier_list_init(&bs->close_notifiers);
notifier_with_return_list_init(&bs->before_write_notifiers);
+ qemu_co_queue_init(&bs->throttled_reqs);
return bs;
}
@@ -706,6 +706,7 @@
bs->open_flags = flags;
bs->buffer_alignment = 512;
+ bs->zero_beyond_eof = true;
open_flags = bdrv_open_flags(bs, flags);
bs->read_only = !(open_flags & BDRV_O_RDWR);
@@ -970,6 +971,7 @@
char tmp_filename[PATH_MAX + 1];
BlockDriverState *file = NULL;
QDict *file_options = NULL;
+ const char *drvname;
/* NULL means an empty set of options */
if (options == NULL) {
@@ -1059,6 +1061,12 @@
}
/* Find the right image format driver */
+ drvname = qdict_get_try_str(options, "driver");
+ if (drvname) {
+ drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR));
+ qdict_del(options, "driver");
+ }
+
if (!drv) {
ret = find_image_format(file, filename, &drv);
}
@@ -1395,6 +1403,7 @@
bs->valid_key = 0;
bs->sg = 0;
bs->growable = 0;
+ bs->zero_beyond_eof = false;
QDECREF(bs->options);
bs->options = NULL;
@@ -1421,6 +1430,35 @@
}
}
+/* Check if any requests are in-flight (including throttled requests) */
+static bool bdrv_requests_pending(BlockDriverState *bs)
+{
+ if (!QLIST_EMPTY(&bs->tracked_requests)) {
+ return true;
+ }
+ if (!qemu_co_queue_empty(&bs->throttled_reqs)) {
+ return true;
+ }
+ if (bs->file && bdrv_requests_pending(bs->file)) {
+ return true;
+ }
+ if (bs->backing_hd && bdrv_requests_pending(bs->backing_hd)) {
+ return true;
+ }
+ return false;
+}
+
+static bool bdrv_requests_pending_all(void)
+{
+ BlockDriverState *bs;
+ QTAILQ_FOREACH(bs, &bdrv_states, list) {
+ if (bdrv_requests_pending(bs)) {
+ return true;
+ }
+ }
+ return false;
+}
+
/*
* Wait for pending requests to complete across all BlockDriverStates
*
@@ -1435,27 +1473,22 @@
*/
void bdrv_drain_all(void)
{
+ /* Always run first iteration so any pending completion BHs run */
+ bool busy = true;
BlockDriverState *bs;
- bool busy;
- do {
- busy = qemu_aio_wait();
-
+ while (busy) {
/* FIXME: We do not have timer support here, so this is effectively
* a busy wait.
*/
QTAILQ_FOREACH(bs, &bdrv_states, list) {
- if (!qemu_co_queue_empty(&bs->throttled_reqs)) {
- qemu_co_queue_restart_all(&bs->throttled_reqs);
+ while (qemu_co_enter_next(&bs->throttled_reqs)) {
busy = true;
}
}
- } while (busy);
- /* If requests are still pending there is a bug somewhere */
- QTAILQ_FOREACH(bs, &bdrv_states, list) {
- assert(QLIST_EMPTY(&bs->tracked_requests));
- assert(qemu_co_queue_empty(&bs->throttled_reqs));
+ busy = bdrv_requests_pending_all();
+ busy |= aio_poll(qemu_get_aio_context(), busy);
}
}
@@ -1600,11 +1633,11 @@
assert(!bs->job);
assert(!bs->in_use);
+ bdrv_close(bs);
+
/* remove from list, if necessary */
bdrv_make_anon(bs);
- bdrv_close(bs);
-
g_free(bs);
}
@@ -2538,7 +2571,35 @@
}
}
- ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
+ if (!(bs->zero_beyond_eof && bs->growable)) {
+ ret = drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
+ } else {
+ /* Read zeros after EOF of growable BDSes */
+ int64_t len, total_sectors, max_nb_sectors;
+
+ len = bdrv_getlength(bs);
+ if (len < 0) {
+ ret = len;
+ goto out;
+ }
+
+ total_sectors = len >> BDRV_SECTOR_BITS;
+ max_nb_sectors = MAX(0, total_sectors - sector_num);
+ if (max_nb_sectors > 0) {
+ ret = drv->bdrv_co_readv(bs, sector_num,
+ MIN(nb_sectors, max_nb_sectors), qiov);
+ } else {
+ ret = 0;
+ }
+
+ /* Reading beyond end of file is supposed to produce zeroes */
+ if (ret == 0 && total_sectors < sector_num + nb_sectors) {
+ uint64_t offset = MAX(0, total_sectors - sector_num);
+ uint64_t bytes = (sector_num + nb_sectors - offset) *
+ BDRV_SECTOR_SIZE;
+ qemu_iovec_memset(qiov, offset * BDRV_SECTOR_SIZE, 0, bytes);
+ }
+ }
out:
tracked_request_end(&req);
@@ -3686,7 +3747,7 @@
double elapsed_time;
int bps_ret, iops_ret;
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (now > bs->slice_end) {
bs->slice_start = now;
bs->slice_end = now + BLOCK_IO_SLICE_TIME;
@@ -3706,7 +3767,7 @@
*wait = max_wait;
}
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (bs->slice_end < now + max_wait) {
bs->slice_end = now + max_wait;
}
diff --git a/block/backup.c b/block/backup.c
index 16105d4..e12b3b1 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -37,6 +37,7 @@
typedef struct BackupBlockJob {
BlockJob common;
BlockDriverState *target;
+ MirrorSyncMode sync_mode;
RateLimit limit;
BlockdevOnError on_source_error;
BlockdevOnError on_target_error;
@@ -247,40 +248,83 @@
bdrv_add_before_write_notifier(bs, &before_write);
- for (; start < end; start++) {
- bool error_is_read;
-
- if (block_job_is_cancelled(&job->common)) {
- break;
+ if (job->sync_mode == MIRROR_SYNC_MODE_NONE) {
+ while (!block_job_is_cancelled(&job->common)) {
+ /* Yield until the job is cancelled. We just let our before_write
+ * notify callback service CoW requests. */
+ job->common.busy = false;
+ qemu_coroutine_yield();
+ job->common.busy = true;
}
+ } else {
+ /* Both FULL and TOP SYNC_MODE's require copying.. */
+ for (; start < end; start++) {
+ bool error_is_read;
- /* we need to yield so that qemu_aio_flush() returns.
- * (without, VM does not reboot)
- */
- if (job->common.speed) {
- uint64_t delay_ns = ratelimit_calculate_delay(
- &job->limit, job->sectors_read);
- job->sectors_read = 0;
- block_job_sleep_ns(&job->common, rt_clock, delay_ns);
- } else {
- block_job_sleep_ns(&job->common, rt_clock, 0);
- }
-
- if (block_job_is_cancelled(&job->common)) {
- break;
- }
-
- ret = backup_do_cow(bs, start * BACKUP_SECTORS_PER_CLUSTER,
- BACKUP_SECTORS_PER_CLUSTER, &error_is_read);
- if (ret < 0) {
- /* Depending on error action, fail now or retry cluster */
- BlockErrorAction action =
- backup_error_action(job, error_is_read, -ret);
- if (action == BDRV_ACTION_REPORT) {
+ if (block_job_is_cancelled(&job->common)) {
break;
+ }
+
+ /* we need to yield so that qemu_aio_flush() returns.
+ * (without, VM does not reboot)
+ */
+ if (job->common.speed) {
+ uint64_t delay_ns = ratelimit_calculate_delay(
+ &job->limit, job->sectors_read);
+ job->sectors_read = 0;
+ block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, delay_ns);
} else {
- start--;
- continue;
+ block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, 0);
+ }
+
+ if (block_job_is_cancelled(&job->common)) {
+ break;
+ }
+
+ if (job->sync_mode == MIRROR_SYNC_MODE_TOP) {
+ int i, n;
+ int alloced = 0;
+
+ /* Check to see if these blocks are already in the
+ * backing file. */
+
+ for (i = 0; i < BACKUP_SECTORS_PER_CLUSTER;) {
+ /* bdrv_co_is_allocated() only returns true/false based
+ * on the first set of sectors it comes accross that
+ * are are all in the same state.
+ * For that reason we must verify each sector in the
+ * backup cluster length. We end up copying more than
+ * needed but at some point that is always the case. */
+ alloced =
+ bdrv_co_is_allocated(bs,
+ start * BACKUP_SECTORS_PER_CLUSTER + i,
+ BACKUP_SECTORS_PER_CLUSTER - i, &n);
+ i += n;
+
+ if (alloced == 1) {
+ break;
+ }
+ }
+
+ /* If the above loop never found any sectors that are in
+ * the topmost image, skip this backup. */
+ if (alloced == 0) {
+ continue;
+ }
+ }
+ /* FULL sync mode we copy the whole drive. */
+ ret = backup_do_cow(bs, start * BACKUP_SECTORS_PER_CLUSTER,
+ BACKUP_SECTORS_PER_CLUSTER, &error_is_read);
+ if (ret < 0) {
+ /* Depending on error action, fail now or retry cluster */
+ BlockErrorAction action =
+ backup_error_action(job, error_is_read, -ret);
+ if (action == BDRV_ACTION_REPORT) {
+ break;
+ } else {
+ start--;
+ continue;
+ }
}
}
}
@@ -300,7 +344,7 @@
}
void backup_start(BlockDriverState *bs, BlockDriverState *target,
- int64_t speed,
+ int64_t speed, MirrorSyncMode sync_mode,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
BlockDriverCompletionFunc *cb, void *opaque,
@@ -335,6 +379,7 @@
job->on_source_error = on_source_error;
job->on_target_error = on_target_error;
job->target = target;
+ job->sync_mode = sync_mode;
job->common.len = len;
job->common.co = qemu_coroutine_create(backup_run);
qemu_coroutine_enter(job->common.co, job);
diff --git a/block/commit.c b/block/commit.c
index 2227fc2..51a1ab3 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -103,7 +103,7 @@
/* Note that even when no rate limit is applied we need to yield
* with no pending I/O here so that bdrv_drain_all() returns.
*/
- block_job_sleep_ns(&s->common, rt_clock, delay_ns);
+ block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);
if (block_job_is_cancelled(&s->common)) {
break;
}
diff --git a/block/curl.c b/block/curl.c
index 82d39ff..e566855 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -86,7 +86,6 @@
static void curl_clean_state(CURLState *s);
static void curl_multi_do(void *arg);
-static int curl_aio_flush(void *opaque);
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
void *s, void *sp)
@@ -94,17 +93,16 @@
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
switch (action) {
case CURL_POLL_IN:
- qemu_aio_set_fd_handler(fd, curl_multi_do, NULL, curl_aio_flush, s);
+ qemu_aio_set_fd_handler(fd, curl_multi_do, NULL, s);
break;
case CURL_POLL_OUT:
- qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, curl_aio_flush, s);
+ qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, s);
break;
case CURL_POLL_INOUT:
- qemu_aio_set_fd_handler(fd, curl_multi_do, curl_multi_do,
- curl_aio_flush, s);
+ qemu_aio_set_fd_handler(fd, curl_multi_do, curl_multi_do, s);
break;
case CURL_POLL_REMOVE:
- qemu_aio_set_fd_handler(fd, NULL, NULL, NULL, NULL);
+ qemu_aio_set_fd_handler(fd, NULL, NULL, NULL);
break;
}
@@ -495,21 +493,6 @@
return -EINVAL;
}
-static int curl_aio_flush(void *opaque)
-{
- BDRVCURLState *s = opaque;
- int i, j;
-
- for (i=0; i < CURL_NUM_STATES; i++) {
- for(j=0; j < CURL_NUM_ACB; j++) {
- if (s->states[i].acb[j]) {
- return 1;
- }
- }
- }
- return 0;
-}
-
static void curl_aio_cancel(BlockDriverAIOCB *blockacb)
{
// Do we have to implement canceling? Seems to work without...
diff --git a/block/gluster.c b/block/gluster.c
index 6de418c..46f36f8 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -32,7 +32,6 @@
struct glfs *glfs;
int fds[2];
struct glfs_fd *fd;
- int qemu_aio_count;
int event_reader_pos;
GlusterAIOCB *event_acb;
} BDRVGlusterState;
@@ -247,7 +246,6 @@
ret = -EIO; /* Partial read/write - fail it */
}
- s->qemu_aio_count--;
qemu_aio_release(acb);
cb(opaque, ret);
if (finished) {
@@ -275,13 +273,6 @@
} while (ret < 0 && errno == EINTR);
}
-static int qemu_gluster_aio_flush_cb(void *opaque)
-{
- BDRVGlusterState *s = opaque;
-
- return (s->qemu_aio_count > 0);
-}
-
/* TODO Convert to fine grained options */
static QemuOptsList runtime_opts = {
.name = "gluster",
@@ -348,7 +339,7 @@
}
fcntl(s->fds[GLUSTER_FD_READ], F_SETFL, O_NONBLOCK);
qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ],
- qemu_gluster_aio_event_reader, NULL, qemu_gluster_aio_flush_cb, s);
+ qemu_gluster_aio_event_reader, NULL, s);
out:
qemu_opts_del(opts);
@@ -445,11 +436,9 @@
qemu_mutex_lock_iothread(); /* We are in gluster thread context */
acb->common.cb(acb->common.opaque, -EIO);
qemu_aio_release(acb);
- s->qemu_aio_count--;
close(s->fds[GLUSTER_FD_READ]);
close(s->fds[GLUSTER_FD_WRITE]);
- qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL,
- NULL);
+ qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL);
bs->drv = NULL; /* Make the disk inaccessible */
qemu_mutex_unlock_iothread();
}
@@ -467,7 +456,6 @@
offset = sector_num * BDRV_SECTOR_SIZE;
size = nb_sectors * BDRV_SECTOR_SIZE;
- s->qemu_aio_count++;
acb = qemu_aio_get(&gluster_aiocb_info, bs, cb, opaque);
acb->size = size;
@@ -488,11 +476,23 @@
return &acb->common;
out:
- s->qemu_aio_count--;
qemu_aio_release(acb);
return NULL;
}
+static int qemu_gluster_truncate(BlockDriverState *bs, int64_t offset)
+{
+ int ret;
+ BDRVGlusterState *s = bs->opaque;
+
+ ret = glfs_ftruncate(s->fd, offset);
+ if (ret < 0) {
+ return -errno;
+ }
+
+ return 0;
+}
+
static BlockDriverAIOCB *qemu_gluster_aio_readv(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
@@ -518,7 +518,6 @@
acb->size = 0;
acb->ret = 0;
acb->finished = NULL;
- s->qemu_aio_count++;
ret = glfs_fsync_async(s->fd, &gluster_finish_aiocb, acb);
if (ret < 0) {
@@ -527,7 +526,6 @@
return &acb->common;
out:
- s->qemu_aio_count--;
qemu_aio_release(acb);
return NULL;
}
@@ -550,7 +548,6 @@
acb->size = 0;
acb->ret = 0;
acb->finished = NULL;
- s->qemu_aio_count++;
ret = glfs_discard_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
if (ret < 0) {
@@ -559,7 +556,6 @@
return &acb->common;
out:
- s->qemu_aio_count--;
qemu_aio_release(acb);
return NULL;
}
@@ -598,7 +594,7 @@
close(s->fds[GLUSTER_FD_READ]);
close(s->fds[GLUSTER_FD_WRITE]);
- qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL, NULL);
+ qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL);
if (s->fd) {
glfs_close(s->fd);
@@ -631,6 +627,7 @@
.bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
+ .bdrv_truncate = qemu_gluster_truncate,
.bdrv_aio_readv = qemu_gluster_aio_readv,
.bdrv_aio_writev = qemu_gluster_aio_writev,
.bdrv_aio_flush = qemu_gluster_aio_flush,
@@ -650,6 +647,7 @@
.bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
+ .bdrv_truncate = qemu_gluster_truncate,
.bdrv_aio_readv = qemu_gluster_aio_readv,
.bdrv_aio_writev = qemu_gluster_aio_writev,
.bdrv_aio_flush = qemu_gluster_aio_flush,
@@ -669,6 +667,7 @@
.bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
+ .bdrv_truncate = qemu_gluster_truncate,
.bdrv_aio_readv = qemu_gluster_aio_readv,
.bdrv_aio_writev = qemu_gluster_aio_writev,
.bdrv_aio_flush = qemu_gluster_aio_flush,
@@ -688,6 +687,7 @@
.bdrv_create = qemu_gluster_create,
.bdrv_getlength = qemu_gluster_getlength,
.bdrv_get_allocated_file_size = qemu_gluster_allocated_file_size,
+ .bdrv_truncate = qemu_gluster_truncate,
.bdrv_aio_readv = qemu_gluster_aio_readv,
.bdrv_aio_writev = qemu_gluster_aio_writev,
.bdrv_aio_flush = qemu_gluster_aio_flush,
diff --git a/block/iscsi.c b/block/iscsi.c
index 5f28c6a..2bbee1f 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -146,13 +146,6 @@
static void iscsi_process_read(void *arg);
static void iscsi_process_write(void *arg);
-static int iscsi_process_flush(void *arg)
-{
- IscsiLun *iscsilun = arg;
-
- return iscsi_queue_length(iscsilun->iscsi) > 0;
-}
-
static void
iscsi_set_events(IscsiLun *iscsilun)
{
@@ -166,7 +159,6 @@
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
iscsi_process_read,
(ev & POLLOUT) ? iscsi_process_write : NULL,
- iscsi_process_flush,
iscsilun);
}
@@ -247,7 +239,9 @@
{
if ((sector_num * BDRV_SECTOR_SIZE) % iscsilun->block_size ||
(nb_sectors * BDRV_SECTOR_SIZE) % iscsilun->block_size) {
- error_report("iSCSI misaligned request: iscsilun->block_size %u, sector_num %ld, nb_sectors %d",
+ error_report("iSCSI misaligned request: "
+ "iscsilun->block_size %u, sector_num %" PRIi64
+ ", nb_sectors %d",
iscsilun->block_size, sector_num, nb_sectors);
return 0;
}
@@ -966,7 +960,7 @@
return;
}
- qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL);
+ timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
iscsi_set_events(iscsilun);
}
#endif
@@ -1179,8 +1173,8 @@
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
/* Set up a timer for sending out iSCSI NOPs */
- iscsilun->nop_timer = qemu_new_timer_ms(rt_clock, iscsi_nop_timed_event, iscsilun);
- qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL);
+ iscsilun->nop_timer = timer_new_ms(QEMU_CLOCK_REALTIME, iscsi_nop_timed_event, iscsilun);
+ timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
#endif
out:
@@ -1210,10 +1204,10 @@
struct iscsi_context *iscsi = iscsilun->iscsi;
if (iscsilun->nop_timer) {
- qemu_del_timer(iscsilun->nop_timer);
- qemu_free_timer(iscsilun->nop_timer);
+ timer_del(iscsilun->nop_timer);
+ timer_free(iscsilun->nop_timer);
}
- qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL, NULL);
+ qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL);
iscsi_destroy_context(iscsi);
memset(iscsilun, 0, sizeof(IscsiLun));
}
@@ -1273,8 +1267,8 @@
goto out;
}
if (iscsilun->nop_timer) {
- qemu_del_timer(iscsilun->nop_timer);
- qemu_free_timer(iscsilun->nop_timer);
+ timer_del(iscsilun->nop_timer);
+ timer_free(iscsilun->nop_timer);
}
if (iscsilun->type != TYPE_DISK) {
ret = -ENODEV;
diff --git a/block/linux-aio.c b/block/linux-aio.c
index ee0f8d1..53434e2 100644
--- a/block/linux-aio.c
+++ b/block/linux-aio.c
@@ -39,7 +39,6 @@
struct qemu_laio_state {
io_context_t ctx;
EventNotifier e;
- int count;
};
static inline ssize_t io_event_ret(struct io_event *ev)
@@ -55,8 +54,6 @@
{
int ret;
- s->count--;
-
ret = laiocb->ret;
if (ret != -ECANCELED) {
if (ret == laiocb->nbytes) {
@@ -101,13 +98,6 @@
}
}
-static int qemu_laio_flush_cb(EventNotifier *e)
-{
- struct qemu_laio_state *s = container_of(e, struct qemu_laio_state, e);
-
- return (s->count > 0) ? 1 : 0;
-}
-
static void laio_cancel(BlockDriverAIOCB *blockacb)
{
struct qemu_laiocb *laiocb = (struct qemu_laiocb *)blockacb;
@@ -177,14 +167,11 @@
goto out_free_aiocb;
}
io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e));
- s->count++;
if (io_submit(s->ctx, 1, &iocbs) < 0)
- goto out_dec_count;
+ goto out_free_aiocb;
return &laiocb->common;
-out_dec_count:
- s->count--;
out_free_aiocb:
qemu_aio_release(laiocb);
return NULL;
@@ -203,8 +190,7 @@
goto out_close_efd;
}
- qemu_aio_set_event_notifier(&s->e, qemu_laio_completion_cb,
- qemu_laio_flush_cb);
+ qemu_aio_set_event_notifier(&s->e, qemu_laio_completion_cb);
return s;
diff --git a/block/mirror.c b/block/mirror.c
index bed4a7e..86de458 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -356,7 +356,7 @@
}
bdrv_dirty_iter_init(bs, &s->hbi);
- last_pause_ns = qemu_get_clock_ns(rt_clock);
+ last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
for (;;) {
uint64_t delay_ns;
int64_t cnt;
@@ -374,7 +374,7 @@
* We do so every SLICE_TIME nanoseconds, or when there is an error,
* or when the source is clean, whichever comes first.
*/
- if (qemu_get_clock_ns(rt_clock) - last_pause_ns < SLICE_TIME &&
+ if (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - last_pause_ns < SLICE_TIME &&
s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
if (s->in_flight == MAX_IN_FLIGHT || s->buf_free_count == 0 ||
(cnt == 0 && s->in_flight > 0)) {
@@ -439,13 +439,13 @@
delay_ns = 0;
}
- block_job_sleep_ns(&s->common, rt_clock, delay_ns);
+ block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);
if (block_job_is_cancelled(&s->common)) {
break;
}
} else if (!should_complete) {
delay_ns = (s->in_flight == 0 && cnt == 0 ? SLICE_TIME : 0);
- block_job_sleep_ns(&s->common, rt_clock, delay_ns);
+ block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);
} else if (cnt == 0) {
/* The two disks are in sync. Exit and report successful
* completion.
@@ -454,7 +454,7 @@
s->common.cancelled = false;
break;
}
- last_pause_ns = qemu_get_clock_ns(rt_clock);
+ last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
}
immediate_exit:
diff --git a/block/nbd.c b/block/nbd.c
index 9c480b8..691066f 100644
--- a/block/nbd.c
+++ b/block/nbd.c
@@ -279,13 +279,6 @@
request->handle = INDEX_TO_HANDLE(s, i);
}
-static int nbd_have_request(void *opaque)
-{
- BDRVNBDState *s = opaque;
-
- return s->in_flight > 0;
-}
-
static void nbd_reply_ready(void *opaque)
{
BDRVNBDState *s = opaque;
@@ -341,8 +334,7 @@
qemu_co_mutex_lock(&s->send_mutex);
s->send_coroutine = qemu_coroutine_self();
- qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write,
- nbd_have_request, s);
+ qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write, s);
if (qiov) {
if (!s->is_unix) {
socket_set_cork(s->sock, 1);
@@ -361,8 +353,7 @@
} else {
rc = nbd_send_request(s->sock, request);
}
- qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL,
- nbd_have_request, s);
+ qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL, s);
s->send_coroutine = NULL;
qemu_co_mutex_unlock(&s->send_mutex);
return rc;
@@ -438,8 +429,7 @@
/* Now that we're connected, set the socket to be non-blocking and
* kick the reply mechanism. */
qemu_set_nonblock(sock);
- qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL,
- nbd_have_request, s);
+ qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL, s);
s->sock = sock;
s->size = size;
@@ -459,7 +449,7 @@
request.len = 0;
nbd_send_request(s->sock, &request);
- qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL, NULL);
+ qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL);
closesocket(s->sock);
}
diff --git a/block/qcow2.c b/block/qcow2.c
index 0eceefe..78097e5 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -291,7 +291,7 @@
.head = QTAILQ_HEAD_INITIALIZER(qcow2_runtime_opts.head),
.desc = {
{
- .name = "lazy_refcounts",
+ .name = QCOW2_OPT_LAZY_REFCOUNTS,
.type = QEMU_OPT_BOOL,
.help = "Postpone refcount updates",
},
@@ -1402,7 +1402,7 @@
int flags = 0;
size_t cluster_size = DEFAULT_CLUSTER_SIZE;
int prealloc = 0;
- int version = 2;
+ int version = 3;
/* Read out options */
while (options && options->name) {
@@ -1722,12 +1722,15 @@
{
BDRVQcowState *s = bs->opaque;
int growable = bs->growable;
+ bool zero_beyond_eof = bs->zero_beyond_eof;
int ret;
BLKDBG_EVENT(bs->file, BLKDBG_VMSTATE_LOAD);
bs->growable = 1;
+ bs->zero_beyond_eof = false;
ret = bdrv_pread(bs, qcow2_vm_state_offset(s) + pos, buf, size);
bs->growable = growable;
+ bs->zero_beyond_eof = zero_beyond_eof;
return ret;
}
diff --git a/block/qcow2.h b/block/qcow2.h
index 3b2d5cd..dba9771 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -59,10 +59,10 @@
#define DEFAULT_CLUSTER_SIZE 65536
-#define QCOW2_OPT_LAZY_REFCOUNTS "lazy_refcounts"
-#define QCOW2_OPT_DISCARD_REQUEST "pass_discard_request"
-#define QCOW2_OPT_DISCARD_SNAPSHOT "pass_discard_snapshot"
-#define QCOW2_OPT_DISCARD_OTHER "pass_discard_other"
+#define QCOW2_OPT_LAZY_REFCOUNTS "lazy-refcounts"
+#define QCOW2_OPT_DISCARD_REQUEST "pass-discard-request"
+#define QCOW2_OPT_DISCARD_SNAPSHOT "pass-discard-snapshot"
+#define QCOW2_OPT_DISCARD_OTHER "pass-discard-other"
typedef struct QCowHeader {
uint32_t magic;
diff --git a/block/qed.c b/block/qed.c
index f767b05..cc904c4 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -353,10 +353,10 @@
{
trace_qed_start_need_check_timer(s);
- /* Use vm_clock so we don't alter the image file while suspended for
+ /* Use QEMU_CLOCK_VIRTUAL so we don't alter the image file while suspended for
* migration.
*/
- qemu_mod_timer(s->need_check_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(s->need_check_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
get_ticks_per_sec() * QED_NEED_CHECK_TIMEOUT);
}
@@ -364,7 +364,7 @@
static void qed_cancel_need_check_timer(BDRVQEDState *s)
{
trace_qed_cancel_need_check_timer(s);
- qemu_del_timer(s->need_check_timer);
+ timer_del(s->need_check_timer);
}
static void bdrv_qed_rebind(BlockDriverState *bs)
@@ -494,7 +494,7 @@
}
}
- s->need_check_timer = qemu_new_timer_ns(vm_clock,
+ s->need_check_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
qed_need_check_timer_cb, s);
out:
@@ -518,7 +518,7 @@
BDRVQEDState *s = bs->opaque;
qed_cancel_need_check_timer(s);
- qemu_free_timer(s->need_check_timer);
+ timer_free(s->need_check_timer);
/* Ensure writes reach stable storage */
bdrv_flush(bs->file);
diff --git a/block/raw.c b/block/raw.c
index f1682d4..4751825 100644
--- a/block/raw.c
+++ b/block/raw.c
@@ -1,3 +1,26 @@
+/*
+ * Block driver for RAW format
+ *
+ * Copyright (c) 2006 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.
+ */
#include "qemu-common.h"
#include "block/block_int.h"
diff --git a/block/rbd.c b/block/rbd.c
index cb71751..e798e19 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -100,7 +100,6 @@
rados_ioctx_t io_ctx;
rbd_image_t image;
char name[RBD_MAX_IMAGE_NAME_SIZE];
- int qemu_aio_count;
char *snap;
int event_reader_pos;
RADOSCB *event_rcb;
@@ -428,19 +427,11 @@
if (s->event_reader_pos == sizeof(s->event_rcb)) {
s->event_reader_pos = 0;
qemu_rbd_complete_aio(s->event_rcb);
- s->qemu_aio_count--;
}
}
} while (ret < 0 && errno == EINTR);
}
-static int qemu_rbd_aio_flush_cb(void *opaque)
-{
- BDRVRBDState *s = opaque;
-
- return (s->qemu_aio_count > 0);
-}
-
/* TODO Convert to fine grained options */
static QemuOptsList runtime_opts = {
.name = "rbd",
@@ -554,7 +545,7 @@
fcntl(s->fds[0], F_SETFL, O_NONBLOCK);
fcntl(s->fds[1], F_SETFL, O_NONBLOCK);
qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], qemu_rbd_aio_event_reader,
- NULL, qemu_rbd_aio_flush_cb, s);
+ NULL, s);
qemu_opts_del(opts);
@@ -578,7 +569,7 @@
close(s->fds[0]);
close(s->fds[1]);
- qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], NULL, NULL, NULL, NULL);
+ qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], NULL, NULL, NULL);
rbd_close(s->image);
rados_ioctx_destroy(s->io_ctx);
@@ -741,8 +732,6 @@
off = sector_num * BDRV_SECTOR_SIZE;
size = nb_sectors * BDRV_SECTOR_SIZE;
- s->qemu_aio_count++; /* All the RADOSCB */
-
rcb = g_malloc(sizeof(RADOSCB));
rcb->done = 0;
rcb->acb = acb;
@@ -779,7 +768,6 @@
failed:
g_free(rcb);
- s->qemu_aio_count--;
qemu_aio_release(acb);
return NULL;
}
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 6a41ad9..1ad4d07 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -242,14 +242,14 @@
return !!inode->snap_ctime;
}
-#undef dprintf
+#undef DPRINTF
#ifdef DEBUG_SDOG
-#define dprintf(fmt, args...) \
+#define DPRINTF(fmt, args...) \
do { \
fprintf(stdout, "%s %d: " fmt, __func__, __LINE__, ##args); \
} while (0)
#else
-#define dprintf(fmt, args...)
+#define DPRINTF(fmt, args...)
#endif
typedef struct SheepdogAIOCB SheepdogAIOCB;
@@ -509,13 +509,6 @@
qemu_coroutine_enter(co, NULL);
}
-static int have_co_req(void *opaque)
-{
- /* this handler is set only when there is a pending request, so
- * always returns 1. */
- return 1;
-}
-
typedef struct SheepdogReqCo {
int sockfd;
SheepdogReq *hdr;
@@ -538,14 +531,14 @@
unsigned int *rlen = srco->rlen;
co = qemu_coroutine_self();
- qemu_aio_set_fd_handler(sockfd, NULL, restart_co_req, have_co_req, co);
+ qemu_aio_set_fd_handler(sockfd, NULL, restart_co_req, co);
ret = send_co_req(sockfd, hdr, data, wlen);
if (ret < 0) {
goto out;
}
- qemu_aio_set_fd_handler(sockfd, restart_co_req, NULL, have_co_req, co);
+ qemu_aio_set_fd_handler(sockfd, restart_co_req, NULL, co);
ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
if (ret < sizeof(*hdr)) {
@@ -570,7 +563,7 @@
out:
/* there is at most one request for this sockfd, so it is safe to
* set each handler to NULL. */
- qemu_aio_set_fd_handler(sockfd, NULL, NULL, NULL, NULL);
+ qemu_aio_set_fd_handler(sockfd, NULL, NULL, NULL);
srco->ret = ret;
srco->finished = true;
@@ -729,7 +722,7 @@
break;
case AIOCB_FLUSH_CACHE:
if (rsp.result == SD_RES_INVALID_PARMS) {
- dprintf("disable cache since the server doesn't support it\n");
+ DPRINTF("disable cache since the server doesn't support it\n");
s->cache_flags = SD_FLAG_CMD_DIRECT;
rsp.result = SD_RES_SUCCESS;
}
@@ -796,14 +789,6 @@
qemu_coroutine_enter(s->co_send, NULL);
}
-static int aio_flush_request(void *opaque)
-{
- BDRVSheepdogState *s = opaque;
-
- return !QLIST_EMPTY(&s->inflight_aio_head) ||
- !QLIST_EMPTY(&s->pending_aio_head);
-}
-
/*
* Return a socket discriptor to read/write objects.
*
@@ -819,7 +804,7 @@
return fd;
}
- qemu_aio_set_fd_handler(fd, co_read_response, NULL, aio_flush_request, s);
+ qemu_aio_set_fd_handler(fd, co_read_response, NULL, s);
return fd;
}
@@ -1069,8 +1054,7 @@
qemu_co_mutex_lock(&s->lock);
s->co_send = qemu_coroutine_self();
- qemu_aio_set_fd_handler(s->fd, co_read_response, co_write_request,
- aio_flush_request, s);
+ qemu_aio_set_fd_handler(s->fd, co_read_response, co_write_request, s);
socket_set_cork(s->fd, 1);
/* send a header */
@@ -1091,8 +1075,7 @@
}
socket_set_cork(s->fd, 0);
- qemu_aio_set_fd_handler(s->fd, co_read_response, NULL,
- aio_flush_request, s);
+ qemu_aio_set_fd_handler(s->fd, co_read_response, NULL, s);
qemu_co_mutex_unlock(&s->lock);
return 0;
@@ -1229,7 +1212,7 @@
* the same object */
QLIST_FOREACH(areq, &s->inflight_aio_head, aio_siblings) {
if (areq != aio_req && areq->oid == aio_req->oid) {
- dprintf("simultaneous CoW to %" PRIx64 "\n", aio_req->oid);
+ DPRINTF("simultaneous CoW to %" PRIx64 "\n", aio_req->oid);
QLIST_REMOVE(aio_req, aio_siblings);
QLIST_INSERT_HEAD(&s->pending_aio_head, aio_req, aio_siblings);
return SD_RES_SUCCESS;
@@ -1319,7 +1302,7 @@
s->discard_supported = true;
if (snapid || tag[0] != '\0') {
- dprintf("%" PRIx32 " snapshot inode was open.\n", vid);
+ DPRINTF("%" PRIx32 " snapshot inode was open.\n", vid);
s->is_snapshot = true;
}
@@ -1350,7 +1333,7 @@
g_free(buf);
return 0;
out:
- qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL);
+ qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
if (s->fd >= 0) {
closesocket(s->fd);
}
@@ -1554,7 +1537,7 @@
unsigned int wlen, rlen = 0;
int fd, ret;
- dprintf("%s\n", s->name);
+ DPRINTF("%s\n", s->name);
fd = connect_to_sdog(s);
if (fd < 0) {
@@ -1578,7 +1561,7 @@
error_report("%s, %s", sd_strerror(rsp->result), s->name);
}
- qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL);
+ qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
closesocket(s->fd);
g_free(s->host_spec);
}
@@ -1714,7 +1697,7 @@
char *buf;
bool deleted;
- dprintf("%" PRIx32 " is snapshot.\n", s->inode.vdi_id);
+ DPRINTF("%" PRIx32 " is snapshot.\n", s->inode.vdi_id);
buf = g_malloc(SD_INODE_SIZE);
@@ -1730,7 +1713,7 @@
goto out;
}
- dprintf("%" PRIx32 " is created.\n", vid);
+ DPRINTF("%" PRIx32 " is created.\n", vid);
fd = connect_to_sdog(s);
if (fd < 0) {
@@ -1751,7 +1734,7 @@
s->is_snapshot = false;
ret = 0;
- dprintf("%" PRIx32 " was newly created.\n", s->inode.vdi_id);
+ DPRINTF("%" PRIx32 " was newly created.\n", s->inode.vdi_id);
out:
g_free(buf);
@@ -1841,11 +1824,11 @@
}
if (create) {
- dprintf("update ino (%" PRIu32 ") %" PRIu64 " %" PRIu64 " %ld\n",
+ DPRINTF("update ino (%" PRIu32 ") %" PRIu64 " %" PRIu64 " %ld\n",
inode->vdi_id, oid,
vid_to_data_oid(inode->data_vdi_id[idx], idx), idx);
oid = vid_to_data_oid(inode->vdi_id, idx);
- dprintf("new oid %" PRIx64 "\n", oid);
+ DPRINTF("new oid %" PRIx64 "\n", oid);
}
aio_req = alloc_aio_req(s, acb, oid, len, offset, flags, old_oid, done);
@@ -1978,7 +1961,7 @@
SheepdogInode *inode;
unsigned int datalen;
- dprintf("sn_info: name %s id_str %s s: name %s vm_state_size %" PRId64 " "
+ DPRINTF("sn_info: name %s id_str %s s: name %s vm_state_size %" PRId64 " "
"is_snapshot %d\n", sn_info->name, sn_info->id_str,
s->name, sn_info->vm_state_size, s->is_snapshot);
@@ -1989,7 +1972,7 @@
return -EINVAL;
}
- dprintf("%s %s\n", sn_info->name, sn_info->id_str);
+ DPRINTF("%s %s\n", sn_info->name, sn_info->id_str);
s->inode.vm_state_size = sn_info->vm_state_size;
s->inode.vm_clock_nsec = sn_info->vm_clock_nsec;
@@ -2033,7 +2016,7 @@
}
memcpy(&s->inode, inode, datalen);
- dprintf("s->inode: name %s snap_id %x oid %x\n",
+ DPRINTF("s->inode: name %s snap_id %x oid %x\n",
s->inode.name, s->inode.snap_id, s->inode.vdi_id);
cleanup:
@@ -2347,6 +2330,7 @@
.bdrv_file_open = sd_open,
.bdrv_close = sd_close,
.bdrv_create = sd_create,
+ .bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_getlength = sd_getlength,
.bdrv_truncate = sd_truncate,
@@ -2374,6 +2358,7 @@
.bdrv_file_open = sd_open,
.bdrv_close = sd_close,
.bdrv_create = sd_create,
+ .bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_getlength = sd_getlength,
.bdrv_truncate = sd_truncate,
diff --git a/block/ssh.c b/block/ssh.c
index d7e7bf8..27691b4 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -740,14 +740,6 @@
qemu_coroutine_enter(co, NULL);
}
-/* Always true because when we have called set_fd_handler there is
- * always a request being processed.
- */
-static int return_true(void *opaque)
-{
- return 1;
-}
-
static coroutine_fn void set_fd_handler(BDRVSSHState *s)
{
int r;
@@ -766,13 +758,13 @@
DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s->sock,
rd_handler, wr_handler);
- qemu_aio_set_fd_handler(s->sock, rd_handler, wr_handler, return_true, co);
+ qemu_aio_set_fd_handler(s->sock, rd_handler, wr_handler, co);
}
static coroutine_fn void clear_fd_handler(BDRVSSHState *s)
{
DPRINTF("s->sock=%d", s->sock);
- qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL, NULL);
+ qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL);
}
/* A non-blocking call returned EAGAIN, so yield, ensuring the
diff --git a/block/stream.c b/block/stream.c
index 7fe9e48..9982125 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -57,6 +57,11 @@
BlockDriverState *intermediate;
intermediate = top->backing_hd;
+ /* Must assign before bdrv_delete() to prevent traversing dangling pointer
+ * while we delete backing image instances.
+ */
+ top->backing_hd = base;
+
while (intermediate) {
BlockDriverState *unused;
@@ -70,7 +75,6 @@
unused->backing_hd = NULL;
bdrv_delete(unused);
}
- top->backing_hd = base;
}
static void coroutine_fn stream_run(void *opaque)
@@ -110,7 +114,7 @@
/* Note that even when no rate limit is applied we need to yield
* with no pending I/O here so that bdrv_drain_all() returns.
*/
- block_job_sleep_ns(&s->common, rt_clock, delay_ns);
+ block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns);
if (block_job_is_cancelled(&s->common)) {
break;
}
diff --git a/block/vhdx.h b/block/vhdx.h
index c3b64c6..fb687ed 100644
--- a/block/vhdx.h
+++ b/block/vhdx.h
@@ -168,7 +168,7 @@
vhdx_header. If not found in
vhdx_header, it is invalid */
uint64_t flushed_file_offset; /* see spec for full details - this
- sould be vhdx file size in bytes */
+ should be vhdx file size in bytes */
uint64_t last_file_offset; /* size in bytes that all allocated
file structures fit into */
} VHDXLogEntryHeader;
diff --git a/block/vmdk.c b/block/vmdk.c
index 3756333..63b489d 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -62,19 +62,20 @@
uint32_t cylinders;
uint32_t heads;
uint32_t sectors_per_track;
-} VMDK3Header;
+} QEMU_PACKED VMDK3Header;
typedef struct {
uint32_t version;
uint32_t flags;
- int64_t capacity;
- int64_t granularity;
- int64_t desc_offset;
- int64_t desc_size;
- int32_t num_gtes_per_gte;
- int64_t rgd_offset;
- int64_t gd_offset;
- int64_t grain_offset;
+ uint64_t capacity;
+ uint64_t granularity;
+ uint64_t desc_offset;
+ uint64_t desc_size;
+ /* Number of GrainTableEntries per GrainTable */
+ uint32_t num_gtes_per_gt;
+ uint64_t rgd_offset;
+ uint64_t gd_offset;
+ uint64_t grain_offset;
char filler[1];
char check_bytes[4];
uint16_t compressAlgorithm;
@@ -109,7 +110,7 @@
typedef struct BDRVVmdkState {
CoMutex lock;
- int desc_offset;
+ uint64_t desc_offset;
bool cid_updated;
uint32_t parent_cid;
int num_extents;
@@ -131,7 +132,7 @@
uint64_t lba;
uint32_t size;
uint8_t data[0];
-} VmdkGrainMarker;
+} QEMU_PACKED VmdkGrainMarker;
enum {
MARKER_END_OF_STREAM = 0,
@@ -385,15 +386,30 @@
/* Create and append extent to the extent array. Return the added VmdkExtent
* address. return NULL if allocation failed. */
-static VmdkExtent *vmdk_add_extent(BlockDriverState *bs,
+static int vmdk_add_extent(BlockDriverState *bs,
BlockDriverState *file, bool flat, int64_t sectors,
int64_t l1_offset, int64_t l1_backup_offset,
uint32_t l1_size,
- int l2_size, unsigned int cluster_sectors)
+ int l2_size, uint64_t cluster_sectors,
+ VmdkExtent **new_extent)
{
VmdkExtent *extent;
BDRVVmdkState *s = bs->opaque;
+ if (cluster_sectors > 0x200000) {
+ /* 0x200000 * 512Bytes = 1GB for one cluster is unrealistic */
+ error_report("invalid granularity, image may be corrupt");
+ return -EINVAL;
+ }
+ if (l1_size > 512 * 1024 * 1024) {
+ /* Although with big capacity and small l1_entry_sectors, we can get a
+ * big l1_size, we don't want unbounded value to allocate the table.
+ * Limit it to 512M, which is 16PB for default cluster and L2 table
+ * size */
+ error_report("L1 size too big");
+ return -EFBIG;
+ }
+
s->extents = g_realloc(s->extents,
(s->num_extents + 1) * sizeof(VmdkExtent));
extent = &s->extents[s->num_extents];
@@ -416,7 +432,10 @@
extent->end_sector = extent->sectors;
}
bs->total_sectors = extent->end_sector;
- return extent;
+ if (new_extent) {
+ *new_extent = extent;
+ }
+ return 0;
}
static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent)
@@ -462,9 +481,9 @@
return ret;
}
-static int vmdk_open_vmdk3(BlockDriverState *bs,
- BlockDriverState *file,
- int flags)
+static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
+ BlockDriverState *file,
+ int flags)
{
int ret;
uint32_t magic;
@@ -475,12 +494,17 @@
if (ret < 0) {
return ret;
}
- extent = vmdk_add_extent(bs,
- bs->file, false,
- le32_to_cpu(header.disk_sectors),
- le32_to_cpu(header.l1dir_offset) << 9,
- 0, 1 << 6, 1 << 9,
- le32_to_cpu(header.granularity));
+ ret = vmdk_add_extent(bs, file, false,
+ le32_to_cpu(header.disk_sectors),
+ le32_to_cpu(header.l1dir_offset) << 9,
+ 0,
+ le32_to_cpu(header.l1dir_size),
+ 4096,
+ le32_to_cpu(header.granularity),
+ &extent);
+ if (ret < 0) {
+ return ret;
+ }
ret = vmdk_init_tables(bs, extent);
if (ret) {
/* free extent allocated by vmdk_add_extent */
@@ -490,7 +514,7 @@
}
static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
- int64_t desc_offset);
+ uint64_t desc_offset);
static int vmdk_open_vmdk4(BlockDriverState *bs,
BlockDriverState *file,
@@ -508,7 +532,7 @@
return ret;
}
if (header.capacity == 0) {
- int64_t desc_offset = le64_to_cpu(header.desc_offset);
+ uint64_t desc_offset = le64_to_cpu(header.desc_offset);
if (desc_offset) {
return vmdk_open_desc_file(bs, flags, desc_offset << 9);
}
@@ -570,7 +594,12 @@
return -ENOTSUP;
}
- l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
+ if (le32_to_cpu(header.num_gtes_per_gt) > 512) {
+ error_report("L2 table size too big");
+ return -EINVAL;
+ }
+
+ l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gt)
* le64_to_cpu(header.granularity);
if (l1_entry_sectors == 0) {
return -EINVAL;
@@ -580,13 +609,17 @@
if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) {
l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9;
}
- extent = vmdk_add_extent(bs, file, false,
+ ret = vmdk_add_extent(bs, file, false,
le64_to_cpu(header.capacity),
le64_to_cpu(header.gd_offset) << 9,
l1_backup_offset,
l1_size,
- le32_to_cpu(header.num_gtes_per_gte),
- le64_to_cpu(header.granularity));
+ le32_to_cpu(header.num_gtes_per_gt),
+ le64_to_cpu(header.granularity),
+ &extent);
+ if (ret < 0) {
+ return ret;
+ }
extent->compressed =
le16_to_cpu(header.compressAlgorithm) == VMDK4_COMPRESSION_DEFLATE;
extent->has_marker = le32_to_cpu(header.flags) & VMDK4_FLAG_MARKER;
@@ -641,7 +674,7 @@
magic = be32_to_cpu(magic);
switch (magic) {
case VMDK3_MAGIC:
- return vmdk_open_vmdk3(bs, file, flags);
+ return vmdk_open_vmfs_sparse(bs, file, flags);
break;
case VMDK4_MAGIC:
return vmdk_open_vmdk4(bs, file, flags);
@@ -685,7 +718,8 @@
}
if (sectors <= 0 ||
- (strcmp(type, "FLAT") && strcmp(type, "SPARSE")) ||
+ (strcmp(type, "FLAT") && strcmp(type, "SPARSE") &&
+ strcmp(type, "VMFS") && strcmp(type, "VMFSSPARSE")) ||
(strcmp(access, "RW"))) {
goto next_line;
}
@@ -698,15 +732,18 @@
}
/* save to extents array */
- if (!strcmp(type, "FLAT")) {
+ if (!strcmp(type, "FLAT") || !strcmp(type, "VMFS")) {
/* FLAT extent */
VmdkExtent *extent;
- extent = vmdk_add_extent(bs, extent_file, true, sectors,
- 0, 0, 0, 0, sectors);
+ ret = vmdk_add_extent(bs, extent_file, true, sectors,
+ 0, 0, 0, 0, sectors, &extent);
+ if (ret < 0) {
+ return ret;
+ }
extent->flat_start_offset = flat_offset << 9;
- } else if (!strcmp(type, "SPARSE")) {
- /* SPARSE extent */
+ } else if (!strcmp(type, "SPARSE") || !strcmp(type, "VMFSSPARSE")) {
+ /* SPARSE extent and VMFSSPARSE extent are both "COWD" sparse file*/
ret = vmdk_open_sparse(bs, extent_file, bs->open_flags);
if (ret) {
bdrv_delete(extent_file);
@@ -728,7 +765,7 @@
}
static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
- int64_t desc_offset)
+ uint64_t desc_offset)
{
int ret;
char *buf = NULL;
@@ -753,6 +790,8 @@
goto exit;
}
if (strcmp(ct, "monolithicFlat") &&
+ strcmp(ct, "vmfs") &&
+ strcmp(ct, "vmfsSparse") &&
strcmp(ct, "twoGbMaxExtentSparse") &&
strcmp(ct, "twoGbMaxExtentFlat")) {
fprintf(stderr,
@@ -807,16 +846,17 @@
uint64_t offset,
bool allocate)
{
- /* 128 sectors * 512 bytes each = grain size 64KB */
- uint8_t whole_grain[extent->cluster_sectors * 512];
+ int ret = VMDK_OK;
+ uint8_t *whole_grain = NULL;
/* we will be here if it's first write on non-exist grain(cluster).
* try to read from parent image, if exist */
if (bs->backing_hd) {
- int ret;
-
+ whole_grain =
+ qemu_blockalign(bs, extent->cluster_sectors << BDRV_SECTOR_BITS);
if (!vmdk_is_cid_valid(bs)) {
- return VMDK_ERROR;
+ ret = VMDK_ERROR;
+ goto exit;
}
/* floor offset to cluster */
@@ -824,17 +864,21 @@
ret = bdrv_read(bs->backing_hd, offset >> 9, whole_grain,
extent->cluster_sectors);
if (ret < 0) {
- return VMDK_ERROR;
+ ret = VMDK_ERROR;
+ goto exit;
}
/* Write grain only into the active image */
ret = bdrv_write(extent->file, cluster_offset, whole_grain,
extent->cluster_sectors);
if (ret < 0) {
- return VMDK_ERROR;
+ ret = VMDK_ERROR;
+ goto exit;
}
}
- return VMDK_OK;
+exit:
+ qemu_vfree(whole_grain);
+ return ret;
}
static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data)
@@ -1200,8 +1244,10 @@
/**
* vmdk_write:
* @zeroed: buf is ignored (data is zero), use zeroed_grain GTE feature
- * if possible, otherwise return -ENOTSUP.
- * @zero_dry_run: used for zeroed == true only, don't update L2 table, just
+ * if possible, otherwise return -ENOTSUP.
+ * @zero_dry_run: used for zeroed == true only, don't update L2 table, just try
+ * with each cluster. By dry run we can find if the zero write
+ * is possible without modifying image data.
*
* Returns: error code with 0 for success.
*/
@@ -1328,6 +1374,8 @@
int ret;
BDRVVmdkState *s = bs->opaque;
qemu_co_mutex_lock(&s->lock);
+ /* write zeroes could fail if sectors not aligned to cluster, test it with
+ * dry_run == true before really updating image */
ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, true);
if (!ret) {
ret = vmdk_write(bs, sector_num, NULL, nb_sectors, true, false);
@@ -1336,7 +1384,6 @@
return ret;
}
-
static int vmdk_create_extent(const char *filename, int64_t filesize,
bool flat, bool compress, bool zeroed_grain)
{
@@ -1367,12 +1414,12 @@
header.compressAlgorithm = compress ? VMDK4_COMPRESSION_DEFLATE : 0;
header.capacity = filesize / 512;
header.granularity = 128;
- header.num_gtes_per_gte = 512;
+ header.num_gtes_per_gt = 512;
grains = (filesize / 512 + header.granularity - 1) / header.granularity;
- gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9;
+ gt_size = ((header.num_gtes_per_gt * sizeof(uint32_t)) + 511) >> 9;
gt_count =
- (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte;
+ (grains + header.num_gtes_per_gt - 1) / header.num_gtes_per_gt;
gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9;
header.desc_offset = 1;
@@ -1388,7 +1435,7 @@
header.flags = cpu_to_le32(header.flags);
header.capacity = cpu_to_le64(header.capacity);
header.granularity = cpu_to_le64(header.granularity);
- header.num_gtes_per_gte = cpu_to_le32(header.num_gtes_per_gte);
+ header.num_gtes_per_gt = cpu_to_le32(header.num_gtes_per_gt);
header.desc_offset = cpu_to_le64(header.desc_offset);
header.desc_size = cpu_to_le64(header.desc_size);
header.rgd_offset = cpu_to_le64(header.rgd_offset);
diff --git a/block/win32-aio.c b/block/win32-aio.c
index fcb7c75..5d1d199 100644
--- a/block/win32-aio.c
+++ b/block/win32-aio.c
@@ -105,13 +105,6 @@
}
}
-static int win32_aio_flush_cb(EventNotifier *e)
-{
- QEMUWin32AIOState *s = container_of(e, QEMUWin32AIOState, e);
-
- return (s->count > 0) ? 1 : 0;
-}
-
static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
{
QEMUWin32AIOCB *waiocb = (QEMUWin32AIOCB *)blockacb;
@@ -201,8 +194,7 @@
goto out_close_efd;
}
- qemu_aio_set_event_notifier(&s->e, win32_aio_completion_cb,
- win32_aio_flush_cb);
+ qemu_aio_set_event_notifier(&s->e, win32_aio_completion_cb);
return s;
diff --git a/blockdev.c b/blockdev.c
index c5abd65..121520e 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -46,6 +46,7 @@
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
extern QemuOptsList qemu_common_drive_opts;
+extern QemuOptsList qemu_old_drive_opts;
static const char *const if_name[IF_COUNT] = {
[IF_NONE] = "none",
@@ -312,7 +313,8 @@
return true;
}
-DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
+static DriveInfo *blockdev_init(QemuOpts *all_opts,
+ BlockInterfaceType block_default_type)
{
const char *buf;
const char *file = NULL;
@@ -322,7 +324,6 @@
enum { MEDIA_DISK, MEDIA_CDROM } media;
int bus_id, unit_id;
int cyls, heads, secs, translation;
- BlockDriver *drv = NULL;
int max_devs;
int index;
int ro = 0;
@@ -338,6 +339,8 @@
QemuOpts *opts;
QDict *bs_opts;
const char *id;
+ bool has_driver_specific_opts;
+ BlockDriver *drv = NULL;
translation = BIOS_ATA_TRANSLATION_AUTO;
media = MEDIA_DISK;
@@ -365,6 +368,8 @@
qdict_del(bs_opts, "id");
}
+ has_driver_specific_opts = !!qdict_size(bs_opts);
+
/* extract parameters */
bus_id = qemu_opt_get_number(opts, "bus", 0);
unit_id = qemu_opt_get_number(opts, "unit", -1);
@@ -375,7 +380,7 @@
secs = qemu_opt_get_number(opts, "secs", 0);
snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
- ro = qemu_opt_get_bool(opts, "readonly", 0);
+ ro = qemu_opt_get_bool(opts, "read-only", 0);
copy_on_read = qemu_opt_get_bool(opts, "copy-on-read", false);
file = qemu_opt_get(opts, "file");
@@ -449,12 +454,14 @@
}
}
- bdrv_flags |= BDRV_O_CACHE_WB;
- if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
- if (bdrv_parse_cache_flags(buf, &bdrv_flags) != 0) {
- error_report("invalid cache option");
- return NULL;
- }
+ if (qemu_opt_get_bool(opts, "cache.writeback", true)) {
+ bdrv_flags |= BDRV_O_CACHE_WB;
+ }
+ if (qemu_opt_get_bool(opts, "cache.direct", false)) {
+ bdrv_flags |= BDRV_O_NOCACHE;
+ }
+ if (qemu_opt_get_bool(opts, "cache.no-flush", true)) {
+ bdrv_flags |= BDRV_O_NO_FLUSH;
}
#ifdef CONFIG_LINUX_AIO
@@ -477,26 +484,31 @@
error_printf("\n");
return NULL;
}
+
drv = bdrv_find_whitelisted_format(buf, ro);
if (!drv) {
- error_report("'%s' invalid format", buf);
+ if (!ro && bdrv_find_whitelisted_format(buf, !ro)) {
+ error_report("'%s' can be only used as read-only device.", buf);
+ } else {
+ error_report("'%s' invalid format", buf);
+ }
return NULL;
}
}
/* disk I/O throttling */
io_limits.bps[BLOCK_IO_LIMIT_TOTAL] =
- qemu_opt_get_number(opts, "bps", 0);
+ qemu_opt_get_number(opts, "throttling.bps-total", 0);
io_limits.bps[BLOCK_IO_LIMIT_READ] =
- qemu_opt_get_number(opts, "bps_rd", 0);
+ qemu_opt_get_number(opts, "throttling.bps-read", 0);
io_limits.bps[BLOCK_IO_LIMIT_WRITE] =
- qemu_opt_get_number(opts, "bps_wr", 0);
+ qemu_opt_get_number(opts, "throttling.bps-write", 0);
io_limits.iops[BLOCK_IO_LIMIT_TOTAL] =
- qemu_opt_get_number(opts, "iops", 0);
+ qemu_opt_get_number(opts, "throttling.iops-total", 0);
io_limits.iops[BLOCK_IO_LIMIT_READ] =
- qemu_opt_get_number(opts, "iops_rd", 0);
+ qemu_opt_get_number(opts, "throttling.iops-read", 0);
io_limits.iops[BLOCK_IO_LIMIT_WRITE] =
- qemu_opt_get_number(opts, "iops_wr", 0);
+ qemu_opt_get_number(opts, "throttling.iops-write", 0);
if (!do_check_io_limits(&io_limits, &error)) {
error_report("%s", error_get_pretty(error));
@@ -658,7 +670,7 @@
abort();
}
if (!file || !*file) {
- if (qdict_size(bs_opts)) {
+ if (has_driver_specific_opts) {
file = NULL;
} else {
return dinfo;
@@ -684,7 +696,7 @@
} else if (ro == 1) {
if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY &&
type != IF_NONE && type != IF_PFLASH) {
- error_report("readonly not supported by this bus type");
+ error_report("read-only not supported by this bus type");
goto err;
}
}
@@ -692,16 +704,17 @@
bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
if (ro && copy_on_read) {
- error_report("warning: disabling copy_on_read on readonly drive");
+ error_report("warning: disabling copy_on_read on read-only drive");
}
+ QINCREF(bs_opts);
ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv);
- bs_opts = NULL;
if (ret < 0) {
if (ret == -EMEDIUMTYPE) {
error_report("could not open disk image %s: not in %s format",
- file ?: dinfo->id, drv->format_name);
+ file ?: dinfo->id, drv ? drv->format_name :
+ qdict_get_str(bs_opts, "driver"));
} else {
error_report("could not open disk image %s: %s",
file ?: dinfo->id, strerror(-ret));
@@ -712,6 +725,7 @@
if (bdrv_key_required(dinfo->bdrv))
autostart = 0;
+ QDECREF(bs_opts);
qemu_opts_del(opts);
return dinfo;
@@ -726,6 +740,80 @@
return NULL;
}
+static void qemu_opt_rename(QemuOpts *opts, const char *from, const char *to)
+{
+ const char *value;
+
+ value = qemu_opt_get(opts, from);
+ if (value) {
+ qemu_opt_set(opts, to, value);
+ qemu_opt_unset(opts, from);
+ }
+}
+
+DriveInfo *drive_init(QemuOpts *all_opts, BlockInterfaceType block_default_type)
+{
+ const char *value;
+
+ /*
+ * Check that only old options are used by copying into a QemuOpts with
+ * stricter checks. Going through a QDict seems to be the easiest way to
+ * achieve this...
+ */
+ QemuOpts* check_opts;
+ QDict *qdict;
+ Error *local_err = NULL;
+
+ qdict = qemu_opts_to_qdict(all_opts, NULL);
+ check_opts = qemu_opts_from_qdict(&qemu_old_drive_opts, qdict, &local_err);
+ QDECREF(qdict);
+
+ if (error_is_set(&local_err)) {
+ qerror_report_err(local_err);
+ error_free(local_err);
+ return NULL;
+ }
+ qemu_opts_del(check_opts);
+
+ /* Change legacy command line options into QMP ones */
+ qemu_opt_rename(all_opts, "iops", "throttling.iops-total");
+ qemu_opt_rename(all_opts, "iops_rd", "throttling.iops-read");
+ qemu_opt_rename(all_opts, "iops_wr", "throttling.iops-write");
+
+ qemu_opt_rename(all_opts, "bps", "throttling.bps-total");
+ qemu_opt_rename(all_opts, "bps_rd", "throttling.bps-read");
+ qemu_opt_rename(all_opts, "bps_wr", "throttling.bps-write");
+
+ qemu_opt_rename(all_opts, "readonly", "read-only");
+
+ value = qemu_opt_get(all_opts, "cache");
+ if (value) {
+ int flags = 0;
+
+ if (bdrv_parse_cache_flags(value, &flags) != 0) {
+ error_report("invalid cache option");
+ return NULL;
+ }
+
+ /* Specific options take precedence */
+ if (!qemu_opt_get(all_opts, "cache.writeback")) {
+ qemu_opt_set_bool(all_opts, "cache.writeback",
+ !!(flags & BDRV_O_CACHE_WB));
+ }
+ if (!qemu_opt_get(all_opts, "cache.direct")) {
+ qemu_opt_set_bool(all_opts, "cache.direct",
+ !!(flags & BDRV_O_NOCACHE));
+ }
+ if (!qemu_opt_get(all_opts, "cache.no-flush")) {
+ qemu_opt_set_bool(all_opts, "cache.no-flush",
+ !!(flags & BDRV_O_NO_FLUSH));
+ }
+ qemu_opt_unset(all_opts, "cache");
+ }
+
+ return blockdev_init(all_opts, block_default_type);
+}
+
void do_commit(Monitor *mon, const QDict *qdict)
{
const char *device = qdict_get_str(qdict, "device");
@@ -971,7 +1059,7 @@
static void abort_commit(BlkTransactionState *common)
{
- assert(false); /* this action never succeeds */
+ g_assert_not_reached(); /* this action never succeeds */
}
static const BdrvActionOps actions[] = {
@@ -1211,7 +1299,7 @@
bdrv_io_limits_disable(bs);
} else {
if (bs->block_timer) {
- qemu_mod_timer(bs->block_timer, qemu_get_clock_ns(vm_clock));
+ timer_mod(bs->block_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
}
}
}
@@ -1431,16 +1519,13 @@
{
BlockDriverState *bs;
BlockDriverState *target_bs;
+ BlockDriverState *source = NULL;
BlockDriver *drv = NULL;
Error *local_err = NULL;
int flags;
int64_t size;
int ret;
- if (sync != MIRROR_SYNC_MODE_FULL) {
- error_setg(errp, "only sync mode 'full' is currently supported");
- return;
- }
if (!has_speed) {
speed = 0;
}
@@ -1483,6 +1568,18 @@
flags = bs->open_flags | BDRV_O_RDWR;
+ /* See if we have a backing HD we can use to create our new image
+ * on top of. */
+ if (sync == MIRROR_SYNC_MODE_TOP) {
+ source = bs->backing_hd;
+ if (!source) {
+ sync = MIRROR_SYNC_MODE_FULL;
+ }
+ }
+ if (sync == MIRROR_SYNC_MODE_NONE) {
+ source = bs;
+ }
+
size = bdrv_getlength(bs);
if (size < 0) {
error_setg_errno(errp, -size, "bdrv_getlength failed");
@@ -1491,8 +1588,14 @@
if (mode != NEW_IMAGE_MODE_EXISTING) {
assert(format && drv);
- bdrv_img_create(target, format,
- NULL, NULL, NULL, size, flags, &local_err, false);
+ if (source) {
+ bdrv_img_create(target, format, source->filename,
+ source->drv->format_name, NULL,
+ size, flags, &local_err, false);
+ } else {
+ bdrv_img_create(target, format, NULL, NULL, NULL,
+ size, flags, &local_err, false);
+ }
}
if (error_is_set(&local_err)) {
@@ -1508,7 +1611,7 @@
return;
}
- backup_start(bs, target_bs, speed, on_source_error, on_target_error,
+ backup_start(bs, target_bs, speed, sync, on_source_error, on_target_error,
block_job_cb, bs, &local_err);
if (local_err != NULL) {
bdrv_delete(target_bs);
@@ -1822,6 +1925,135 @@
.type = QEMU_OPT_STRING,
.help = "discard operation (ignore/off, unmap/on)",
},{
+ .name = "cache.writeback",
+ .type = QEMU_OPT_BOOL,
+ .help = "enables writeback mode for any caches",
+ },{
+ .name = "cache.direct",
+ .type = QEMU_OPT_BOOL,
+ .help = "enables use of O_DIRECT (bypass the host page cache)",
+ },{
+ .name = "cache.no-flush",
+ .type = QEMU_OPT_BOOL,
+ .help = "ignore any flush requests for the device",
+ },{
+ .name = "aio",
+ .type = QEMU_OPT_STRING,
+ .help = "host AIO implementation (threads, native)",
+ },{
+ .name = "format",
+ .type = QEMU_OPT_STRING,
+ .help = "disk format (raw, qcow2, ...)",
+ },{
+ .name = "serial",
+ .type = QEMU_OPT_STRING,
+ .help = "disk serial number",
+ },{
+ .name = "rerror",
+ .type = QEMU_OPT_STRING,
+ .help = "read error action",
+ },{
+ .name = "werror",
+ .type = QEMU_OPT_STRING,
+ .help = "write error action",
+ },{
+ .name = "addr",
+ .type = QEMU_OPT_STRING,
+ .help = "pci address (virtio only)",
+ },{
+ .name = "read-only",
+ .type = QEMU_OPT_BOOL,
+ .help = "open drive file as read-only",
+ },{
+ .name = "throttling.iops-total",
+ .type = QEMU_OPT_NUMBER,
+ .help = "limit total I/O operations per second",
+ },{
+ .name = "throttling.iops-read",
+ .type = QEMU_OPT_NUMBER,
+ .help = "limit read operations per second",
+ },{
+ .name = "throttling.iops-write",
+ .type = QEMU_OPT_NUMBER,
+ .help = "limit write operations per second",
+ },{
+ .name = "throttling.bps-total",
+ .type = QEMU_OPT_NUMBER,
+ .help = "limit total bytes per second",
+ },{
+ .name = "throttling.bps-read",
+ .type = QEMU_OPT_NUMBER,
+ .help = "limit read bytes per second",
+ },{
+ .name = "throttling.bps-write",
+ .type = QEMU_OPT_NUMBER,
+ .help = "limit write bytes per second",
+ },{
+ .name = "copy-on-read",
+ .type = QEMU_OPT_BOOL,
+ .help = "copy read data from backing file into image file",
+ },{
+ .name = "boot",
+ .type = QEMU_OPT_BOOL,
+ .help = "(deprecated, ignored)",
+ },
+ { /* end of list */ }
+ },
+};
+
+QemuOptsList qemu_old_drive_opts = {
+ .name = "drive",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_old_drive_opts.head),
+ .desc = {
+ {
+ .name = "bus",
+ .type = QEMU_OPT_NUMBER,
+ .help = "bus number",
+ },{
+ .name = "unit",
+ .type = QEMU_OPT_NUMBER,
+ .help = "unit number (i.e. lun for scsi)",
+ },{
+ .name = "if",
+ .type = QEMU_OPT_STRING,
+ .help = "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
+ },{
+ .name = "index",
+ .type = QEMU_OPT_NUMBER,
+ .help = "index number",
+ },{
+ .name = "cyls",
+ .type = QEMU_OPT_NUMBER,
+ .help = "number of cylinders (ide disk geometry)",
+ },{
+ .name = "heads",
+ .type = QEMU_OPT_NUMBER,
+ .help = "number of heads (ide disk geometry)",
+ },{
+ .name = "secs",
+ .type = QEMU_OPT_NUMBER,
+ .help = "number of sectors (ide disk geometry)",
+ },{
+ .name = "trans",
+ .type = QEMU_OPT_STRING,
+ .help = "chs translation (auto, lba. none)",
+ },{
+ .name = "media",
+ .type = QEMU_OPT_STRING,
+ .help = "media type (disk, cdrom)",
+ },{
+ .name = "snapshot",
+ .type = QEMU_OPT_BOOL,
+ .help = "enable/disable snapshot mode",
+ },{
+ .name = "file",
+ .type = QEMU_OPT_STRING,
+ .help = "disk image",
+ },{
+ .name = "discard",
+ .type = QEMU_OPT_STRING,
+ .help = "discard operation (ignore/off, unmap/on)",
+ },{
.name = "cache",
.type = QEMU_OPT_STRING,
.help = "host cache usage (none, writeback, writethrough, "
diff --git a/blockjob.c b/blockjob.c
index ca80df1..7edc945 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -187,7 +187,7 @@
return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret;
}
-void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns)
+void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns)
{
assert(job->busy);
@@ -200,7 +200,7 @@
if (block_job_is_paused(job)) {
qemu_coroutine_yield();
} else {
- co_sleep_ns(clock, ns);
+ co_sleep_ns(type, ns);
}
job->busy = true;
}
diff --git a/configure b/configure
index 877a821..0a55c20 100755
--- a/configure
+++ b/configure
@@ -155,7 +155,6 @@
curses=""
docs=""
fdt=""
-nptl=""
pixman=""
sdl=""
virtfs=""
@@ -232,7 +231,7 @@
usb_redir=""
glx=""
zlib="yes"
-guest_agent="yes"
+guest_agent=""
want_tools="yes"
libiscsi=""
coroutine=""
@@ -856,10 +855,6 @@
;;
--enable-fdt) fdt="yes"
;;
- --disable-nptl) nptl="no"
- ;;
- --enable-nptl) nptl="yes"
- ;;
--enable-mixemu) mixemu="yes"
;;
--disable-linux-aio) linux_aio="no"
@@ -1103,8 +1098,6 @@
echo " --disable-rdma disable RDMA-based migration support"
echo " --enable-rdma enable RDMA-based migration support"
echo " --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)"
-echo " --disable-nptl disable usermode NPTL support"
-echo " --enable-nptl enable usermode NPTL support"
echo " --enable-system enable all system emulation targets"
echo " --disable-system disable all system emulation targets"
echo " --enable-user enable supported user emulation targets"
@@ -1439,7 +1432,7 @@
##########################################
# NPTL probe
-if test "$nptl" != "no" ; then
+if test "$linux_user" = "yes"; then
cat > $TMPC <<EOF
#include <sched.h>
#include <linux/futex.h>
@@ -1450,14 +1443,8 @@
return 0;
}
EOF
-
- if compile_object ; then
- nptl=yes
- else
- if test "$nptl" = "yes" ; then
- feature_not_found "nptl"
- fi
- nptl=no
+ if ! compile_object ; then
+ feature_not_found "nptl"
fi
fi
@@ -1482,7 +1469,7 @@
# libseccomp check
if test "$seccomp" != "no" ; then
- if $pkg_config --atleast-version=1.0.0 libseccomp --modversion >/dev/null 2>&1; then
+ if $pkg_config --atleast-version=2.1.0 libseccomp --modversion >/dev/null 2>&1; then
libs_softmmu="$libs_softmmu `$pkg_config --libs libseccomp`"
QEMU_CFLAGS="$QEMU_CFLAGS `$pkg_config --cflags libseccomp`"
seccomp="yes"
@@ -2831,6 +2818,37 @@
dup3=yes
fi
+# check for ppoll support
+ppoll=no
+cat > $TMPC << EOF
+#include <poll.h>
+
+int main(void)
+{
+ struct pollfd pfd = { .fd = 0, .events = 0, .revents = 0 };
+ ppoll(&pfd, 1, 0, 0);
+ return 0;
+}
+EOF
+if compile_prog "" "" ; then
+ ppoll=yes
+fi
+
+# check for prctl(PR_SET_TIMERSLACK , ... ) support
+prctl_pr_set_timerslack=no
+cat > $TMPC << EOF
+#include <sys/prctl.h>
+
+int main(void)
+{
+ prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
+ return 0;
+}
+EOF
+if compile_prog "" "" ; then
+ prctl_pr_set_timerslack=yes
+fi
+
# check for epoll support
epoll=no
cat > $TMPC << EOF
@@ -3457,10 +3475,15 @@
virtfs=no
fi
fi
+fi
+if [ "$guest_agent" != "no" ]; then
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
- if [ "$guest_agent" = "yes" ]; then
tools="qemu-ga\$(EXESUF) $tools"
- fi
+ guest_agent=yes
+ elif [ "$guest_agent" != yes ]; then
+ guest_agent=no
+ else
+ error_exit "Guest agent is not supported on this platform"
fi
fi
@@ -3581,7 +3604,6 @@
echo "Documentation $docs"
[ ! -z "$uname_release" ] && \
echo "uname -r $uname_release"
-echo "NPTL support $nptl"
echo "GUEST_BASE $guest_base"
echo "PIE $pie"
echo "vde support $vde"
@@ -3659,7 +3681,7 @@
echo "ARCH=$ARCH" >> $config_host_mak
case "$cpu" in
- arm|i386|x86_64|ppc)
+ arm|i386|x86_64|ppc|aarch64)
# The TCG interpreter currently does not support ld/st optimization.
if test "$tcg_interpreter" = "no" ; then
echo "CONFIG_QEMU_LDST_OPTIMIZATION=y" >> $config_host_mak
@@ -3823,6 +3845,12 @@
if test "$dup3" = "yes" ; then
echo "CONFIG_DUP3=y" >> $config_host_mak
fi
+if test "$ppoll" = "yes" ; then
+ echo "CONFIG_PPOLL=y" >> $config_host_mak
+fi
+if test "$prctl_pr_set_timerslack" = "yes" ; then
+ echo "CONFIG_PRCTL_PR_SET_TIMERSLACK=y" >> $config_host_mak
+fi
if test "$epoll" = "yes" ; then
echo "CONFIG_EPOLL=y" >> $config_host_mak
fi
@@ -4216,7 +4244,6 @@
echo "# Automatically generated by configure - do not modify" > $config_target_mak
bflt="no"
-target_nptl="no"
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_name/g"`
gdb_xml_files=""
@@ -4231,16 +4258,13 @@
TARGET_BASE_ARCH=i386
;;
alpha)
- target_nptl="yes"
;;
arm|armeb)
TARGET_ARCH=arm
bflt="yes"
- target_nptl="yes"
gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
;;
cris)
- target_nptl="yes"
;;
lm32)
;;
@@ -4251,12 +4275,10 @@
microblaze|microblazeel)
TARGET_ARCH=microblaze
bflt="yes"
- target_nptl="yes"
;;
mips|mipsel)
TARGET_ARCH=mips
echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
- target_nptl="yes"
;;
mipsn32|mipsn32el)
TARGET_ARCH=mips64
@@ -4277,13 +4299,11 @@
;;
ppc)
gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
- target_nptl="yes"
;;
ppcemb)
TARGET_BASE_ARCH=ppc
TARGET_ABI_DIR=ppc
gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
- target_nptl="yes"
;;
ppc64)
TARGET_BASE_ARCH=ppc
@@ -4300,7 +4320,6 @@
sh4|sh4eb)
TARGET_ARCH=sh4
bflt="yes"
- target_nptl="yes"
;;
sparc)
;;
@@ -4314,7 +4333,6 @@
echo "TARGET_ABI32=y" >> $config_target_mak
;;
s390x)
- target_nptl="yes"
;;
unicore32)
;;
@@ -4396,10 +4414,6 @@
if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
echo "TARGET_HAS_BFLT=y" >> $config_target_mak
fi
-if test "$target_user_only" = "yes" \
- -a "$nptl" = "yes" -a "$target_nptl" = "yes"; then
- echo "CONFIG_USE_NPTL=y" >> $config_target_mak
-fi
if test "$target_user_only" = "yes" -a "$guest_base" = "yes"; then
echo "CONFIG_USE_GUEST_BASE=y" >> $config_target_mak
fi
@@ -4530,13 +4544,13 @@
fi
# build tree in object directory in case the source is not in the current directory
-DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos"
+DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa"
DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw"
DIRS="$DIRS roms/seabios roms/vgabios"
DIRS="$DIRS qapi-generated"
FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
-FILES="$FILES tests/tcg/lm32/Makefile po/Makefile"
+FILES="$FILES tests/tcg/lm32/Makefile tests/tcg/xtensa/Makefile po/Makefile"
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
FILES="$FILES pc-bios/spapr-rtas/Makefile"
FILES="$FILES pc-bios/s390-ccw/Makefile"
diff --git a/cpus.c b/cpus.c
index ca6b886..b9e5685 100644
--- a/cpus.c
+++ b/cpus.c
@@ -62,12 +62,17 @@
static CPUState *next_cpu;
+bool cpu_is_stopped(CPUState *cpu)
+{
+ return cpu->stopped || !runstate_is_running();
+}
+
static bool cpu_thread_is_idle(CPUState *cpu)
{
if (cpu->stop || cpu->queued_work_first) {
return false;
}
- if (cpu->stopped || !runstate_is_running()) {
+ if (cpu_is_stopped(cpu)) {
return true;
}
if (!cpu->halted || qemu_cpu_has_work(cpu) ||
@@ -112,7 +117,7 @@
int64_t dummy;
} TimersState;
-TimersState timers_state;
+static TimersState timers_state;
/* Return the virtual CPU time, based on the instruction counter. */
int64_t cpu_get_icount(void)
@@ -202,7 +207,7 @@
return;
}
cur_time = cpu_get_clock();
- cur_icount = qemu_get_clock_ns(vm_clock);
+ cur_icount = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
delta = cur_icount - cur_time;
/* FIXME: This is a very crude algorithm, somewhat prone to oscillation. */
if (delta > 0
@@ -223,15 +228,16 @@
static void icount_adjust_rt(void *opaque)
{
- qemu_mod_timer(icount_rt_timer,
- qemu_get_clock_ms(rt_clock) + 1000);
+ timer_mod(icount_rt_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
icount_adjust();
}
static void icount_adjust_vm(void *opaque)
{
- qemu_mod_timer(icount_vm_timer,
- qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
+ timer_mod(icount_vm_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ get_ticks_per_sec() / 10);
icount_adjust();
}
@@ -247,22 +253,22 @@
}
if (runstate_is_running()) {
- int64_t clock = qemu_get_clock_ns(rt_clock);
+ int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
int64_t warp_delta = clock - vm_clock_warp_start;
if (use_icount == 1) {
qemu_icount_bias += warp_delta;
} else {
/*
- * In adaptive mode, do not let the vm_clock run too
+ * In adaptive mode, do not let QEMU_CLOCK_VIRTUAL run too
* far ahead of real time.
*/
int64_t cur_time = cpu_get_clock();
- int64_t cur_icount = qemu_get_clock_ns(vm_clock);
+ int64_t cur_icount = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
int64_t delta = cur_time - cur_icount;
qemu_icount_bias += MIN(warp_delta, delta);
}
- if (qemu_clock_expired(vm_clock)) {
- qemu_notify_event();
+ if (qemu_clock_expired(QEMU_CLOCK_VIRTUAL)) {
+ qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
}
}
vm_clock_warp_start = -1;
@@ -270,19 +276,19 @@
void qtest_clock_warp(int64_t dest)
{
- int64_t clock = qemu_get_clock_ns(vm_clock);
+ int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
assert(qtest_enabled());
while (clock < dest) {
- int64_t deadline = qemu_clock_deadline(vm_clock);
+ int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
int64_t warp = MIN(dest - clock, deadline);
qemu_icount_bias += warp;
- qemu_run_timers(vm_clock);
- clock = qemu_get_clock_ns(vm_clock);
+ qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
+ clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
- qemu_notify_event();
+ qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
}
-void qemu_clock_warp(QEMUClock *clock)
+void qemu_clock_warp(QEMUClockType type)
{
int64_t deadline;
@@ -291,20 +297,20 @@
* applicable to other clocks. But a clock argument removes the
* need for if statements all over the place.
*/
- if (clock != vm_clock || !use_icount) {
+ if (type != QEMU_CLOCK_VIRTUAL || !use_icount) {
return;
}
/*
- * If the CPUs have been sleeping, advance the vm_clock timer now. This
- * ensures that the deadline for the timer is computed correctly below.
+ * If the CPUs have been sleeping, advance QEMU_CLOCK_VIRTUAL timer now.
+ * This ensures that the deadline for the timer is computed correctly below.
* This also makes sure that the insn counter is synchronized before the
* CPU starts running, in case the CPU is woken by an event other than
- * the earliest vm_clock timer.
+ * the earliest QEMU_CLOCK_VIRTUAL timer.
*/
icount_warp_rt(NULL);
- if (!all_cpu_threads_idle() || !qemu_clock_has_timers(vm_clock)) {
- qemu_del_timer(icount_warp_timer);
+ if (!all_cpu_threads_idle() || !qemu_clock_has_timers(QEMU_CLOCK_VIRTUAL)) {
+ timer_del(icount_warp_timer);
return;
}
@@ -313,28 +319,40 @@
return;
}
- vm_clock_warp_start = qemu_get_clock_ns(rt_clock);
- deadline = qemu_clock_deadline(vm_clock);
+ vm_clock_warp_start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
+ /* We want to use the earliest deadline from ALL vm_clocks */
+ deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+
+ /* Maintain prior (possibly buggy) behaviour where if no deadline
+ * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than
+ * INT32_MAX nanoseconds ahead, we still use INT32_MAX
+ * nanoseconds.
+ */
+ if ((deadline < 0) || (deadline > INT32_MAX)) {
+ deadline = INT32_MAX;
+ }
+
if (deadline > 0) {
/*
- * Ensure the vm_clock proceeds even when the virtual CPU goes to
+ * Ensure QEMU_CLOCK_VIRTUAL proceeds even when the virtual CPU goes to
* sleep. Otherwise, the CPU might be waiting for a future timer
* interrupt to wake it up, but the interrupt never comes because
* the vCPU isn't running any insns and thus doesn't advance the
- * vm_clock.
+ * QEMU_CLOCK_VIRTUAL.
*
* An extreme solution for this problem would be to never let VCPUs
- * sleep in icount mode if there is a pending vm_clock timer; rather
- * time could just advance to the next vm_clock event. Instead, we
- * do stop VCPUs and only advance vm_clock after some "real" time,
- * (related to the time left until the next event) has passed. This
- * rt_clock timer will do this. This avoids that the warps are too
- * visible externally---for example, you will not be sending network
- * packets continuously instead of every 100ms.
+ * sleep in icount mode if there is a pending QEMU_CLOCK_VIRTUAL
+ * timer; rather time could just advance to the next QEMU_CLOCK_VIRTUAL
+ * event. Instead, we do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL
+ * after some e"real" time, (related to the time left until the next
+ * event) has passed. The QEMU_CLOCK_REALTIME timer will do this.
+ * This avoids that the warps are visible externally; for example,
+ * you will not be sending network packets continuously instead of
+ * every 100ms.
*/
- qemu_mod_timer(icount_warp_timer, vm_clock_warp_start + deadline);
- } else {
- qemu_notify_event();
+ timer_mod(icount_warp_timer, vm_clock_warp_start + deadline);
+ } else if (deadline == 0) {
+ qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
}
}
@@ -358,7 +376,8 @@
return;
}
- icount_warp_timer = qemu_new_timer_ns(rt_clock, icount_warp_rt, NULL);
+ icount_warp_timer = timer_new_ns(QEMU_CLOCK_REALTIME,
+ icount_warp_rt, NULL);
if (strcmp(option, "auto") != 0) {
icount_time_shift = strtol(option, NULL, 0);
use_icount = 1;
@@ -376,12 +395,15 @@
the virtual time trigger catches emulated time passing too fast.
Realtime triggers occur even when idle, so use them less frequently
than VM triggers. */
- icount_rt_timer = qemu_new_timer_ms(rt_clock, icount_adjust_rt, NULL);
- qemu_mod_timer(icount_rt_timer,
- qemu_get_clock_ms(rt_clock) + 1000);
- icount_vm_timer = qemu_new_timer_ns(vm_clock, icount_adjust_vm, NULL);
- qemu_mod_timer(icount_vm_timer,
- qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 10);
+ icount_rt_timer = timer_new_ms(QEMU_CLOCK_REALTIME,
+ icount_adjust_rt, NULL);
+ timer_mod(icount_rt_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
+ icount_vm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+ icount_adjust_vm, NULL);
+ timer_mod(icount_vm_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ get_ticks_per_sec() / 10);
}
/***********************************************************/
@@ -429,11 +451,6 @@
}
}
-bool cpu_is_stopped(CPUState *cpu)
-{
- return !runstate_is_running() || cpu->stopped;
-}
-
static int do_vm_stop(RunState state)
{
int ret = 0;
@@ -457,7 +474,7 @@
if (cpu->stop) {
return false;
}
- if (cpu->stopped || !runstate_is_running()) {
+ if (cpu_is_stopped(cpu)) {
return false;
}
return true;
@@ -735,7 +752,7 @@
while (all_cpu_threads_idle()) {
/* Start accounting real time to the virtual clock if the CPUs
are idle. */
- qemu_clock_warp(vm_clock);
+ qemu_clock_warp(QEMU_CLOCK_VIRTUAL);
qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
}
@@ -866,8 +883,13 @@
while (1) {
tcg_exec_all();
- if (use_icount && qemu_clock_deadline(vm_clock) <= 0) {
- qemu_notify_event();
+
+ if (use_icount) {
+ int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+
+ if (deadline == 0) {
+ qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
+ }
}
qemu_tcg_wait_io_event();
}
@@ -985,7 +1007,7 @@
{
CPUState *cpu = first_cpu;
- qemu_clock_enable(vm_clock, false);
+ qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false);
while (cpu) {
cpu->stop = true;
qemu_cpu_kick(cpu);
@@ -1026,7 +1048,7 @@
{
CPUState *cpu = first_cpu;
- qemu_clock_enable(vm_clock, true);
+ qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
while (cpu) {
cpu_resume(cpu);
cpu = cpu->next_cpu;
@@ -1145,11 +1167,23 @@
#endif
if (use_icount) {
int64_t count;
+ int64_t deadline;
int decr;
qemu_icount -= (env->icount_decr.u16.low + env->icount_extra);
env->icount_decr.u16.low = 0;
env->icount_extra = 0;
- count = qemu_icount_round(qemu_clock_deadline(vm_clock));
+ deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+
+ /* Maintain prior (possibly buggy) behaviour where if no deadline
+ * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than
+ * INT32_MAX nanoseconds ahead, we still use INT32_MAX
+ * nanoseconds.
+ */
+ if ((deadline < 0) || (deadline > INT32_MAX)) {
+ deadline = INT32_MAX;
+ }
+
+ count = qemu_icount_round(deadline);
qemu_icount += count;
decr = (count > 0xffff) ? 0xffff : count;
count -= decr;
@@ -1175,8 +1209,8 @@
{
int r;
- /* Account partial waits to the vm_clock. */
- qemu_clock_warp(vm_clock);
+ /* Account partial waits to QEMU_CLOCK_VIRTUAL. */
+ qemu_clock_warp(QEMU_CLOCK_VIRTUAL);
if (next_cpu == NULL) {
next_cpu = first_cpu;
@@ -1185,7 +1219,7 @@
CPUState *cpu = next_cpu;
CPUArchState *env = cpu->env_ptr;
- qemu_clock_enable(vm_clock,
+ qemu_clock_enable(QEMU_CLOCK_VIRTUAL,
(cpu->singlestep_enabled & SSTEP_NOTIMER) == 0);
if (cpu_can_run(cpu)) {
diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak
index 18e5337..bc07600 100644
--- a/default-configs/alpha-softmmu.mak
+++ b/default-configs/alpha-softmmu.mak
@@ -14,3 +14,4 @@
CONFIG_IDE_CMD646=y
CONFIG_I8259=y
CONFIG_MC146818RTC=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 27cbe3d..ac0815d 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -34,9 +34,9 @@
CONFIG_MICRODRIVE=y
CONFIG_USB_MUSB=y
-CONFIG_ARM9MPCORE=y
CONFIG_ARM11MPCORE=y
-CONFIG_ARM15MPCORE=y
+CONFIG_A9MPCORE=y
+CONFIG_A15MPCORE=y
CONFIG_ARM_GIC=y
CONFIG_ARM_GIC_KVM=$(CONFIG_KVM)
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 4a0fc9c..37ef90f 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -33,7 +33,6 @@
CONFIG_PAM=y
CONFIG_PCI_PIIX=y
CONFIG_WDT_IB700=y
-CONFIG_PC_SYSFW=y
CONFIG_XEN_I386=$(CONFIG_XEN)
CONFIG_ISA_DEBUG=y
CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak
index b443702..71177ef 100644
--- a/default-configs/mips-softmmu.mak
+++ b/default-configs/mips-softmmu.mak
@@ -3,7 +3,6 @@
include pci.mak
include sound.mak
include usb.mak
-CONFIG_ISA_MMIO=y
CONFIG_ESP=y
CONFIG_VGA=y
CONFIG_VGA_PCI=y
@@ -34,3 +33,5 @@
CONFIG_JAZZ_LED=y
CONFIG_MC146818RTC=y
CONFIG_VT82C686=y
+CONFIG_ISA_TESTDEV=y
+CONFIG_EMPTY_SLOT=y
diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak
index d638957..617301b 100644
--- a/default-configs/mips64-softmmu.mak
+++ b/default-configs/mips64-softmmu.mak
@@ -3,7 +3,6 @@
include pci.mak
include sound.mak
include usb.mak
-CONFIG_ISA_MMIO=y
CONFIG_ESP=y
CONFIG_VGA=y
CONFIG_VGA_PCI=y
@@ -34,3 +33,5 @@
CONFIG_JAZZ_LED=y
CONFIG_MC146818RTC=y
CONFIG_VT82C686=y
+CONFIG_ISA_TESTDEV=y
+CONFIG_EMPTY_SLOT=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index c9be3f4..317b151 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -3,7 +3,6 @@
include pci.mak
include sound.mak
include usb.mak
-CONFIG_ISA_MMIO=y
CONFIG_ESP=y
CONFIG_VGA=y
CONFIG_VGA_PCI=y
@@ -36,3 +35,5 @@
CONFIG_JAZZ_LED=y
CONFIG_MC146818RTC=y
CONFIG_VT82C686=y
+CONFIG_ISA_TESTDEV=y
+CONFIG_EMPTY_SLOT=y
diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak
index 4f4a449..532a9ae 100644
--- a/default-configs/mipsel-softmmu.mak
+++ b/default-configs/mipsel-softmmu.mak
@@ -3,7 +3,6 @@
include pci.mak
include sound.mak
include usb.mak
-CONFIG_ISA_MMIO=y
CONFIG_ESP=y
CONFIG_VGA=y
CONFIG_VGA_PCI=y
@@ -34,3 +33,5 @@
CONFIG_JAZZ_LED=y
CONFIG_MC146818RTC=y
CONFIG_VT82C686=y
+CONFIG_ISA_TESTDEV=y
+CONFIG_EMPTY_SLOT=y
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 73e4cc5..eac0b28 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -46,3 +46,4 @@
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
# For PReP
CONFIG_MC146818RTC=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index 6d1933b..7831c2b 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -48,4 +48,11 @@
# For pSeries
CONFIG_XICS=$(CONFIG_PSERIES)
# For PReP
+CONFIG_I82378=y
+CONFIG_I8259=y
+CONFIG_I8254=y
+CONFIG_PCSPK=y
+CONFIG_I82374=y
+CONFIG_I8257=y
CONFIG_MC146818RTC=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index e3b5e50..86080a7 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -41,3 +41,4 @@
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
# For PReP
CONFIG_MC146818RTC=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/sh4-softmmu.mak b/default-configs/sh4-softmmu.mak
index f6bf62d..8e00390 100644
--- a/default-configs/sh4-softmmu.mak
+++ b/default-configs/sh4-softmmu.mak
@@ -5,7 +5,14 @@
CONFIG_SERIAL=y
CONFIG_PTIMER=y
CONFIG_PFLASH_CFI02=y
-CONFIG_ISA_MMIO=y
CONFIG_SH4=y
CONFIG_IDE_MMIO=y
CONFIG_SM501=y
+CONFIG_ISA_TESTDEV=y
+CONFIG_I82378=y
+CONFIG_I8259=y
+CONFIG_I8254=y
+CONFIG_PCSPK=y
+CONFIG_I82374=y
+CONFIG_I8257=y
+CONFIG_MC146818RTC=y
diff --git a/default-configs/sh4eb-softmmu.mak b/default-configs/sh4eb-softmmu.mak
index c1d513d..efdd058 100644
--- a/default-configs/sh4eb-softmmu.mak
+++ b/default-configs/sh4eb-softmmu.mak
@@ -5,7 +5,14 @@
CONFIG_SERIAL=y
CONFIG_PTIMER=y
CONFIG_PFLASH_CFI02=y
-CONFIG_ISA_MMIO=y
CONFIG_SH4=y
CONFIG_IDE_MMIO=y
CONFIG_SM501=y
+CONFIG_ISA_TESTDEV=y
+CONFIG_I82378=y
+CONFIG_I8259=y
+CONFIG_I8254=y
+CONFIG_PCSPK=y
+CONFIG_I82374=y
+CONFIG_I8257=y
+CONFIG_MC146818RTC=y
diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak
index 9b08ee8..299c97b 100644
--- a/default-configs/sparc64-softmmu.mak
+++ b/default-configs/sparc64-softmmu.mak
@@ -15,3 +15,4 @@
CONFIG_IDE_CMD646=y
CONFIG_PCI_APB=y
CONFIG_MC146818RTC=y
+CONFIG_ISA_TESTDEV=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 10bb0c6..31bddce 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -33,7 +33,6 @@
CONFIG_PAM=y
CONFIG_PCI_PIIX=y
CONFIG_WDT_IB700=y
-CONFIG_PC_SYSFW=y
CONFIG_XEN_I386=$(CONFIG_XEN)
CONFIG_ISA_DEBUG=y
CONFIG_ISA_TESTDEV=y
diff --git a/disas.c b/disas.c
index 71007fb..0203ef2 100644
--- a/disas.c
+++ b/disas.c
@@ -158,6 +158,35 @@
}
#endif
+static int print_insn_objdump(bfd_vma pc, disassemble_info *info,
+ const char *prefix)
+{
+ int i, n = info->buffer_length;
+ uint8_t *buf = g_malloc(n);
+
+ info->read_memory_func(pc, buf, n, info);
+
+ for (i = 0; i < n; ++i) {
+ if (i % 32 == 0) {
+ info->fprintf_func(info->stream, "\n%s: ", prefix);
+ }
+ info->fprintf_func(info->stream, "%02x", buf[i]);
+ }
+
+ g_free(buf);
+ return n;
+}
+
+static int print_insn_od_host(bfd_vma pc, disassemble_info *info)
+{
+ return print_insn_objdump(pc, info, "OBJD-H");
+}
+
+static int print_insn_od_target(bfd_vma pc, disassemble_info *info)
+{
+ return print_insn_objdump(pc, info, "OBJD-T");
+}
+
/* Disassemble this for me please... (debugging). 'flags' has the following
values:
i386 - 1 means 16 bit code, 2 means 64 bit code
@@ -171,7 +200,7 @@
target_ulong pc;
int count;
CPUDebug s;
- int (*print_insn)(bfd_vma pc, disassemble_info *info);
+ int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
@@ -263,11 +292,10 @@
#elif defined(TARGET_LM32)
s.info.mach = bfd_mach_lm32;
print_insn = print_insn_lm32;
-#else
- fprintf(out, "0x" TARGET_FMT_lx
- ": Asm output not supported on this arch\n", code);
- return;
#endif
+ if (print_insn == NULL) {
+ print_insn = print_insn_od_target;
+ }
for (pc = code; size > 0; pc += count, size -= count) {
fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
@@ -303,7 +331,7 @@
uintptr_t pc;
int count;
CPUDebug s;
- int (*print_insn)(bfd_vma pc, disassemble_info *info);
+ int (*print_insn)(bfd_vma pc, disassemble_info *info) = NULL;
INIT_DISASSEMBLE_INFO(s.info, out, fprintf);
s.info.print_address_func = generic_print_host_address;
@@ -347,11 +375,10 @@
print_insn = print_insn_hppa;
#elif defined(__ia64__)
print_insn = print_insn_ia64;
-#else
- fprintf(out, "0x%lx: Asm output not supported on this arch\n",
- (long) code);
- return;
#endif
+ if (print_insn == NULL) {
+ print_insn = print_insn_od_host;
+ }
for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
fprintf(out, "0x%08" PRIxPTR ": ", pc);
count = print_insn(pc, &s.info);
diff --git a/dma-helpers.c b/dma-helpers.c
index 499550f..c9620a5 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -11,6 +11,7 @@
#include "trace.h"
#include "qemu/range.h"
#include "qemu/thread.h"
+#include "qemu/main-loop.h"
/* #define DEBUG_IOMMU */
diff --git a/docs/q35-chipset.cfg b/docs/q35-chipset.cfg
index 1b6efc0..e4ddb7d 100644
--- a/docs/q35-chipset.cfg
+++ b/docs/q35-chipset.cfg
@@ -91,6 +91,29 @@
port = "4"
chassis = "4"
+##
+# Example PCIe switch with two downstream ports
+#
+#[device "pcie-switch-upstream-port-1"]
+# driver = "x3130-upstream"
+# bus = "ich9-pcie-port-4"
+# addr = "00.0"
+#
+#[device "pcie-switch-downstream-port-1-1"]
+# driver = "xio3130-downstream"
+# multifunction = "on"
+# bus = "pcie-switch-upstream-port-1"
+# addr = "00.0"
+# port = "1"
+# chassis = "5"
+#
+#[device "pcie-switch-downstream-port-1-2"]
+# driver = "xio3130-downstream"
+# multifunction = "on"
+# bus = "pcie-switch-upstream-port-1"
+# addr = "00.1"
+# port = "1"
+# chassis = "6"
[device "ich9-ehci-1"]
driver = "ich9-usb-ehci1"
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index cccb11e..0ce045c 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -34,9 +34,15 @@
There are two basic syntaxes used, type definitions and command definitions.
The first syntax defines a type and is represented by a dictionary. There are
-two kinds of types that are supported: complex user-defined types, and enums.
+three kinds of user-defined types that are supported: complex types,
+enumeration types and union types.
-A complex type is a dictionary containing a single key who's value is a
+Generally speaking, types definitions should always use CamelCase for the type
+names. Command names should be all lower case with words separated by a hyphen.
+
+=== Complex types ===
+
+A complex type is a dictionary containing a single key whose value is a
dictionary. This corresponds to a struct in C or an Object in JSON. An
example of a complex type is:
@@ -47,13 +53,104 @@
members should always be added to the end of the dictionary to preserve
backwards compatibility.
-An enumeration type is a dictionary containing a single key who's value is a
+=== Enumeration types ===
+
+An enumeration type is a dictionary containing a single key whose value is a
list of strings. An example enumeration is:
{ 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] }
-Generally speaking, complex types and enums should always use CamelCase for
-the type names.
+=== Union types ===
+
+Union types are used to let the user choose between several different data
+types. A union type is defined using a dictionary as explained in the
+following paragraphs.
+
+
+A simple union type defines a mapping from discriminator values to data types
+like in this example:
+
+ { 'type': 'FileOptions', 'data': { 'filename': 'str' } }
+ { 'type': 'Qcow2Options',
+ 'data': { 'backing-file': 'str', 'lazy-refcounts': 'bool' } }
+
+ { 'union': 'BlockdevOptions',
+ 'data': { 'file': 'FileOptions',
+ 'qcow2': 'Qcow2Options' } }
+
+In the QMP wire format, a simple union is represented by a dictionary that
+contains the 'type' field as a discriminator, and a 'data' field that is of the
+specified data type corresponding to the discriminator value:
+
+ { "type": "qcow2", "data" : { "backing-file": "/some/place/my-image",
+ "lazy-refcounts": true } }
+
+
+A union definition can specify a complex type as its base. In this case, the
+fields of the complex type are included as top-level fields of the union
+dictionary in the QMP wire format. An example definition is:
+
+ { 'type': 'BlockdevCommonOptions', 'data': { 'readonly': 'bool' } }
+ { 'union': 'BlockdevOptions',
+ 'base': 'BlockdevCommonOptions',
+ 'data': { 'raw': 'RawOptions',
+ 'qcow2': 'Qcow2Options' } }
+
+And it looks like this on the wire:
+
+ { "type": "qcow2",
+ "readonly": false,
+ "data" : { "backing-file": "/some/place/my-image",
+ "lazy-refcounts": true } }
+
+
+Flat union types avoid the nesting on the wire. They are used whenever a
+specific field of the base type is declared as the discriminator ('type' is
+then no longer generated). The discriminator must always be a string field.
+The above example can then be modified as follows:
+
+ { 'type': 'BlockdevCommonOptions',
+ 'data': { 'driver': 'str', 'readonly': 'bool' } }
+ { 'union': 'BlockdevOptions',
+ 'base': 'BlockdevCommonOptions',
+ 'discriminator': 'driver',
+ 'data': { 'raw': 'RawOptions',
+ 'qcow2': 'Qcow2Options' } }
+
+Resulting in this JSON object:
+
+ { "driver": "qcow2",
+ "readonly": false,
+ "backing-file": "/some/place/my-image",
+ "lazy-refcounts": true }
+
+
+A special type of unions are anonymous unions. They don't form a dictionary in
+the wire format but allow the direct use of different types in their place. As
+they aren't structured, they don't have any explicit discriminator but use
+the (QObject) data type of their value as an implicit discriminator. This means
+that they are restricted to using only one discriminator value per QObject
+type. For example, you cannot have two different complex types in an anonymous
+union, or two different integer types.
+
+Anonymous unions are declared using an empty dictionary as their discriminator.
+The discriminator values never appear on the wire, they are only used in the
+generated C code. Anonymous unions cannot have a base type.
+
+ { 'union': 'BlockRef',
+ 'discriminator': {},
+ 'data': { 'definition': 'BlockdevOptions',
+ 'reference': 'str' } }
+
+This example allows using both of the following example objects:
+
+ { "file": "my_existing_block_device_id" }
+ { "file": { "driver": "file",
+ "readonly": false,
+ 'filename': "/tmp/mydisk.qcow2" } }
+
+
+=== Commands ===
Commands are defined by using a list containing three members. The first
member is the command name, the second member is a dictionary containing
@@ -65,8 +162,6 @@
'data': { 'arg1': 'str', '*arg2': 'str' },
'returns': 'str' }
-Command names should be all lower case with words separated by a hyphen.
-
== Code generation ==
diff --git a/docs/rdma.txt b/docs/rdma.txt
index 45d1c8a..8d1e003 100644
--- a/docs/rdma.txt
+++ b/docs/rdma.txt
@@ -199,7 +199,7 @@
check this field and register all requests found in the array of commands located
in the data portion and return an equal number of results in the response.
The maximum number of repeats is hard-coded to 4096. This is a conservative
-limit based on the maximum size of a SEND message along with emperical
+limit based on the maximum size of a SEND message along with empirical
observations on the maximum future benefit of simultaneous page registrations.
The 'type' field has 12 different command values:
diff --git a/dump.c b/dump.c
index 6a3a72a..c0dae2c 100644
--- a/dump.c
+++ b/dump.c
@@ -59,6 +59,7 @@
}
typedef struct DumpState {
+ GuestPhysBlockList guest_phys_blocks;
ArchDumpInfo dump_info;
MemoryMappingList list;
uint16_t phdr_num;
@@ -69,7 +70,7 @@
hwaddr memory_offset;
int fd;
- RAMBlock *block;
+ GuestPhysBlock *next_block;
ram_addr_t start;
bool has_filter;
int64_t begin;
@@ -81,6 +82,7 @@
{
int ret = 0;
+ guest_phys_blocks_free(&s->guest_phys_blocks);
memory_mapping_list_free(&s->list);
if (s->fd != -1) {
close(s->fd);
@@ -187,7 +189,8 @@
}
static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping,
- int phdr_index, hwaddr offset)
+ int phdr_index, hwaddr offset,
+ hwaddr filesz)
{
Elf64_Phdr phdr;
int ret;
@@ -197,15 +200,12 @@
phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
phdr.p_offset = cpu_convert_to_target64(offset, endian);
phdr.p_paddr = cpu_convert_to_target64(memory_mapping->phys_addr, endian);
- if (offset == -1) {
- /* When the memory is not stored into vmcore, offset will be -1 */
- phdr.p_filesz = 0;
- } else {
- phdr.p_filesz = cpu_convert_to_target64(memory_mapping->length, endian);
- }
+ phdr.p_filesz = cpu_convert_to_target64(filesz, endian);
phdr.p_memsz = cpu_convert_to_target64(memory_mapping->length, endian);
phdr.p_vaddr = cpu_convert_to_target64(memory_mapping->virt_addr, endian);
+ assert(memory_mapping->length >= filesz);
+
ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
if (ret < 0) {
dump_error(s, "dump: failed to write program header table.\n");
@@ -216,7 +216,8 @@
}
static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping,
- int phdr_index, hwaddr offset)
+ int phdr_index, hwaddr offset,
+ hwaddr filesz)
{
Elf32_Phdr phdr;
int ret;
@@ -226,15 +227,12 @@
phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
phdr.p_offset = cpu_convert_to_target32(offset, endian);
phdr.p_paddr = cpu_convert_to_target32(memory_mapping->phys_addr, endian);
- if (offset == -1) {
- /* When the memory is not stored into vmcore, offset will be -1 */
- phdr.p_filesz = 0;
- } else {
- phdr.p_filesz = cpu_convert_to_target32(memory_mapping->length, endian);
- }
+ phdr.p_filesz = cpu_convert_to_target32(filesz, endian);
phdr.p_memsz = cpu_convert_to_target32(memory_mapping->length, endian);
phdr.p_vaddr = cpu_convert_to_target32(memory_mapping->virt_addr, endian);
+ assert(memory_mapping->length >= filesz);
+
ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
if (ret < 0) {
dump_error(s, "dump: failed to write program header table.\n");
@@ -393,14 +391,14 @@
}
/* write the memroy to vmcore. 1 page per I/O. */
-static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
+static int write_memory(DumpState *s, GuestPhysBlock *block, ram_addr_t start,
int64_t size)
{
int64_t i;
int ret;
for (i = 0; i < size / TARGET_PAGE_SIZE; i++) {
- ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
+ ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE,
TARGET_PAGE_SIZE);
if (ret < 0) {
return ret;
@@ -408,7 +406,7 @@
}
if ((size % TARGET_PAGE_SIZE) != 0) {
- ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
+ ret = write_data(s, block->host_addr + start + i * TARGET_PAGE_SIZE,
size % TARGET_PAGE_SIZE);
if (ret < 0) {
return ret;
@@ -418,57 +416,71 @@
return 0;
}
-/* get the memory's offset in the vmcore */
-static hwaddr get_offset(hwaddr phys_addr,
- DumpState *s)
+/* get the memory's offset and size in the vmcore */
+static void get_offset_range(hwaddr phys_addr,
+ ram_addr_t mapping_length,
+ DumpState *s,
+ hwaddr *p_offset,
+ hwaddr *p_filesz)
{
- RAMBlock *block;
+ GuestPhysBlock *block;
hwaddr offset = s->memory_offset;
int64_t size_in_block, start;
+ /* When the memory is not stored into vmcore, offset will be -1 */
+ *p_offset = -1;
+ *p_filesz = 0;
+
if (s->has_filter) {
if (phys_addr < s->begin || phys_addr >= s->begin + s->length) {
- return -1;
+ return;
}
}
- QTAILQ_FOREACH(block, &ram_list.blocks, next) {
+ QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
if (s->has_filter) {
- if (block->offset >= s->begin + s->length ||
- block->offset + block->length <= s->begin) {
+ if (block->target_start >= s->begin + s->length ||
+ block->target_end <= s->begin) {
/* This block is out of the range */
continue;
}
- if (s->begin <= block->offset) {
- start = block->offset;
+ if (s->begin <= block->target_start) {
+ start = block->target_start;
} else {
start = s->begin;
}
- size_in_block = block->length - (start - block->offset);
- if (s->begin + s->length < block->offset + block->length) {
- size_in_block -= block->offset + block->length -
- (s->begin + s->length);
+ size_in_block = block->target_end - start;
+ if (s->begin + s->length < block->target_end) {
+ size_in_block -= block->target_end - (s->begin + s->length);
}
} else {
- start = block->offset;
- size_in_block = block->length;
+ start = block->target_start;
+ size_in_block = block->target_end - block->target_start;
}
if (phys_addr >= start && phys_addr < start + size_in_block) {
- return phys_addr - start + offset;
+ *p_offset = phys_addr - start + offset;
+
+ /* The offset range mapped from the vmcore file must not spill over
+ * the GuestPhysBlock, clamp it. The rest of the mapping will be
+ * zero-filled in memory at load time; see
+ * <http://refspecs.linuxbase.org/elf/gabi4+/ch5.pheader.html>.
+ */
+ *p_filesz = phys_addr + mapping_length <= start + size_in_block ?
+ mapping_length :
+ size_in_block - (phys_addr - start);
+ return;
}
offset += size_in_block;
}
-
- return -1;
}
static int write_elf_loads(DumpState *s)
{
- hwaddr offset;
+ hwaddr offset, filesz;
MemoryMapping *memory_mapping;
uint32_t phdr_index = 1;
int ret;
@@ -481,11 +493,15 @@
}
QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
- offset = get_offset(memory_mapping->phys_addr, s);
+ get_offset_range(memory_mapping->phys_addr,
+ memory_mapping->length,
+ s, &offset, &filesz);
if (s->dump_info.d_class == ELFCLASS64) {
- ret = write_elf64_load(s, memory_mapping, phdr_index++, offset);
+ ret = write_elf64_load(s, memory_mapping, phdr_index++, offset,
+ filesz);
} else {
- ret = write_elf32_load(s, memory_mapping, phdr_index++, offset);
+ ret = write_elf32_load(s, memory_mapping, phdr_index++, offset,
+ filesz);
}
if (ret < 0) {
@@ -596,7 +612,7 @@
return 0;
}
-static int get_next_block(DumpState *s, RAMBlock *block)
+static int get_next_block(DumpState *s, GuestPhysBlock *block)
{
while (1) {
block = QTAILQ_NEXT(block, next);
@@ -606,16 +622,16 @@
}
s->start = 0;
- s->block = block;
+ s->next_block = block;
if (s->has_filter) {
- if (block->offset >= s->begin + s->length ||
- block->offset + block->length <= s->begin) {
+ if (block->target_start >= s->begin + s->length ||
+ block->target_end <= s->begin) {
/* This block is out of the range */
continue;
}
- if (s->begin > block->offset) {
- s->start = s->begin - block->offset;
+ if (s->begin > block->target_start) {
+ s->start = s->begin - block->target_start;
}
}
@@ -626,18 +642,18 @@
/* write all memory to vmcore */
static int dump_iterate(DumpState *s)
{
- RAMBlock *block;
+ GuestPhysBlock *block;
int64_t size;
int ret;
while (1) {
- block = s->block;
+ block = s->next_block;
- size = block->length;
+ size = block->target_end - block->target_start;
if (s->has_filter) {
size -= s->start;
- if (s->begin + s->length < block->offset + block->length) {
- size -= block->offset + block->length - (s->begin + s->length);
+ if (s->begin + s->length < block->target_end) {
+ size -= block->target_end - (s->begin + s->length);
}
}
ret = write_memory(s, block, s->start, size);
@@ -672,23 +688,23 @@
static ram_addr_t get_start_block(DumpState *s)
{
- RAMBlock *block;
+ GuestPhysBlock *block;
if (!s->has_filter) {
- s->block = QTAILQ_FIRST(&ram_list.blocks);
+ s->next_block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
return 0;
}
- QTAILQ_FOREACH(block, &ram_list.blocks, next) {
- if (block->offset >= s->begin + s->length ||
- block->offset + block->length <= s->begin) {
+ QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
+ if (block->target_start >= s->begin + s->length ||
+ block->target_end <= s->begin) {
/* This block is out of the range */
continue;
}
- s->block = block;
- if (s->begin > block->offset) {
- s->start = s->begin - block->offset;
+ s->next_block = block;
+ if (s->begin > block->target_start) {
+ s->start = s->begin - block->target_start;
} else {
s->start = 0;
}
@@ -713,24 +729,8 @@
s->resume = false;
}
- s->errp = errp;
- s->fd = fd;
- s->has_filter = has_filter;
- s->begin = begin;
- s->length = length;
- s->start = get_start_block(s);
- if (s->start == -1) {
- error_set(errp, QERR_INVALID_PARAMETER, "begin");
- goto cleanup;
- }
-
- /*
- * get dump info: endian, class and architecture.
- * If the target architecture is not supported, cpu_get_dump_info() will
- * return -1.
- *
- * If we use KVM, we should synchronize the registers before we get dump
- * info.
+ /* If we use KVM, we should synchronize the registers before we get dump
+ * info or physmap info.
*/
cpu_synchronize_all_states();
nr_cpus = 0;
@@ -738,7 +738,26 @@
nr_cpus++;
}
- ret = cpu_get_dump_info(&s->dump_info);
+ s->errp = errp;
+ s->fd = fd;
+ s->has_filter = has_filter;
+ s->begin = begin;
+ s->length = length;
+
+ guest_phys_blocks_init(&s->guest_phys_blocks);
+ guest_phys_blocks_append(&s->guest_phys_blocks);
+
+ s->start = get_start_block(s);
+ if (s->start == -1) {
+ error_set(errp, QERR_INVALID_PARAMETER, "begin");
+ goto cleanup;
+ }
+
+ /* get dump info: endian, class and architecture.
+ * If the target architecture is not supported, cpu_get_dump_info() will
+ * return -1.
+ */
+ ret = cpu_get_dump_info(&s->dump_info, &s->guest_phys_blocks);
if (ret < 0) {
error_set(errp, QERR_UNSUPPORTED);
goto cleanup;
@@ -754,13 +773,13 @@
/* get memory mapping */
memory_mapping_list_init(&s->list);
if (paging) {
- qemu_get_guest_memory_mapping(&s->list, &err);
+ qemu_get_guest_memory_mapping(&s->list, &s->guest_phys_blocks, &err);
if (err != NULL) {
error_propagate(errp, err);
goto cleanup;
}
} else {
- qemu_get_guest_simple_memory_mapping(&s->list);
+ qemu_get_guest_simple_memory_mapping(&s->list, &s->guest_phys_blocks);
}
if (s->has_filter) {
@@ -812,6 +831,8 @@
return 0;
cleanup:
+ guest_phys_blocks_free(&s->guest_phys_blocks);
+
if (s->resume) {
vm_start();
}
@@ -859,7 +880,7 @@
return;
}
- s = g_malloc(sizeof(DumpState));
+ s = g_malloc0(sizeof(DumpState));
ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
if (ret < 0) {
diff --git a/exec.c b/exec.c
index 7997002..3ca9381 100644
--- a/exec.c
+++ b/exec.c
@@ -402,11 +402,14 @@
#if defined(CONFIG_USER_ONLY)
cpu_list_unlock();
#endif
- vmstate_register(NULL, cpu_index, &vmstate_cpu_common, cpu);
+ if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
+ vmstate_register(NULL, cpu_index, &vmstate_cpu_common, cpu);
+ }
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
cpu_save, cpu_load, env);
assert(cc->vmsd == NULL);
+ assert(qdev_get_vmsd(DEVICE(cpu)) == NULL);
#endif
if (cc->vmsd != NULL) {
vmstate_register(NULL, cpu_index, cc->vmsd, cpu);
@@ -590,15 +593,14 @@
void cpu_single_step(CPUState *cpu, int enabled)
{
#if defined(TARGET_HAS_ICE)
- CPUArchState *env = cpu->env_ptr;
-
if (cpu->singlestep_enabled != enabled) {
cpu->singlestep_enabled = enabled;
if (kvm_enabled()) {
- kvm_update_guest_debug(env, 0);
+ kvm_update_guest_debug(cpu, 0);
} else {
/* must flush all the translated code to avoid inconsistencies */
/* XXX: only flush what is necessary */
+ CPUArchState *env = cpu->env_ptr;
tb_flush(env);
}
}
@@ -646,6 +648,10 @@
CPUWatchpoint *wp;
#endif
+ /* Reset non arch specific state */
+ cpu_reset(ENV_GET_CPU(new_env));
+
+ /* Copy arch specific state into the new CPU */
memcpy(new_env, env, sizeof(CPUArchState));
/* Clone all break/watchpoints.
diff --git a/gdbstub.c b/gdbstub.c
index 35ca7c2..9d067d6 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -40,7 +40,6 @@
#include "cpu.h"
#include "qemu/sockets.h"
#include "sysemu/kvm.h"
-#include "qemu/bitops.h"
static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
uint8_t *buf, int len, bool is_write)
@@ -316,10 +315,7 @@
static GDBState *gdbserver_state;
-/* 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. */
-static int gdb_has_xml;
+bool gdb_has_xml;
#ifdef CONFIG_USER_ONLY
/* XXX: This is not thread safe. Do we care? */
@@ -489,1319 +485,6 @@
return put_packet_binary(s, buf, strlen(buf));
}
-/* 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.
- */
-#define GET_REG8(val) do { \
- stb_p(mem_buf, val); \
- return 1; \
- } while(0)
-#define GET_REG16(val) do { \
- stw_p(mem_buf, val); \
- return 2; \
- } while(0)
-#define GET_REG32(val) do { \
- stl_p(mem_buf, val); \
- return 4; \
- } while(0)
-#define GET_REG64(val) do { \
- stq_p(mem_buf, val); \
- return 8; \
- } while(0)
-
-#if TARGET_LONG_BITS == 64
-#define GET_REGL(val) GET_REG64(val)
-#define ldtul_p(addr) ldq_p(addr)
-#else
-#define GET_REGL(val) GET_REG32(val)
-#define ldtul_p(addr) ldl_p(addr)
-#endif
-
-#if defined(TARGET_I386)
-
-#ifdef TARGET_X86_64
-static const int gpr_map[16] = {
- R_EAX, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP, R_ESP,
- 8, 9, 10, 11, 12, 13, 14, 15
-};
-#else
-#define gpr_map gpr_map32
-#endif
-static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
-
-#define NUM_CORE_REGS (CPU_NB_REGS * 2 + 25)
-
-#define IDX_IP_REG CPU_NB_REGS
-#define IDX_FLAGS_REG (IDX_IP_REG + 1)
-#define IDX_SEG_REGS (IDX_FLAGS_REG + 1)
-#define IDX_FP_REGS (IDX_SEG_REGS + 6)
-#define IDX_XMM_REGS (IDX_FP_REGS + 16)
-#define IDX_MXCSR_REG (IDX_XMM_REGS + CPU_NB_REGS)
-
-static int cpu_gdb_read_register(CPUX86State *env, uint8_t *mem_buf, int n)
-{
- if (n < CPU_NB_REGS) {
- if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
- GET_REG64(env->regs[gpr_map[n]]);
- } else if (n < CPU_NB_REGS32) {
- GET_REG32(env->regs[gpr_map32[n]]);
- }
- } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
-#ifdef USE_X86LDOUBLE
- /* FIXME: byteswap float values - after fixing fpregs layout. */
- memcpy(mem_buf, &env->fpregs[n - IDX_FP_REGS], 10);
-#else
- memset(mem_buf, 0, 10);
-#endif
- return 10;
- } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
- n -= IDX_XMM_REGS;
- if (n < CPU_NB_REGS32 ||
- (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
- stq_p(mem_buf, env->xmm_regs[n].XMM_Q(0));
- stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1));
- return 16;
- }
- } else {
- switch (n) {
- case IDX_IP_REG:
- if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
- GET_REG64(env->eip);
- } else {
- GET_REG32(env->eip);
- }
- case IDX_FLAGS_REG: GET_REG32(env->eflags);
-
- case IDX_SEG_REGS: GET_REG32(env->segs[R_CS].selector);
- case IDX_SEG_REGS + 1: GET_REG32(env->segs[R_SS].selector);
- case IDX_SEG_REGS + 2: GET_REG32(env->segs[R_DS].selector);
- case IDX_SEG_REGS + 3: GET_REG32(env->segs[R_ES].selector);
- case IDX_SEG_REGS + 4: GET_REG32(env->segs[R_FS].selector);
- case IDX_SEG_REGS + 5: GET_REG32(env->segs[R_GS].selector);
-
- case IDX_FP_REGS + 8: GET_REG32(env->fpuc);
- case IDX_FP_REGS + 9: GET_REG32((env->fpus & ~0x3800) |
- (env->fpstt & 0x7) << 11);
- case IDX_FP_REGS + 10: GET_REG32(0); /* ftag */
- case IDX_FP_REGS + 11: GET_REG32(0); /* fiseg */
- case IDX_FP_REGS + 12: GET_REG32(0); /* fioff */
- case IDX_FP_REGS + 13: GET_REG32(0); /* foseg */
- case IDX_FP_REGS + 14: GET_REG32(0); /* fooff */
- case IDX_FP_REGS + 15: GET_REG32(0); /* fop */
-
- case IDX_MXCSR_REG: GET_REG32(env->mxcsr);
- }
- }
- return 0;
-}
-
-static int cpu_x86_gdb_load_seg(CPUX86State *env, int sreg, uint8_t *mem_buf)
-{
- uint16_t selector = ldl_p(mem_buf);
-
- if (selector != env->segs[sreg].selector) {
-#if defined(CONFIG_USER_ONLY)
- cpu_x86_load_seg(env, sreg, selector);
-#else
- unsigned int limit, flags;
- target_ulong base;
-
- if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
- base = selector << 4;
- limit = 0xffff;
- flags = 0;
- } else {
- if (!cpu_x86_get_descr_debug(env, selector, &base, &limit, &flags))
- return 4;
- }
- cpu_x86_load_seg_cache(env, sreg, selector, base, limit, flags);
-#endif
- }
- return 4;
-}
-
-static int cpu_gdb_write_register(CPUX86State *env, uint8_t *mem_buf, int n)
-{
- uint32_t tmp;
-
- if (n < CPU_NB_REGS) {
- if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
- env->regs[gpr_map[n]] = ldtul_p(mem_buf);
- return sizeof(target_ulong);
- } else if (n < CPU_NB_REGS32) {
- n = gpr_map32[n];
- env->regs[n] &= ~0xffffffffUL;
- env->regs[n] |= (uint32_t)ldl_p(mem_buf);
- return 4;
- }
- } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
-#ifdef USE_X86LDOUBLE
- /* FIXME: byteswap float values - after fixing fpregs layout. */
- memcpy(&env->fpregs[n - IDX_FP_REGS], mem_buf, 10);
-#endif
- return 10;
- } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
- n -= IDX_XMM_REGS;
- if (n < CPU_NB_REGS32 ||
- (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
- env->xmm_regs[n].XMM_Q(0) = ldq_p(mem_buf);
- env->xmm_regs[n].XMM_Q(1) = ldq_p(mem_buf + 8);
- return 16;
- }
- } else {
- switch (n) {
- case IDX_IP_REG:
- if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
- env->eip = ldq_p(mem_buf);
- return 8;
- } else {
- env->eip &= ~0xffffffffUL;
- env->eip |= (uint32_t)ldl_p(mem_buf);
- return 4;
- }
- case IDX_FLAGS_REG:
- env->eflags = ldl_p(mem_buf);
- return 4;
-
- case IDX_SEG_REGS: return cpu_x86_gdb_load_seg(env, R_CS, mem_buf);
- case IDX_SEG_REGS + 1: return cpu_x86_gdb_load_seg(env, R_SS, mem_buf);
- case IDX_SEG_REGS + 2: return cpu_x86_gdb_load_seg(env, R_DS, mem_buf);
- case IDX_SEG_REGS + 3: return cpu_x86_gdb_load_seg(env, R_ES, mem_buf);
- case IDX_SEG_REGS + 4: return cpu_x86_gdb_load_seg(env, R_FS, mem_buf);
- case IDX_SEG_REGS + 5: return cpu_x86_gdb_load_seg(env, R_GS, mem_buf);
-
- case IDX_FP_REGS + 8:
- env->fpuc = ldl_p(mem_buf);
- return 4;
- case IDX_FP_REGS + 9:
- tmp = ldl_p(mem_buf);
- env->fpstt = (tmp >> 11) & 7;
- env->fpus = tmp & ~0x3800;
- return 4;
- case IDX_FP_REGS + 10: /* ftag */ return 4;
- case IDX_FP_REGS + 11: /* fiseg */ return 4;
- case IDX_FP_REGS + 12: /* fioff */ return 4;
- case IDX_FP_REGS + 13: /* foseg */ return 4;
- case IDX_FP_REGS + 14: /* fooff */ return 4;
- case IDX_FP_REGS + 15: /* fop */ return 4;
-
- case IDX_MXCSR_REG:
- env->mxcsr = ldl_p(mem_buf);
- return 4;
- }
- }
- /* Unrecognised register. */
- return 0;
-}
-
-#elif defined (TARGET_PPC)
-
-/* Old gdb always expects FP registers. Newer (xml-aware) gdb only
- expects whatever the target description contains. Due to a
- historical mishap the FP registers appear in between core integer
- regs and PC, MSR, CR, and so forth. We hack round this by giving the
- FP regs zero size when talking to a newer gdb. */
-#define NUM_CORE_REGS 71
-#if defined (TARGET_PPC64)
-#define GDB_CORE_XML "power64-core.xml"
-#else
-#define GDB_CORE_XML "power-core.xml"
-#endif
-
-static int cpu_gdb_read_register(CPUPPCState *env, uint8_t *mem_buf, int n)
-{
- if (n < 32) {
- /* gprs */
- GET_REGL(env->gpr[n]);
- } else if (n < 64) {
- /* fprs */
- if (gdb_has_xml)
- return 0;
- stfq_p(mem_buf, env->fpr[n-32]);
- return 8;
- } else {
- switch (n) {
- case 64: GET_REGL(env->nip);
- case 65: GET_REGL(env->msr);
- case 66:
- {
- uint32_t cr = 0;
- int i;
- for (i = 0; i < 8; i++)
- cr |= env->crf[i] << (32 - ((i + 1) * 4));
- GET_REG32(cr);
- }
- case 67: GET_REGL(env->lr);
- case 68: GET_REGL(env->ctr);
- case 69: GET_REGL(env->xer);
- case 70:
- {
- if (gdb_has_xml)
- return 0;
- GET_REG32(env->fpscr);
- }
- }
- }
- return 0;
-}
-
-static int cpu_gdb_write_register(CPUPPCState *env, uint8_t *mem_buf, int n)
-{
- if (n < 32) {
- /* gprs */
- env->gpr[n] = ldtul_p(mem_buf);
- return sizeof(target_ulong);
- } else if (n < 64) {
- /* fprs */
- if (gdb_has_xml)
- return 0;
- env->fpr[n-32] = ldfq_p(mem_buf);
- return 8;
- } else {
- switch (n) {
- case 64:
- env->nip = ldtul_p(mem_buf);
- return sizeof(target_ulong);
- case 65:
- ppc_store_msr(env, ldtul_p(mem_buf));
- return sizeof(target_ulong);
- case 66:
- {
- uint32_t cr = ldl_p(mem_buf);
- int i;
- for (i = 0; i < 8; i++)
- env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF;
- return 4;
- }
- case 67:
- env->lr = ldtul_p(mem_buf);
- return sizeof(target_ulong);
- case 68:
- env->ctr = ldtul_p(mem_buf);
- return sizeof(target_ulong);
- case 69:
- env->xer = ldtul_p(mem_buf);
- return sizeof(target_ulong);
- case 70:
- /* fpscr */
- if (gdb_has_xml)
- return 0;
- store_fpscr(env, ldtul_p(mem_buf), 0xffffffff);
- return sizeof(target_ulong);
- }
- }
- return 0;
-}
-
-#elif defined (TARGET_SPARC)
-
-#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
-#define NUM_CORE_REGS 86
-#else
-#define NUM_CORE_REGS 72
-#endif
-
-#ifdef TARGET_ABI32
-#define GET_REGA(val) GET_REG32(val)
-#else
-#define GET_REGA(val) GET_REGL(val)
-#endif
-
-static int cpu_gdb_read_register(CPUSPARCState *env, uint8_t *mem_buf, int n)
-{
- if (n < 8) {
- /* g0..g7 */
- GET_REGA(env->gregs[n]);
- }
- if (n < 32) {
- /* register window */
- GET_REGA(env->regwptr[n - 8]);
- }
-#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
- if (n < 64) {
- /* fprs */
- if (n & 1) {
- GET_REG32(env->fpr[(n - 32) / 2].l.lower);
- } else {
- GET_REG32(env->fpr[(n - 32) / 2].l.upper);
- }
- }
- /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
- switch (n) {
- case 64: GET_REGA(env->y);
- case 65: GET_REGA(cpu_get_psr(env));
- case 66: GET_REGA(env->wim);
- case 67: GET_REGA(env->tbr);
- case 68: GET_REGA(env->pc);
- case 69: GET_REGA(env->npc);
- case 70: GET_REGA(env->fsr);
- case 71: GET_REGA(0); /* csr */
- default: GET_REGA(0);
- }
-#else
- if (n < 64) {
- /* f0-f31 */
- if (n & 1) {
- GET_REG32(env->fpr[(n - 32) / 2].l.lower);
- } else {
- GET_REG32(env->fpr[(n - 32) / 2].l.upper);
- }
- }
- if (n < 80) {
- /* f32-f62 (double width, even numbers only) */
- GET_REG64(env->fpr[(n - 32) / 2].ll);
- }
- switch (n) {
- case 80: GET_REGL(env->pc);
- case 81: GET_REGL(env->npc);
- case 82: GET_REGL((cpu_get_ccr(env) << 32) |
- ((env->asi & 0xff) << 24) |
- ((env->pstate & 0xfff) << 8) |
- cpu_get_cwp64(env));
- case 83: GET_REGL(env->fsr);
- case 84: GET_REGL(env->fprs);
- case 85: GET_REGL(env->y);
- }
-#endif
- return 0;
-}
-
-static int cpu_gdb_write_register(CPUSPARCState *env, uint8_t *mem_buf, int n)
-{
-#if defined(TARGET_ABI32)
- abi_ulong tmp;
-
- tmp = ldl_p(mem_buf);
-#else
- target_ulong tmp;
-
- tmp = ldtul_p(mem_buf);
-#endif
-
- if (n < 8) {
- /* g0..g7 */
- env->gregs[n] = tmp;
- } else if (n < 32) {
- /* register window */
- env->regwptr[n - 8] = tmp;
- }
-#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
- else if (n < 64) {
- /* fprs */
- /* f0-f31 */
- if (n & 1) {
- env->fpr[(n - 32) / 2].l.lower = tmp;
- } else {
- env->fpr[(n - 32) / 2].l.upper = tmp;
- }
- } else {
- /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
- switch (n) {
- case 64: env->y = tmp; break;
- case 65: cpu_put_psr(env, tmp); break;
- case 66: env->wim = tmp; break;
- case 67: env->tbr = tmp; break;
- case 68: env->pc = tmp; break;
- case 69: env->npc = tmp; break;
- case 70: env->fsr = tmp; break;
- default: return 0;
- }
- }
- return 4;
-#else
- else if (n < 64) {
- /* f0-f31 */
- tmp = ldl_p(mem_buf);
- if (n & 1) {
- env->fpr[(n - 32) / 2].l.lower = tmp;
- } else {
- env->fpr[(n - 32) / 2].l.upper = tmp;
- }
- return 4;
- } else if (n < 80) {
- /* f32-f62 (double width, even numbers only) */
- env->fpr[(n - 32) / 2].ll = tmp;
- } else {
- switch (n) {
- case 80: env->pc = tmp; break;
- case 81: env->npc = tmp; break;
- case 82:
- cpu_put_ccr(env, tmp >> 32);
- env->asi = (tmp >> 24) & 0xff;
- env->pstate = (tmp >> 8) & 0xfff;
- cpu_put_cwp64(env, tmp & 0xff);
- break;
- case 83: env->fsr = tmp; break;
- case 84: env->fprs = tmp; break;
- case 85: env->y = tmp; break;
- default: return 0;
- }
- }
- return 8;
-#endif
-}
-#elif defined (TARGET_ARM)
-
-/* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect
- whatever the target description contains. Due to a historical mishap
- the FPA registers appear in between core integer regs and the CPSR.
- We hack round this by giving the FPA regs zero size when talking to a
- newer gdb. */
-#define NUM_CORE_REGS 26
-#define GDB_CORE_XML "arm-core.xml"
-
-static int cpu_gdb_read_register(CPUARMState *env, uint8_t *mem_buf, int n)
-{
- if (n < 16) {
- /* Core integer register. */
- GET_REG32(env->regs[n]);
- }
- if (n < 24) {
- /* FPA registers. */
- if (gdb_has_xml)
- return 0;
- memset(mem_buf, 0, 12);
- return 12;
- }
- switch (n) {
- case 24:
- /* FPA status register. */
- if (gdb_has_xml)
- return 0;
- GET_REG32(0);
- case 25:
- /* CPSR */
- GET_REG32(cpsr_read(env));
- }
- /* Unknown register. */
- return 0;
-}
-
-static int cpu_gdb_write_register(CPUARMState *env, uint8_t *mem_buf, int n)
-{
- uint32_t tmp;
-
- tmp = ldl_p(mem_buf);
-
- /* Mask out low bit of PC to workaround gdb bugs. This will probably
- cause problems if we ever implement the Jazelle DBX extensions. */
- if (n == 15)
- tmp &= ~1;
-
- if (n < 16) {
- /* Core integer register. */
- env->regs[n] = tmp;
- return 4;
- }
- if (n < 24) { /* 16-23 */
- /* FPA registers (ignored). */
- if (gdb_has_xml)
- return 0;
- return 12;
- }
- switch (n) {
- case 24:
- /* FPA status register (ignored). */
- if (gdb_has_xml)
- return 0;
- return 4;
- case 25:
- /* CPSR */
- cpsr_write (env, tmp, 0xffffffff);
- return 4;
- }
- /* Unknown register. */
- return 0;
-}
-
-#elif defined (TARGET_M68K)
-
-#define NUM_CORE_REGS 18
-
-#define GDB_CORE_XML "cf-core.xml"
-
-static int cpu_gdb_read_register(CPUM68KState *env, uint8_t *mem_buf, int n)
-{
- if (n < 8) {
- /* D0-D7 */
- GET_REG32(env->dregs[n]);
- } else if (n < 16) {
- /* A0-A7 */
- GET_REG32(env->aregs[n - 8]);
- } else {
- switch (n) {
- case 16: GET_REG32(env->sr);
- case 17: GET_REG32(env->pc);
- }
- }
- /* FP registers not included here because they vary between
- ColdFire and m68k. Use XML bits for these. */
- return 0;
-}
-
-static int cpu_gdb_write_register(CPUM68KState *env, uint8_t *mem_buf, int n)
-{
- uint32_t tmp;
-
- tmp = ldl_p(mem_buf);
-
- if (n < 8) {
- /* D0-D7 */
- env->dregs[n] = tmp;
- } else if (n < 16) {
- /* A0-A7 */
- env->aregs[n - 8] = tmp;
- } else {
- switch (n) {
- case 16: env->sr = tmp; break;
- case 17: env->pc = tmp; break;
- default: return 0;
- }
- }
- return 4;
-}
-#elif defined (TARGET_MIPS)
-
-#define NUM_CORE_REGS 73
-
-static int cpu_gdb_read_register(CPUMIPSState *env, uint8_t *mem_buf, int n)
-{
- if (n < 32) {
- GET_REGL(env->active_tc.gpr[n]);
- }
- if (env->CP0_Config1 & (1 << CP0C1_FP)) {
- if (n >= 38 && n < 70) {
- if (env->CP0_Status & (1 << CP0St_FR))
- GET_REGL(env->active_fpu.fpr[n - 38].d);
- else
- GET_REGL(env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]);
- }
- switch (n) {
- case 70: GET_REGL((int32_t)env->active_fpu.fcr31);
- case 71: GET_REGL((int32_t)env->active_fpu.fcr0);
- }
- }
- switch (n) {
- case 32: GET_REGL((int32_t)env->CP0_Status);
- case 33: GET_REGL(env->active_tc.LO[0]);
- case 34: GET_REGL(env->active_tc.HI[0]);
- case 35: GET_REGL(env->CP0_BadVAddr);
- case 36: GET_REGL((int32_t)env->CP0_Cause);
- case 37: GET_REGL(env->active_tc.PC | !!(env->hflags & MIPS_HFLAG_M16));
- case 72: GET_REGL(0); /* fp */
- case 89: GET_REGL((int32_t)env->CP0_PRid);
- }
- if (n >= 73 && n <= 88) {
- /* 16 embedded regs. */
- GET_REGL(0);
- }
-
- return 0;
-}
-
-/* convert MIPS rounding mode in FCR31 to IEEE library */
-static unsigned int ieee_rm[] =
- {
- float_round_nearest_even,
- float_round_to_zero,
- float_round_up,
- float_round_down
- };
-#define RESTORE_ROUNDING_MODE \
- set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status)
-
-static int cpu_gdb_write_register(CPUMIPSState *env, uint8_t *mem_buf, int n)
-{
- target_ulong tmp;
-
- tmp = ldtul_p(mem_buf);
-
- if (n < 32) {
- env->active_tc.gpr[n] = tmp;
- return sizeof(target_ulong);
- }
- if (env->CP0_Config1 & (1 << CP0C1_FP)
- && n >= 38 && n < 73) {
- if (n < 70) {
- if (env->CP0_Status & (1 << CP0St_FR))
- env->active_fpu.fpr[n - 38].d = tmp;
- else
- env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp;
- }
- switch (n) {
- case 70:
- env->active_fpu.fcr31 = tmp & 0xFF83FFFF;
- /* set rounding mode */
- RESTORE_ROUNDING_MODE;
- break;
- case 71: env->active_fpu.fcr0 = tmp; break;
- }
- return sizeof(target_ulong);
- }
- switch (n) {
- case 32: env->CP0_Status = tmp; break;
- case 33: env->active_tc.LO[0] = tmp; break;
- case 34: env->active_tc.HI[0] = tmp; break;
- case 35: env->CP0_BadVAddr = tmp; break;
- case 36: env->CP0_Cause = tmp; break;
- case 37:
- env->active_tc.PC = tmp & ~(target_ulong)1;
- if (tmp & 1) {
- env->hflags |= MIPS_HFLAG_M16;
- } else {
- env->hflags &= ~(MIPS_HFLAG_M16);
- }
- break;
- case 72: /* fp, ignored */ break;
- default:
- if (n > 89)
- return 0;
- /* Other registers are readonly. Ignore writes. */
- break;
- }
-
- return sizeof(target_ulong);
-}
-#elif defined(TARGET_OPENRISC)
-
-#define NUM_CORE_REGS (32 + 3)
-
-static int cpu_gdb_read_register(CPUOpenRISCState *env, uint8_t *mem_buf, int n)
-{
- if (n < 32) {
- GET_REG32(env->gpr[n]);
- } else {
- switch (n) {
- case 32: /* PPC */
- GET_REG32(env->ppc);
- break;
-
- case 33: /* NPC */
- GET_REG32(env->npc);
- break;
-
- case 34: /* SR */
- GET_REG32(env->sr);
- break;
-
- default:
- break;
- }
- }
- return 0;
-}
-
-static int cpu_gdb_write_register(CPUOpenRISCState *env,
- uint8_t *mem_buf, int n)
-{
- uint32_t tmp;
-
- if (n > NUM_CORE_REGS) {
- return 0;
- }
-
- tmp = ldl_p(mem_buf);
-
- if (n < 32) {
- env->gpr[n] = tmp;
- } else {
- switch (n) {
- case 32: /* PPC */
- env->ppc = tmp;
- break;
-
- case 33: /* NPC */
- env->npc = tmp;
- break;
-
- case 34: /* SR */
- env->sr = tmp;
- break;
-
- default:
- break;
- }
- }
- return 4;
-}
-#elif defined (TARGET_SH4)
-
-/* Hint: Use "set architecture sh4" in GDB to see fpu registers */
-/* FIXME: We should use XML for this. */
-
-#define NUM_CORE_REGS 59
-
-static int cpu_gdb_read_register(CPUSH4State *env, uint8_t *mem_buf, int n)
-{
- switch (n) {
- case 0 ... 7:
- if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
- GET_REGL(env->gregs[n + 16]);
- } else {
- GET_REGL(env->gregs[n]);
- }
- case 8 ... 15:
- GET_REGL(env->gregs[n]);
- case 16:
- GET_REGL(env->pc);
- case 17:
- GET_REGL(env->pr);
- case 18:
- GET_REGL(env->gbr);
- case 19:
- GET_REGL(env->vbr);
- case 20:
- GET_REGL(env->mach);
- case 21:
- GET_REGL(env->macl);
- case 22:
- GET_REGL(env->sr);
- case 23:
- GET_REGL(env->fpul);
- case 24:
- GET_REGL(env->fpscr);
- case 25 ... 40:
- if (env->fpscr & FPSCR_FR) {
- stfl_p(mem_buf, env->fregs[n - 9]);
- } else {
- stfl_p(mem_buf, env->fregs[n - 25]);
- }
- return 4;
- case 41:
- GET_REGL(env->ssr);
- case 42:
- GET_REGL(env->spc);
- case 43 ... 50:
- GET_REGL(env->gregs[n - 43]);
- case 51 ... 58:
- GET_REGL(env->gregs[n - (51 - 16)]);
- }
-
- return 0;
-}
-
-static int cpu_gdb_write_register(CPUSH4State *env, uint8_t *mem_buf, int n)
-{
- switch (n) {
- case 0 ... 7:
- if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
- env->gregs[n + 16] = ldl_p(mem_buf);
- } else {
- env->gregs[n] = ldl_p(mem_buf);
- }
- break;
- case 8 ... 15:
- env->gregs[n] = ldl_p(mem_buf);
- break;
- case 16:
- env->pc = ldl_p(mem_buf);
- break;
- case 17:
- env->pr = ldl_p(mem_buf);
- break;
- case 18:
- env->gbr = ldl_p(mem_buf);
- break;
- case 19:
- env->vbr = ldl_p(mem_buf);
- break;
- case 20:
- env->mach = ldl_p(mem_buf);
- break;
- case 21:
- env->macl = ldl_p(mem_buf);
- break;
- case 22:
- env->sr = ldl_p(mem_buf);
- break;
- case 23:
- env->fpul = ldl_p(mem_buf);
- break;
- case 24:
- env->fpscr = ldl_p(mem_buf);
- break;
- case 25 ... 40:
- if (env->fpscr & FPSCR_FR) {
- env->fregs[n - 9] = ldfl_p(mem_buf);
- } else {
- env->fregs[n - 25] = ldfl_p(mem_buf);
- }
- break;
- case 41:
- env->ssr = ldl_p(mem_buf);
- break;
- case 42:
- env->spc = ldl_p(mem_buf);
- break;
- case 43 ... 50:
- env->gregs[n - 43] = ldl_p(mem_buf);
- break;
- case 51 ... 58:
- env->gregs[n - (51 - 16)] = ldl_p(mem_buf);
- break;
- default: return 0;
- }
-
- return 4;
-}
-#elif defined (TARGET_MICROBLAZE)
-
-#define NUM_CORE_REGS (32 + 5)
-
-static int cpu_gdb_read_register(CPUMBState *env, uint8_t *mem_buf, int n)
-{
- if (n < 32) {
- GET_REG32(env->regs[n]);
- } else {
- GET_REG32(env->sregs[n - 32]);
- }
- return 0;
-}
-
-static int cpu_gdb_write_register(CPUMBState *env, uint8_t *mem_buf, int n)
-{
- uint32_t tmp;
-
- if (n > NUM_CORE_REGS)
- return 0;
-
- tmp = ldl_p(mem_buf);
-
- if (n < 32) {
- env->regs[n] = tmp;
- } else {
- env->sregs[n - 32] = tmp;
- }
- return 4;
-}
-#elif defined (TARGET_CRIS)
-
-#define NUM_CORE_REGS 49
-
-static int
-read_register_crisv10(CPUCRISState *env, uint8_t *mem_buf, int n)
-{
- if (n < 15) {
- GET_REG32(env->regs[n]);
- }
-
- if (n == 15) {
- GET_REG32(env->pc);
- }
-
- if (n < 32) {
- switch (n) {
- case 16:
- GET_REG8(env->pregs[n - 16]);
- break;
- case 17:
- GET_REG8(env->pregs[n - 16]);
- break;
- case 20:
- case 21:
- GET_REG16(env->pregs[n - 16]);
- break;
- default:
- if (n >= 23) {
- GET_REG32(env->pregs[n - 16]);
- }
- break;
- }
- }
- return 0;
-}
-
-static int cpu_gdb_read_register(CPUCRISState *env, uint8_t *mem_buf, int n)
-{
- uint8_t srs;
-
- if (env->pregs[PR_VR] < 32)
- return read_register_crisv10(env, mem_buf, n);
-
- srs = env->pregs[PR_SRS];
- if (n < 16) {
- GET_REG32(env->regs[n]);
- }
-
- if (n >= 21 && n < 32) {
- GET_REG32(env->pregs[n - 16]);
- }
- if (n >= 33 && n < 49) {
- GET_REG32(env->sregs[srs][n - 33]);
- }
- switch (n) {
- case 16: GET_REG8(env->pregs[0]);
- case 17: GET_REG8(env->pregs[1]);
- case 18: GET_REG32(env->pregs[2]);
- case 19: GET_REG8(srs);
- case 20: GET_REG16(env->pregs[4]);
- case 32: GET_REG32(env->pc);
- }
-
- return 0;
-}
-
-static int cpu_gdb_write_register(CPUCRISState *env, uint8_t *mem_buf, int n)
-{
- uint32_t tmp;
-
- if (n > 49)
- return 0;
-
- tmp = ldl_p(mem_buf);
-
- if (n < 16) {
- env->regs[n] = tmp;
- }
-
- if (n >= 21 && n < 32) {
- env->pregs[n - 16] = tmp;
- }
-
- /* FIXME: Should support function regs be writable? */
- switch (n) {
- case 16: return 1;
- case 17: return 1;
- case 18: env->pregs[PR_PID] = tmp; break;
- case 19: return 1;
- case 20: return 2;
- case 32: env->pc = tmp; break;
- }
-
- return 4;
-}
-#elif defined (TARGET_ALPHA)
-
-#define NUM_CORE_REGS 67
-
-static int cpu_gdb_read_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
-{
- uint64_t val;
- CPU_DoubleU d;
-
- switch (n) {
- case 0 ... 30:
- val = env->ir[n];
- break;
- case 32 ... 62:
- d.d = env->fir[n - 32];
- val = d.ll;
- break;
- case 63:
- val = cpu_alpha_load_fpcr(env);
- break;
- case 64:
- val = env->pc;
- break;
- case 66:
- val = env->unique;
- break;
- case 31:
- case 65:
- /* 31 really is the zero register; 65 is unassigned in the
- gdb protocol, but is still required to occupy 8 bytes. */
- val = 0;
- break;
- default:
- return 0;
- }
- GET_REGL(val);
-}
-
-static int cpu_gdb_write_register(CPUAlphaState *env, uint8_t *mem_buf, int n)
-{
- target_ulong tmp = ldtul_p(mem_buf);
- CPU_DoubleU d;
-
- switch (n) {
- case 0 ... 30:
- env->ir[n] = tmp;
- break;
- case 32 ... 62:
- d.ll = tmp;
- env->fir[n - 32] = d.d;
- break;
- case 63:
- cpu_alpha_store_fpcr(env, tmp);
- break;
- case 64:
- env->pc = tmp;
- break;
- case 66:
- env->unique = tmp;
- break;
- case 31:
- case 65:
- /* 31 really is the zero register; 65 is unassigned in the
- gdb protocol, but is still required to occupy 8 bytes. */
- break;
- default:
- return 0;
- }
- return 8;
-}
-#elif defined (TARGET_S390X)
-
-#define NUM_CORE_REGS S390_NUM_REGS
-
-static int cpu_gdb_read_register(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- uint64_t val;
- int cc_op;
-
- switch (n) {
- case S390_PSWM_REGNUM:
- cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr);
- val = deposit64(env->psw.mask, 44, 2, cc_op);
- GET_REGL(val);
- break;
- case S390_PSWA_REGNUM:
- GET_REGL(env->psw.addr);
- break;
- case S390_R0_REGNUM ... S390_R15_REGNUM:
- GET_REGL(env->regs[n-S390_R0_REGNUM]);
- break;
- case S390_A0_REGNUM ... S390_A15_REGNUM:
- GET_REG32(env->aregs[n-S390_A0_REGNUM]);
- break;
- case S390_FPC_REGNUM:
- GET_REG32(env->fpc);
- break;
- case S390_F0_REGNUM ... S390_F15_REGNUM:
- GET_REG64(env->fregs[n-S390_F0_REGNUM].ll);
- break;
- }
-
- return 0;
-}
-
-static int cpu_gdb_write_register(CPUS390XState *env, uint8_t *mem_buf, int n)
-{
- target_ulong tmpl;
- uint32_t tmp32;
- int r = 8;
- tmpl = ldtul_p(mem_buf);
- tmp32 = ldl_p(mem_buf);
-
- switch (n) {
- case S390_PSWM_REGNUM:
- env->psw.mask = tmpl;
- env->cc_op = extract64(tmpl, 44, 2);
- break;
- case S390_PSWA_REGNUM:
- env->psw.addr = tmpl;
- break;
- case S390_R0_REGNUM ... S390_R15_REGNUM:
- env->regs[n-S390_R0_REGNUM] = tmpl;
- break;
- case S390_A0_REGNUM ... S390_A15_REGNUM:
- env->aregs[n-S390_A0_REGNUM] = tmp32;
- r = 4;
- break;
- case S390_FPC_REGNUM:
- env->fpc = tmp32;
- r = 4;
- break;
- case S390_F0_REGNUM ... S390_F15_REGNUM:
- env->fregs[n-S390_F0_REGNUM].ll = tmpl;
- break;
- default:
- return 0;
- }
- return r;
-}
-#elif defined (TARGET_LM32)
-
-#include "hw/lm32/lm32_pic.h"
-#define NUM_CORE_REGS (32 + 7)
-
-static int cpu_gdb_read_register(CPULM32State *env, uint8_t *mem_buf, int n)
-{
- if (n < 32) {
- GET_REG32(env->regs[n]);
- } else {
- switch (n) {
- case 32:
- GET_REG32(env->pc);
- break;
- /* FIXME: put in right exception ID */
- case 33:
- GET_REG32(0);
- break;
- case 34:
- GET_REG32(env->eba);
- break;
- case 35:
- GET_REG32(env->deba);
- break;
- case 36:
- GET_REG32(env->ie);
- break;
- case 37:
- GET_REG32(lm32_pic_get_im(env->pic_state));
- break;
- case 38:
- GET_REG32(lm32_pic_get_ip(env->pic_state));
- break;
- }
- }
- return 0;
-}
-
-static int cpu_gdb_write_register(CPULM32State *env, uint8_t *mem_buf, int n)
-{
- uint32_t tmp;
-
- if (n > NUM_CORE_REGS) {
- return 0;
- }
-
- tmp = ldl_p(mem_buf);
-
- if (n < 32) {
- env->regs[n] = tmp;
- } else {
- switch (n) {
- case 32:
- env->pc = tmp;
- break;
- case 34:
- env->eba = tmp;
- break;
- case 35:
- env->deba = tmp;
- break;
- case 36:
- env->ie = tmp;
- break;
- case 37:
- lm32_pic_set_im(env->pic_state, tmp);
- break;
- case 38:
- lm32_pic_set_ip(env->pic_state, tmp);
- break;
- }
- }
- return 4;
-}
-#elif defined(TARGET_XTENSA)
-
-/* Use num_core_regs to see only non-privileged registers in an unmodified gdb.
- * Use num_regs to see all registers. gdb modification is required for that:
- * reset bit 0 in the 'flags' field of the registers definitions in the
- * gdb/xtensa-config.c inside gdb source tree or inside gdb overlay.
- */
-#define NUM_CORE_REGS (env->config->gdb_regmap.num_regs)
-#define num_g_regs NUM_CORE_REGS
-
-static int cpu_gdb_read_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
-{
- const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
-
- if (n < 0 || n >= env->config->gdb_regmap.num_regs) {
- return 0;
- }
-
- switch (reg->type) {
- case 9: /*pc*/
- GET_REG32(env->pc);
- break;
-
- case 1: /*ar*/
- xtensa_sync_phys_from_window(env);
- GET_REG32(env->phys_regs[(reg->targno & 0xff) % env->config->nareg]);
- break;
-
- case 2: /*SR*/
- GET_REG32(env->sregs[reg->targno & 0xff]);
- break;
-
- case 3: /*UR*/
- GET_REG32(env->uregs[reg->targno & 0xff]);
- break;
-
- case 4: /*f*/
- GET_REG32(float32_val(env->fregs[reg->targno & 0x0f]));
- break;
-
- case 8: /*a*/
- GET_REG32(env->regs[reg->targno & 0x0f]);
- break;
-
- default:
- qemu_log("%s from reg %d of unsupported type %d\n",
- __func__, n, reg->type);
- return 0;
- }
-}
-
-static int cpu_gdb_write_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
-{
- uint32_t tmp;
- const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
-
- if (n < 0 || n >= env->config->gdb_regmap.num_regs) {
- return 0;
- }
-
- tmp = ldl_p(mem_buf);
-
- switch (reg->type) {
- case 9: /*pc*/
- env->pc = tmp;
- break;
-
- case 1: /*ar*/
- env->phys_regs[(reg->targno & 0xff) % env->config->nareg] = tmp;
- xtensa_sync_window_from_phys(env);
- break;
-
- case 2: /*SR*/
- env->sregs[reg->targno & 0xff] = tmp;
- break;
-
- case 3: /*UR*/
- env->uregs[reg->targno & 0xff] = tmp;
- break;
-
- case 4: /*f*/
- env->fregs[reg->targno & 0x0f] = make_float32(tmp);
- break;
-
- case 8: /*a*/
- env->regs[reg->targno & 0x0f] = tmp;
- break;
-
- default:
- qemu_log("%s to reg %d of unsupported type %d\n",
- __func__, n, reg->type);
- return 0;
- }
-
- return 4;
-}
-#else
-
-#define NUM_CORE_REGS 0
-
-static int cpu_gdb_read_register(CPUArchState *env, uint8_t *mem_buf, int n)
-{
- return 0;
-}
-
-static int cpu_gdb_write_register(CPUArchState *env, uint8_t *mem_buf, int n)
-{
- return 0;
-}
-
-#endif
-
-#if !defined(TARGET_XTENSA)
-static int num_g_regs = NUM_CORE_REGS;
-#endif
-
-#ifdef GDB_CORE_XML
/* Encode data using the encoding for 'x' packets. */
static int memtox(char *buf, const char *mem, int len)
{
@@ -1823,7 +506,8 @@
return p - buf;
}
-static const char *get_feature_xml(const char *p, const char **newp)
+static const char *get_feature_xml(const char *p, const char **newp,
+ CPUClass *cc)
{
size_t len;
int i;
@@ -1847,7 +531,7 @@
"<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
"<target>"
"<xi:include href=\"%s\"/>",
- GDB_CORE_XML);
+ cc->gdb_core_xml_file);
for (r = cpu->gdb_regs; r; r = r->next) {
pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
@@ -1865,15 +549,16 @@
}
return name ? xml_builtin[i][1] : NULL;
}
-#endif
static int gdb_read_register(CPUState *cpu, uint8_t *mem_buf, int reg)
{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
CPUArchState *env = cpu->env_ptr;
GDBRegisterState *r;
- if (reg < NUM_CORE_REGS)
- return cpu_gdb_read_register(env, mem_buf, reg);
+ if (reg < cc->gdb_num_core_regs) {
+ return cc->gdb_read_register(cpu, mem_buf, reg);
+ }
for (r = cpu->gdb_regs; r; r = r->next) {
if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
@@ -1885,11 +570,13 @@
static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
CPUArchState *env = cpu->env_ptr;
GDBRegisterState *r;
- if (reg < NUM_CORE_REGS)
- return cpu_gdb_write_register(env, mem_buf, reg);
+ if (reg < cc->gdb_num_core_regs) {
+ return cc->gdb_write_register(cpu, mem_buf, reg);
+ }
for (r = cpu->gdb_regs; r; r = r->next) {
if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
@@ -1899,7 +586,6 @@
return 0;
}
-#if !defined(TARGET_XTENSA)
/* Register a supplemental set of CPU registers. If g_pos is nonzero it
specifies the first register number and these registers are included in
a standard "g" packet. Direction is relative to gdb, i.e. get_reg is
@@ -1912,7 +598,6 @@
{
GDBRegisterState *s;
GDBRegisterState **p;
- static int last_reg = NUM_CORE_REGS;
p = &cpu->gdb_regs;
while (*p) {
@@ -1923,25 +608,24 @@
}
s = g_new0(GDBRegisterState, 1);
- s->base_reg = last_reg;
+ s->base_reg = cpu->gdb_num_regs;
s->num_regs = num_regs;
s->get_reg = get_reg;
s->set_reg = set_reg;
s->xml = xml;
/* Add to end of list. */
- last_reg += num_regs;
+ cpu->gdb_num_regs += num_regs;
*p = s;
if (g_pos) {
if (g_pos != s->base_reg) {
fprintf(stderr, "Error: Bad gdb register numbering for '%s'\n"
"Expected %d got %d\n", xml, g_pos, s->base_reg);
} else {
- num_g_regs = last_reg;
+ cpu->gdb_num_g_regs = cpu->gdb_num_regs;
}
}
}
-#endif
#ifndef CONFIG_USER_ONLY
static const int xlat_gdb_type[] = {
@@ -2071,10 +755,8 @@
static int gdb_handle_packet(GDBState *s, const char *line_buf)
{
-#ifdef TARGET_XTENSA
- CPUArchState *env;
-#endif
CPUState *cpu;
+ CPUClass *cc;
const char *p;
uint32_t thread;
int ch, reg_size, type, res;
@@ -2221,11 +903,8 @@
break;
case 'g':
cpu_synchronize_state(s->g_cpu);
-#ifdef TARGET_XTENSA
- env = s->g_cpu->env_ptr;
-#endif
len = 0;
- for (addr = 0; addr < num_g_regs; addr++) {
+ for (addr = 0; addr < s->g_cpu->gdb_num_g_regs; addr++) {
reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
len += reg_size;
}
@@ -2234,13 +913,10 @@
break;
case 'G':
cpu_synchronize_state(s->g_cpu);
-#ifdef TARGET_XTENSA
- env = s->g_cpu->env_ptr;
-#endif
registers = mem_buf;
len = strlen(p) / 2;
hextomem((uint8_t *)registers, p, len);
- for (addr = 0; addr < num_g_regs && len > 0; addr++) {
+ for (addr = 0; addr < s->g_cpu->gdb_num_g_regs && len > 0; addr++) {
reg_size = gdb_write_register(s->g_cpu, registers, addr);
len -= reg_size;
registers += reg_size;
@@ -2443,20 +1119,25 @@
#endif /* !CONFIG_USER_ONLY */
if (strncmp(p, "Supported", 9) == 0) {
snprintf(buf, sizeof(buf), "PacketSize=%x", MAX_PACKET_LENGTH);
-#ifdef GDB_CORE_XML
- pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
-#endif
+ cc = CPU_GET_CLASS(first_cpu);
+ if (cc->gdb_core_xml_file != NULL) {
+ pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
+ }
put_packet(s, buf);
break;
}
-#ifdef GDB_CORE_XML
if (strncmp(p, "Xfer:features:read:", 19) == 0) {
const char *xml;
target_ulong total_len;
- gdb_has_xml = 1;
+ cc = CPU_GET_CLASS(first_cpu);
+ if (cc->gdb_core_xml_file == NULL) {
+ goto unknown_command;
+ }
+
+ gdb_has_xml = true;
p += 19;
- xml = get_feature_xml(p, &p);
+ xml = get_feature_xml(p, &p, cc);
if (!xml) {
snprintf(buf, sizeof(buf), "E00");
put_packet(s, buf);
@@ -2488,7 +1169,6 @@
put_packet_binary(s, buf, len + 1);
break;
}
-#endif
/* Unrecognised 'q' command. */
goto unknown_command;
@@ -2863,7 +1543,7 @@
s->c_cpu = first_cpu;
s->g_cpu = first_cpu;
s->fd = fd;
- gdb_has_xml = 0;
+ gdb_has_xml = false;
gdbserver_state = s;
@@ -2949,7 +1629,7 @@
switch (event) {
case CHR_EVENT_OPENED:
vm_stop(RUN_STATE_PAUSED);
- gdb_has_xml = 0;
+ gdb_has_xml = false;
break;
default:
break;
diff --git a/hmp.c b/hmp.c
index c45514b..fcca6ae 100644
--- a/hmp.c
+++ b/hmp.c
@@ -1195,13 +1195,13 @@
monitor_flush(status->mon);
}
- qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock) + 1000);
+ timer_mod(status->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
} else {
if (status->is_block_migration) {
monitor_printf(status->mon, "\n");
}
monitor_resume(status->mon);
- qemu_del_timer(status->timer);
+ timer_del(status->timer);
g_free(status);
}
@@ -1235,9 +1235,9 @@
status = g_malloc0(sizeof(*status));
status->mon = mon;
status->is_block_migration = blk || inc;
- status->timer = qemu_new_timer_ms(rt_clock, hmp_migrate_status_cb,
+ status->timer = timer_new_ms(QEMU_CLOCK_REALTIME, hmp_migrate_status_cb,
status);
- qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock));
+ timer_mod(status->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
}
}
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 35e2af4..f0ffbe8 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -61,6 +61,8 @@
s->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output);
+ v9fs_path_init(&path);
+
fse = get_fsdev_fsentry(s->fsconf.fsdev_id);
if (!fse) {
@@ -111,7 +113,6 @@
* call back to do that. Since we are in the init path, we don't
* use co-routines here.
*/
- v9fs_path_init(&path);
if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) {
fprintf(stderr,
"error in converting name to path %s", strerror(errno));
@@ -149,6 +150,7 @@
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->props = virtio_9p_properties;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->init = virtio_9p_device_init;
vdc->get_features = virtio_9p_get_features;
vdc->get_config = virtio_9p_get_config;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 8ba2959..5f44bb7 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -1153,10 +1153,12 @@
sock_id = atoi(ctx->fs_root);
if (sock_id < 0) {
fprintf(stderr, "socket descriptor not initialized\n");
+ g_free(proxy);
return -1;
}
}
g_free(ctx->fs_root);
+ ctx->fs_root = NULL;
proxy->in_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
proxy->in_iovec.iov_len = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index b07feda..7467b88 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -433,9 +433,9 @@
if (enable) {
expire_time = muldiv64(ar->tmr.overflow_time, get_ticks_per_sec(),
PM_TIMER_FREQUENCY);
- qemu_mod_timer(ar->tmr.timer, expire_time);
+ timer_mod(ar->tmr.timer, expire_time);
} else {
- qemu_del_timer(ar->tmr.timer);
+ timer_del(ar->tmr.timer);
}
}
@@ -481,7 +481,7 @@
MemoryRegion *parent)
{
ar->tmr.update_sci = update_sci;
- ar->tmr.timer = qemu_new_timer_ns(vm_clock, acpi_pm_tmr_timer, ar);
+ ar->tmr.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, acpi_pm_tmr_timer, ar);
memory_region_init_io(&ar->tmr.io, memory_region_owner(parent),
&acpi_pm_tmr_ops, ar, "acpi-tmr", 4);
memory_region_add_subregion(parent, 8, &ar->tmr.io);
@@ -490,7 +490,7 @@
void acpi_pm_tmr_reset(ACPIREGS *ar)
{
ar->tmr.overflow_time = 0;
- qemu_del_timer(ar->tmr.timer);
+ timer_del(ar->tmr.timer);
}
/* ACPI PM1aCNT */
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index c885690..613d987 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -263,7 +263,7 @@
return ret;
}
- qemu_get_timer(f, s->ar.tmr.timer);
+ timer_get(f, s->ar.tmr.timer);
qemu_get_sbe64s(f, &s->ar.tmr.overflow_time);
qemu_get_be16s(f, (uint16_t *)s->ar.gpe.sts);
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index b7fb044..aac9a32 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -26,9 +26,9 @@
} TyphoonCchip;
typedef struct TyphoonWindow {
- uint32_t base_addr;
- uint32_t mask;
- uint32_t translated_base_pfn;
+ uint64_t wba;
+ uint64_t wsm;
+ uint64_t tba;
} TyphoonWindow;
typedef struct TyphoonPchip {
@@ -37,6 +37,10 @@
MemoryRegion reg_mem;
MemoryRegion reg_io;
MemoryRegion reg_conf;
+
+ AddressSpace iommu_as;
+ MemoryRegion iommu;
+
uint64_t ctl;
TyphoonWindow win[4];
} TyphoonPchip;
@@ -209,53 +213,53 @@
switch (addr) {
case 0x0000:
/* WSBA0: Window Space Base Address Register. */
- ret = s->pchip.win[0].base_addr;
+ ret = s->pchip.win[0].wba;
break;
case 0x0040:
/* WSBA1 */
- ret = s->pchip.win[1].base_addr;
+ ret = s->pchip.win[1].wba;
break;
case 0x0080:
/* WSBA2 */
- ret = s->pchip.win[2].base_addr;
+ ret = s->pchip.win[2].wba;
break;
case 0x00c0:
/* WSBA3 */
- ret = s->pchip.win[3].base_addr;
+ ret = s->pchip.win[3].wba;
break;
case 0x0100:
/* WSM0: Window Space Mask Register. */
- ret = s->pchip.win[0].mask;
+ ret = s->pchip.win[0].wsm;
break;
case 0x0140:
/* WSM1 */
- ret = s->pchip.win[1].mask;
+ ret = s->pchip.win[1].wsm;
break;
case 0x0180:
/* WSM2 */
- ret = s->pchip.win[2].mask;
+ ret = s->pchip.win[2].wsm;
break;
case 0x01c0:
/* WSM3 */
- ret = s->pchip.win[3].mask;
+ ret = s->pchip.win[3].wsm;
break;
case 0x0200:
/* TBA0: Translated Base Address Register. */
- ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10;
+ ret = s->pchip.win[0].tba;
break;
case 0x0240:
/* TBA1 */
- ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10;
+ ret = s->pchip.win[1].tba;
break;
case 0x0280:
/* TBA2 */
- ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10;
+ ret = s->pchip.win[2].tba;
break;
case 0x02c0:
/* TBA3 */
- ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10;
+ ret = s->pchip.win[3].tba;
break;
case 0x0300:
@@ -458,53 +462,53 @@
switch (addr) {
case 0x0000:
/* WSBA0: Window Space Base Address Register. */
- s->pchip.win[0].base_addr = val;
+ s->pchip.win[0].wba = val & 0xfff00003u;
break;
case 0x0040:
/* WSBA1 */
- s->pchip.win[1].base_addr = val;
+ s->pchip.win[1].wba = val & 0xfff00003u;
break;
case 0x0080:
/* WSBA2 */
- s->pchip.win[2].base_addr = val;
+ s->pchip.win[2].wba = val & 0xfff00003u;
break;
case 0x00c0:
/* WSBA3 */
- s->pchip.win[3].base_addr = val;
+ s->pchip.win[3].wba = (val & 0x80fff00001ull) | 2;
break;
case 0x0100:
/* WSM0: Window Space Mask Register. */
- s->pchip.win[0].mask = val;
+ s->pchip.win[0].wsm = val & 0xfff00000u;
break;
case 0x0140:
/* WSM1 */
- s->pchip.win[1].mask = val;
+ s->pchip.win[1].wsm = val & 0xfff00000u;
break;
case 0x0180:
/* WSM2 */
- s->pchip.win[2].mask = val;
+ s->pchip.win[2].wsm = val & 0xfff00000u;
break;
case 0x01c0:
/* WSM3 */
- s->pchip.win[3].mask = val;
+ s->pchip.win[3].wsm = val & 0xfff00000u;
break;
case 0x0200:
/* TBA0: Translated Base Address Register. */
- s->pchip.win[0].translated_base_pfn = val >> 10;
+ s->pchip.win[0].tba = val & 0x7fffffc00ull;
break;
case 0x0240:
/* TBA1 */
- s->pchip.win[1].translated_base_pfn = val >> 10;
+ s->pchip.win[1].tba = val & 0x7fffffc00ull;
break;
case 0x0280:
/* TBA2 */
- s->pchip.win[2].translated_base_pfn = val >> 10;
+ s->pchip.win[2].tba = val & 0x7fffffc00ull;
break;
case 0x02c0:
/* TBA3 */
- s->pchip.win[3].translated_base_pfn = val >> 10;
+ s->pchip.win[3].tba = val & 0x7fffffc00ull;
break;
case 0x0300:
@@ -512,7 +516,6 @@
oldval = s->pchip.ctl;
oldval &= ~0x00001cff0fc7ffull; /* RW fields */
oldval |= val & 0x00001cff0fc7ffull;
-
s->pchip.ctl = oldval;
break;
@@ -593,6 +596,140 @@
},
};
+/* A subroutine of typhoon_translate_iommu that builds an IOMMUTLBEntry
+ using the given translated address and mask. */
+static bool make_iommu_tlbe(hwaddr taddr, hwaddr mask, IOMMUTLBEntry *ret)
+{
+ *ret = (IOMMUTLBEntry) {
+ .target_as = &address_space_memory,
+ .translated_addr = taddr,
+ .addr_mask = mask,
+ .perm = IOMMU_RW,
+ };
+ return true;
+}
+
+/* A subroutine of typhoon_translate_iommu that handles scatter-gather
+ translation, given the address of the PTE. */
+static bool pte_translate(hwaddr pte_addr, IOMMUTLBEntry *ret)
+{
+ uint64_t pte = ldq_phys(pte_addr);
+
+ /* Check valid bit. */
+ if ((pte & 1) == 0) {
+ return false;
+ }
+
+ return make_iommu_tlbe((pte & 0x3ffffe) << 12, 0x1fff, ret);
+}
+
+/* A subroutine of typhoon_translate_iommu that handles one of the
+ four single-address-cycle translation windows. */
+static bool window_translate(TyphoonWindow *win, hwaddr addr,
+ IOMMUTLBEntry *ret)
+{
+ uint32_t wba = win->wba;
+ uint64_t wsm = win->wsm;
+ uint64_t tba = win->tba;
+ uint64_t wsm_ext = wsm | 0xfffff;
+
+ /* Check for window disabled. */
+ if ((wba & 1) == 0) {
+ return false;
+ }
+
+ /* Check for window hit. */
+ if ((addr & ~wsm_ext) != (wba & 0xfff00000u)) {
+ return false;
+ }
+
+ if (wba & 2) {
+ /* Scatter-gather translation. */
+ hwaddr pte_addr;
+
+ /* See table 10-6, Generating PTE address for PCI DMA Address. */
+ pte_addr = tba & ~(wsm >> 10);
+ pte_addr |= (addr & (wsm | 0xfe000)) >> 10;
+ return pte_translate(pte_addr, ret);
+ } else {
+ /* Direct-mapped translation. */
+ return make_iommu_tlbe(tba & ~wsm_ext, wsm_ext, ret);
+ }
+}
+
+/* Handle PCI-to-system address translation. */
+/* TODO: A translation failure here ought to set PCI error codes on the
+ Pchip and generate a machine check interrupt. */
+static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr)
+{
+ TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
+ IOMMUTLBEntry ret;
+ int i;
+
+ if (addr <= 0xffffffffu) {
+ /* Single-address cycle. */
+
+ /* Check for the Window Hole, inhibiting matching. */
+ if ((pchip->ctl & 0x20)
+ && addr >= 0x80000
+ && addr <= 0xfffff) {
+ goto failure;
+ }
+
+ /* Check the first three windows. */
+ for (i = 0; i < 3; ++i) {
+ if (window_translate(&pchip->win[i], addr, &ret)) {
+ goto success;
+ }
+ }
+
+ /* Check the fourth window for DAC disable. */
+ if ((pchip->win[3].wba & 0x80000000000ull) == 0
+ && window_translate(&pchip->win[3], addr, &ret)) {
+ goto success;
+ }
+ } else {
+ /* Double-address cycle. */
+
+ if (addr >= 0x10000000000ull && addr < 0x20000000000ull) {
+ /* Check for the DMA monster window. */
+ if (pchip->ctl & 0x40) {
+ /* See 10.1.4.4; in particular <39:35> is ignored. */
+ make_iommu_tlbe(0, 0x007ffffffffull, &ret);
+ goto success;
+ }
+ }
+
+ if (addr >= 0x80000000000 && addr <= 0xfffffffffff) {
+ /* Check the fourth window for DAC enable and window enable. */
+ if ((pchip->win[3].wba & 0x80000000001ull) == 0x80000000001ull) {
+ uint64_t pte_addr;
+
+ pte_addr = pchip->win[3].tba & 0x7ffc00000ull;
+ pte_addr |= (addr & 0xffffe000u) >> 10;
+ if (pte_translate(pte_addr, &ret)) {
+ goto success;
+ }
+ }
+ }
+ }
+
+ failure:
+ ret = (IOMMUTLBEntry) { .perm = IOMMU_NONE };
+ success:
+ return ret;
+}
+
+static const MemoryRegionIOMMUOps typhoon_iommu_ops = {
+ .translate = typhoon_translate_iommu,
+};
+
+static AddressSpace *typhoon_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
+{
+ TyphoonState *s = opaque;
+ return &s->pchip.iommu_as;
+}
+
static void typhoon_set_irq(void *opaque, int irq, int level)
{
TyphoonState *s = opaque;
@@ -688,12 +825,15 @@
s = TYPHOON_PCI_HOST_BRIDGE(dev);
phb = PCI_HOST_BRIDGE(dev);
+ s->cchip.misc = 0x800000000ull; /* Revision: Typhoon. */
+ s->pchip.win[3].wba = 2; /* Window 3 SG always enabled. */
+
/* Remember the CPUs so that we can deliver interrupts to them. */
for (i = 0; i < 4; i++) {
AlphaCPU *cpu = cpus[i];
s->cchip.cpu[i] = cpu;
if (cpu != NULL) {
- cpu->alarm_timer = qemu_new_timer_ns(vm_clock,
+ cpu->alarm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
typhoon_alarm_timer,
(void *)((uintptr_t)s + i));
}
@@ -746,6 +886,12 @@
0, 64, TYPE_PCI_BUS);
phb->bus = b;
+ /* Host memory as seen from the PCI side, via the IOMMU. */
+ memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops,
+ "iommu-typhoon", UINT64_MAX);
+ address_space_init(&s->pchip.iommu_as, &s->pchip.iommu, "pchip0-pci");
+ pci_setup_iommu(b, typhoon_pci_dma_iommu, s);
+
/* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */
memory_region_init_io(&s->pchip.reg_iack, OBJECT(s), &alpha_pci_iack_ops,
b, "pci0-iack", 64*MB);
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 9e3a06f..3671b42 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -1,6 +1,6 @@
obj-y += boot.o collie.o exynos4_boards.o gumstix.o highbank.o
obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o
-obj-y += omap_sx1.o palm.o pic_cpu.o realview.o spitz.o stellaris.o
+obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 5b22e84..89a9015 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -114,15 +114,21 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
+#define TYPE_BITBAND "ARM,bitband-memory"
+#define BITBAND(obj) OBJECT_CHECK(BitBandState, (obj), TYPE_BITBAND)
+
typedef struct {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
uint32_t base;
} BitBandState;
static int bitband_init(SysBusDevice *dev)
{
- BitBandState *s = FROM_SYSBUS(BitBandState, dev);
+ BitBandState *s = BITBAND(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &bitband_ops, &s->base,
"bitband", 0x02000000);
@@ -134,12 +140,12 @@
{
DeviceState *dev;
- dev = qdev_create(NULL, "ARM,bitband-memory");
+ dev = qdev_create(NULL, TYPE_BITBAND);
qdev_prop_set_uint32(dev, "base", 0x20000000);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x22000000);
- dev = qdev_create(NULL, "ARM,bitband-memory");
+ dev = qdev_create(NULL, TYPE_BITBAND);
qdev_prop_set_uint32(dev, "base", 0x40000000);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x42000000);
@@ -167,7 +173,6 @@
DeviceState *nvic;
/* FIXME: make this local state. */
static qemu_irq pic[64];
- qemu_irq *cpu_pic;
int image_size;
uint64_t entry;
uint64_t lowaddr;
@@ -215,8 +220,8 @@
nvic = qdev_create(NULL, "armv7m_nvic");
env->nvic = nvic;
qdev_init_nofail(nvic);
- cpu_pic = arm_pic_init_cpu(cpu);
- sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0, cpu_pic[ARM_PIC_CPU_IRQ]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0,
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
for (i = 0; i < 64; i++) {
pic[i] = qdev_get_gpio_in(nvic, i);
}
@@ -270,7 +275,7 @@
}
static const TypeInfo bitband_info = {
- .name = "ARM,bitband-memory",
+ .name = TYPE_BITBAND,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(BitBandState),
.class_init = bitband_class_init,
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index 216b9b7..4ebb938 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -137,10 +137,8 @@
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
unsigned long ram_size)
{
- qemu_irq cpu_irq[EXYNOS4210_NCPUS];
int i, n;
Exynos4210State *s = g_new(Exynos4210State, 1);
- qemu_irq *irqp;
qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
unsigned long mem_size;
DeviceState *dev;
@@ -152,15 +150,6 @@
fprintf(stderr, "Unable to find CPU %d definition\n", n);
exit(1);
}
-
- /* Create PIC controller for each processor instance */
- irqp = arm_pic_init_cpu(s->cpu[n]);
-
- /*
- * Get GICs gpio_in cpu_irq to connect a combiner to them later.
- * Use only IRQ for a while.
- */
- cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
}
/*** IRQs ***/
@@ -178,8 +167,9 @@
}
busdev = SYS_BUS_DEVICE(dev);
- /* Connect IRQ Gate output to cpu_irq */
- sysbus_connect_irq(busdev, 0, cpu_irq[i]);
+ /* Connect IRQ Gate output to CPU's IRQ line */
+ sysbus_connect_irq(busdev, 0,
+ qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
}
/* Private memory region and Internal GIC */
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index be264d3..f733a6c 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -116,8 +116,15 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
+#define TYPE_HIGHBANK_REGISTERS "highbank-regs"
+#define HIGHBANK_REGISTERS(obj) \
+ OBJECT_CHECK(HighbankRegsState, (obj), TYPE_HIGHBANK_REGISTERS)
+
typedef struct {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion *iomem;
uint32_t regs[NUM_REGS];
} HighbankRegsState;
@@ -135,8 +142,7 @@
static void highbank_regs_reset(DeviceState *dev)
{
- SysBusDevice *sys_dev = SYS_BUS_DEVICE(dev);
- HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, sys_dev);
+ HighbankRegsState *s = HIGHBANK_REGISTERS(dev);
s->regs[0x40] = 0x05F20121;
s->regs[0x41] = 0x2;
@@ -146,7 +152,7 @@
static int highbank_regs_init(SysBusDevice *dev)
{
- HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev);
+ HighbankRegsState *s = HIGHBANK_REGISTERS(dev);
s->iomem = g_new(MemoryRegion, 1);
memory_region_init_io(s->iomem, OBJECT(s), &hb_mem_ops, s->regs,
@@ -168,7 +174,7 @@
}
static const TypeInfo highbank_regs_info = {
- .name = "highbank-regs",
+ .name = TYPE_HIGHBANK_REGISTERS,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(HighbankRegsState),
.class_init = highbank_regs_class_init,
@@ -203,7 +209,6 @@
const char *initrd_filename = args->initrd_filename;
DeviceState *dev = NULL;
SysBusDevice *busdev;
- qemu_irq *irqp;
qemu_irq pic[128];
int n;
qemu_irq cpu_irq[4];
@@ -233,8 +238,7 @@
/* This will become a QOM property eventually */
cpu->reset_cbar = GIC_BASE_ADDR;
- irqp = arm_pic_init_cpu(cpu);
- cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+ cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
}
sysmem = get_system_memory();
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index 249a430..59c3726 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -15,8 +15,15 @@
#include "exec/address-spaces.h"
#include "sysemu/sysemu.h"
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_INTEGRATOR_CM "integrator_core"
+#define INTEGRATOR_CM(obj) \
+ OBJECT_CHECK(IntegratorCMState, (obj), TYPE_INTEGRATOR_CM)
+
+typedef struct IntegratorCMState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
uint32_t memsz;
MemoryRegion flash;
@@ -31,7 +38,7 @@
uint32_t int_level;
uint32_t irq_enabled;
uint32_t fiq_enabled;
-} integratorcm_state;
+} IntegratorCMState;
static uint8_t integrator_spd[128] = {
128, 8, 4, 11, 9, 1, 64, 0, 2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
@@ -41,7 +48,7 @@
static uint64_t integratorcm_read(void *opaque, hwaddr offset,
unsigned size)
{
- integratorcm_state *s = (integratorcm_state *)opaque;
+ IntegratorCMState *s = opaque;
if (offset >= 0x100 && offset < 0x200) {
/* CM_SPD */
if (offset >= 0x180)
@@ -108,7 +115,7 @@
}
}
-static void integratorcm_do_remap(integratorcm_state *s)
+static void integratorcm_do_remap(IntegratorCMState *s)
{
/* Sync memory region state with CM_CTRL REMAP bit:
* bit 0 => flash at address 0; bit 1 => RAM
@@ -116,7 +123,7 @@
memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
}
-static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
+static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value)
{
if (value & 8) {
qemu_system_reset_request();
@@ -133,7 +140,7 @@
integratorcm_do_remap(s);
}
-static void integratorcm_update(integratorcm_state *s)
+static void integratorcm_update(IntegratorCMState *s)
{
/* ??? The CPU irq/fiq is raised when either the core module or base PIC
are active. */
@@ -144,7 +151,7 @@
static void integratorcm_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
- integratorcm_state *s = (integratorcm_state *)opaque;
+ IntegratorCMState *s = opaque;
switch (offset >> 2) {
case 2: /* CM_OSC */
if (s->cm_lock == 0xa05f)
@@ -226,7 +233,7 @@
static int integratorcm_init(SysBusDevice *dev)
{
- integratorcm_state *s = FROM_SYSBUS(integratorcm_state, dev);
+ IntegratorCMState *s = INTEGRATOR_CM(dev);
s->cm_osc = 0x01000048;
/* ??? What should the high bits of this value be? */
@@ -264,15 +271,21 @@
/* Integrator/CP hardware emulation. */
/* Primary interrupt controller. */
-typedef struct icp_pic_state
-{
- SysBusDevice busdev;
- MemoryRegion iomem;
- uint32_t level;
- uint32_t irq_enabled;
- uint32_t fiq_enabled;
- qemu_irq parent_irq;
- qemu_irq parent_fiq;
+#define TYPE_INTEGRATOR_PIC "integrator_pic"
+#define INTEGRATOR_PIC(obj) \
+ OBJECT_CHECK(icp_pic_state, (obj), TYPE_INTEGRATOR_PIC)
+
+typedef struct icp_pic_state {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ MemoryRegion iomem;
+ uint32_t level;
+ uint32_t irq_enabled;
+ uint32_t fiq_enabled;
+ qemu_irq parent_irq;
+ qemu_irq parent_fiq;
} icp_pic_state;
static void icp_pic_update(icp_pic_state *s)
@@ -367,16 +380,17 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int icp_pic_init(SysBusDevice *dev)
+static int icp_pic_init(SysBusDevice *sbd)
{
- icp_pic_state *s = FROM_SYSBUS(icp_pic_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ icp_pic_state *s = INTEGRATOR_PIC(dev);
- qdev_init_gpio_in(&dev->qdev, icp_pic_set_irq, 32);
- sysbus_init_irq(dev, &s->parent_irq);
- sysbus_init_irq(dev, &s->parent_fiq);
+ qdev_init_gpio_in(dev, icp_pic_set_irq, 32);
+ sysbus_init_irq(sbd, &s->parent_irq);
+ sysbus_init_irq(sbd, &s->parent_fiq);
memory_region_init_io(&s->iomem, OBJECT(s), &icp_pic_ops, s,
"icp-pic", 0x00800000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
return 0;
}
@@ -451,7 +465,6 @@
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
qemu_irq pic[32];
- qemu_irq *cpu_pic;
DeviceState *dev;
int i;
@@ -474,19 +487,19 @@
memory_region_init_alias(ram_alias, NULL, "ram.alias", ram, 0, ram_size);
memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
- dev = qdev_create(NULL, "integrator_core");
+ dev = qdev_create(NULL, TYPE_INTEGRATOR_CM);
qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
qdev_init_nofail(dev);
sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
- cpu_pic = arm_pic_init_cpu(cpu);
- dev = sysbus_create_varargs("integrator_pic", 0x14000000,
- cpu_pic[ARM_PIC_CPU_IRQ],
- cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+ dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000,
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
+ NULL);
for (i = 0; i < 32; i++) {
pic[i] = qdev_get_gpio_in(dev, i);
}
- sysbus_create_simple("integrator_pic", 0xca000000, pic[26]);
+ sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]);
sysbus_create_varargs("integrator_pit", 0x13000000,
pic[5], pic[6], pic[7], NULL);
sysbus_create_simple("pl031", 0x15000000, pic[8]);
@@ -524,7 +537,7 @@
machine_init(integratorcp_machine_init);
static Property core_properties[] = {
- DEFINE_PROP_UINT32("memsz", integratorcm_state, memsz, 0),
+ DEFINE_PROP_UINT32("memsz", IntegratorCMState, memsz, 0),
DEFINE_PROP_END_OF_LIST(),
};
@@ -538,9 +551,9 @@
}
static const TypeInfo core_info = {
- .name = "integrator_core",
+ .name = TYPE_INTEGRATOR_CM,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(integratorcm_state),
+ .instance_size = sizeof(IntegratorCMState),
.class_init = core_class_init,
};
@@ -552,7 +565,7 @@
}
static const TypeInfo icp_pic_info = {
- .name = "integrator_pic",
+ .name = TYPE_INTEGRATOR_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(icp_pic_state),
.class_init = icp_pic_class_init,
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
index bd6c05c..a248bf0 100644
--- a/hw/arm/kzm.c
+++ b/hw/arm/kzm.c
@@ -82,7 +82,6 @@
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *sram = g_new(MemoryRegion, 1);
MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
- qemu_irq *cpu_pic;
DeviceState *dev;
DeviceState *ccm;
@@ -108,11 +107,10 @@
memory_region_init_ram(sram, NULL, "kzm.sram", 0x4000);
memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram);
- cpu_pic = arm_pic_init_cpu(cpu);
dev = sysbus_create_varargs("imx_avic", 0x68000000,
- cpu_pic[ARM_PIC_CPU_IRQ],
- cpu_pic[ARM_PIC_CPU_FIQ], NULL);
-
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
+ NULL);
imx_serial_create(0, 0x43f90000, qdev_get_gpio_in(dev, 45));
imx_serial_create(1, 0x43f94000, qdev_get_gpio_in(dev, 32));
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index b06d442..4404b8d 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -146,8 +146,15 @@
uint32_t next;
} mv88w8618_rx_desc;
+#define TYPE_MV88W8618_ETH "mv88w8618_eth"
+#define MV88W8618_ETH(obj) \
+ OBJECT_CHECK(mv88w8618_eth_state, (obj), TYPE_MV88W8618_ETH)
+
typedef struct mv88w8618_eth_state {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
qemu_irq irq;
uint32_t smir;
@@ -382,16 +389,17 @@
.cleanup = eth_cleanup,
};
-static int mv88w8618_eth_init(SysBusDevice *dev)
+static int mv88w8618_eth_init(SysBusDevice *sbd)
{
- mv88w8618_eth_state *s = FROM_SYSBUS(mv88w8618_eth_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ mv88w8618_eth_state *s = MV88W8618_ETH(dev);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->id, s);
memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_eth_ops, s,
"mv88w8618-eth", MP_ETH_SIZE);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
return 0;
}
@@ -429,7 +437,7 @@
}
static const TypeInfo mv88w8618_eth_info = {
- .name = "mv88w8618_eth",
+ .name = TYPE_MV88W8618_ETH,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(mv88w8618_eth_state),
.class_init = mv88w8618_eth_class_init,
@@ -454,8 +462,15 @@
#define MP_LCD_TEXTCOLOR 0xe0e0ff /* RRGGBB */
+#define TYPE_MUSICPAL_LCD "musicpal_lcd"
+#define MUSICPAL_LCD(obj) \
+ OBJECT_CHECK(musicpal_lcd_state, (obj), TYPE_MUSICPAL_LCD)
+
typedef struct musicpal_lcd_state {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
uint32_t brightness;
uint32_t mode;
@@ -534,7 +549,7 @@
{
}
-static void musicpal_lcd_gpio_brigthness_in(void *opaque, int irq, int level)
+static void musicpal_lcd_gpio_brightness_in(void *opaque, int irq, int level)
{
musicpal_lcd_state *s = opaque;
s->brightness &= ~(1 << irq);
@@ -606,20 +621,21 @@
.gfx_update = lcd_refresh,
};
-static int musicpal_lcd_init(SysBusDevice *dev)
+static int musicpal_lcd_init(SysBusDevice *sbd)
{
- musicpal_lcd_state *s = FROM_SYSBUS(musicpal_lcd_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ musicpal_lcd_state *s = MUSICPAL_LCD(dev);
s->brightness = 7;
memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_lcd_ops, s,
"musicpal-lcd", MP_LCD_SIZE);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
- s->con = graphic_console_init(DEVICE(dev), &musicpal_gfx_ops, s);
+ s->con = graphic_console_init(dev, &musicpal_gfx_ops, s);
qemu_console_resize(s->con, 128*3, 64*3);
- qdev_init_gpio_in(&dev->qdev, musicpal_lcd_gpio_brigthness_in, 3);
+ qdev_init_gpio_in(dev, musicpal_lcd_gpio_brightness_in, 3);
return 0;
}
@@ -650,7 +666,7 @@
}
static const TypeInfo musicpal_lcd_info = {
- .name = "musicpal_lcd",
+ .name = TYPE_MUSICPAL_LCD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(musicpal_lcd_state),
.class_init = musicpal_lcd_class_init,
@@ -661,9 +677,15 @@
#define MP_PIC_ENABLE_SET 0x08
#define MP_PIC_ENABLE_CLR 0x0C
-typedef struct mv88w8618_pic_state
-{
- SysBusDevice busdev;
+#define TYPE_MV88W8618_PIC "mv88w8618_pic"
+#define MV88W8618_PIC(obj) \
+ OBJECT_CHECK(mv88w8618_pic_state, (obj), TYPE_MV88W8618_PIC)
+
+typedef struct mv88w8618_pic_state {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
uint32_t level;
uint32_t enabled;
@@ -721,8 +743,7 @@
static void mv88w8618_pic_reset(DeviceState *d)
{
- mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state,
- SYS_BUS_DEVICE(d));
+ mv88w8618_pic_state *s = MV88W8618_PIC(d);
s->level = 0;
s->enabled = 0;
@@ -736,9 +757,9 @@
static int mv88w8618_pic_init(SysBusDevice *dev)
{
- mv88w8618_pic_state *s = FROM_SYSBUS(mv88w8618_pic_state, dev);
+ mv88w8618_pic_state *s = MV88W8618_PIC(dev);
- qdev_init_gpio_in(&dev->qdev, mv88w8618_pic_set_irq, 32);
+ qdev_init_gpio_in(DEVICE(dev), mv88w8618_pic_set_irq, 32);
sysbus_init_irq(dev, &s->parent_irq);
memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_pic_ops, s,
"musicpal-pic", MP_PIC_SIZE);
@@ -769,7 +790,7 @@
}
static const TypeInfo mv88w8618_pic_info = {
- .name = "mv88w8618_pic",
+ .name = TYPE_MV88W8618_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(mv88w8618_pic_state),
.class_init = mv88w8618_pic_class_init,
@@ -795,8 +816,15 @@
qemu_irq irq;
} mv88w8618_timer_state;
+#define TYPE_MV88W8618_PIT "mv88w8618_pit"
+#define MV88W8618_PIT(obj) \
+ OBJECT_CHECK(mv88w8618_pit_state, (obj), TYPE_MV88W8618_PIT)
+
typedef struct mv88w8618_pit_state {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
mv88w8618_timer_state timer[4];
} mv88w8618_pit_state;
@@ -878,8 +906,7 @@
static void mv88w8618_pit_reset(DeviceState *d)
{
- mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state,
- SYS_BUS_DEVICE(d));
+ mv88w8618_pit_state *s = MV88W8618_PIT(d);
int i;
for (i = 0; i < 4; i++) {
@@ -896,7 +923,7 @@
static int mv88w8618_pit_init(SysBusDevice *dev)
{
- mv88w8618_pit_state *s = FROM_SYSBUS(mv88w8618_pit_state, dev);
+ mv88w8618_pit_state *s = MV88W8618_PIT(dev);
int i;
/* Letting them all run at 1 MHz is likely just a pragmatic
@@ -946,7 +973,7 @@
}
static const TypeInfo mv88w8618_pit_info = {
- .name = "mv88w8618_pit",
+ .name = TYPE_MV88W8618_PIT,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(mv88w8618_pit_state),
.class_init = mv88w8618_pit_class_init,
@@ -955,8 +982,15 @@
/* Flash config register offsets */
#define MP_FLASHCFG_CFGR0 0x04
+#define TYPE_MV88W8618_FLASHCFG "mv88w8618_flashcfg"
+#define MV88W8618_FLASHCFG(obj) \
+ OBJECT_CHECK(mv88w8618_flashcfg_state, (obj), TYPE_MV88W8618_FLASHCFG)
+
typedef struct mv88w8618_flashcfg_state {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
uint32_t cfgr0;
} mv88w8618_flashcfg_state;
@@ -996,7 +1030,7 @@
static int mv88w8618_flashcfg_init(SysBusDevice *dev)
{
- mv88w8618_flashcfg_state *s = FROM_SYSBUS(mv88w8618_flashcfg_state, dev);
+ mv88w8618_flashcfg_state *s = MV88W8618_FLASHCFG(dev);
s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */
memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_flashcfg_ops, s,
@@ -1026,7 +1060,7 @@
}
static const TypeInfo mv88w8618_flashcfg_info = {
- .name = "mv88w8618_flashcfg",
+ .name = TYPE_MV88W8618_FLASHCFG,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(mv88w8618_flashcfg_state),
.class_init = mv88w8618_flashcfg_class_init,
@@ -1149,8 +1183,15 @@
/* LCD brightness bits in GPIO_OE_HI */
#define MP_OE_LCD_BRIGHTNESS 0x0007
+#define TYPE_MUSICPAL_GPIO "musicpal_gpio"
+#define MUSICPAL_GPIO(obj) \
+ OBJECT_CHECK(musicpal_gpio_state, (obj), TYPE_MUSICPAL_GPIO)
+
typedef struct musicpal_gpio_state {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
uint32_t lcd_brightness;
uint32_t out_state;
@@ -1310,8 +1351,7 @@
static void musicpal_gpio_reset(DeviceState *d)
{
- musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state,
- SYS_BUS_DEVICE(d));
+ musicpal_gpio_state *s = MUSICPAL_GPIO(d);
s->lcd_brightness = 0;
s->out_state = 0;
@@ -1321,19 +1361,20 @@
s->isr = 0;
}
-static int musicpal_gpio_init(SysBusDevice *dev)
+static int musicpal_gpio_init(SysBusDevice *sbd)
{
- musicpal_gpio_state *s = FROM_SYSBUS(musicpal_gpio_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ musicpal_gpio_state *s = MUSICPAL_GPIO(dev);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_gpio_ops, s,
"musicpal-gpio", MP_GPIO_SIZE);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
- qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
+ qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
- qdev_init_gpio_in(&dev->qdev, musicpal_gpio_pin_event, 32);
+ qdev_init_gpio_in(dev, musicpal_gpio_pin_event, 32);
return 0;
}
@@ -1365,7 +1406,7 @@
}
static const TypeInfo musicpal_gpio_info = {
- .name = "musicpal_gpio",
+ .name = TYPE_MUSICPAL_GPIO,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(musicpal_gpio_state),
.class_init = musicpal_gpio_class_init,
@@ -1395,8 +1436,15 @@
#define MP_KEY_BTN_VOLUME (1 << 6)
#define MP_KEY_BTN_NAVIGATION (1 << 7)
+#define TYPE_MUSICPAL_KEY "musicpal_key"
+#define MUSICPAL_KEY(obj) \
+ OBJECT_CHECK(musicpal_key_state, (obj), TYPE_MUSICPAL_KEY)
+
typedef struct musicpal_key_state {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
uint32_t kbd_extended;
uint32_t pressed_keys;
@@ -1480,17 +1528,18 @@
s->kbd_extended = 0;
}
-static int musicpal_key_init(SysBusDevice *dev)
+static int musicpal_key_init(SysBusDevice *sbd)
{
- musicpal_key_state *s = FROM_SYSBUS(musicpal_key_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ musicpal_key_state *s = MUSICPAL_KEY(dev);
memory_region_init(&s->iomem, OBJECT(s), "dummy", 0);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
s->kbd_extended = 0;
s->pressed_keys = 0;
- qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
+ qdev_init_gpio_out(dev, s->out, ARRAY_SIZE(s->out));
qemu_add_kbd_event_handler(musicpal_key_event, s);
@@ -1519,7 +1568,7 @@
}
static const TypeInfo musicpal_key_info = {
- .name = "musicpal_key",
+ .name = TYPE_MUSICPAL_KEY,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(musicpal_key_state),
.class_init = musicpal_key_class_init,
@@ -1537,7 +1586,6 @@
const char *kernel_cmdline = args->kernel_cmdline;
const char *initrd_filename = args->initrd_filename;
ARMCPU *cpu;
- qemu_irq *cpu_pic;
qemu_irq pic[32];
DeviceState *dev;
DeviceState *i2c_dev;
@@ -1561,7 +1609,6 @@
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- cpu_pic = arm_pic_init_cpu(cpu);
/* For now we use a fixed - the original - RAM size */
memory_region_init_ram(ram, NULL, "musicpal.ram", MP_RAM_DEFAULT_SIZE);
@@ -1572,12 +1619,12 @@
vmstate_register_ram_global(sram);
memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram);
- dev = sysbus_create_simple("mv88w8618_pic", MP_PIC_BASE,
- cpu_pic[ARM_PIC_CPU_IRQ]);
+ dev = sysbus_create_simple(TYPE_MV88W8618_PIC, MP_PIC_BASE,
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
for (i = 0; i < 32; i++) {
pic[i] = qdev_get_gpio_in(dev, i);
}
- sysbus_create_varargs("mv88w8618_pit", MP_PIT_BASE, pic[MP_TIMER1_IRQ],
+ sysbus_create_varargs(TYPE_MV88W8618_PIT, MP_PIT_BASE, pic[MP_TIMER1_IRQ],
pic[MP_TIMER2_IRQ], pic[MP_TIMER3_IRQ],
pic[MP_TIMER4_IRQ], NULL);
@@ -1624,10 +1671,10 @@
#endif
}
- sysbus_create_simple("mv88w8618_flashcfg", MP_FLASHCFG_BASE, NULL);
+ sysbus_create_simple(TYPE_MV88W8618_FLASHCFG, MP_FLASHCFG_BASE, NULL);
qemu_check_nic_model(&nd_table[0], "mv88w8618");
- dev = qdev_create(NULL, "mv88w8618_eth");
+ dev = qdev_create(NULL, TYPE_MV88W8618_ETH);
qdev_set_nic_properties(dev, &nd_table[0]);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, MP_ETH_BASE);
@@ -1637,12 +1684,13 @@
sysbus_create_simple(TYPE_MUSICPAL_MISC, MP_MISC_BASE, NULL);
- dev = sysbus_create_simple("musicpal_gpio", MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
+ dev = sysbus_create_simple(TYPE_MUSICPAL_GPIO, MP_GPIO_BASE,
+ pic[MP_GPIO_IRQ]);
i2c_dev = sysbus_create_simple("gpio_i2c", -1, NULL);
i2c = (i2c_bus *)qdev_get_child_bus(i2c_dev, "i2c");
- lcd_dev = sysbus_create_simple("musicpal_lcd", MP_LCD_BASE, NULL);
- key_dev = sysbus_create_simple("musicpal_key", -1, NULL);
+ lcd_dev = sysbus_create_simple(TYPE_MUSICPAL_LCD, MP_LCD_BASE, NULL);
+ key_dev = sysbus_create_simple(TYPE_MUSICPAL_KEY, -1, NULL);
/* I2C read data */
qdev_connect_gpio_out(i2c_dev, 0,
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index 19be5fc..47511d2 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -99,7 +99,7 @@
static inline uint32_t omap_timer_read(struct omap_mpu_timer_s *timer)
{
- uint64_t distance = qemu_get_clock_ns(vm_clock) - timer->time;
+ uint64_t distance = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - timer->time;
if (timer->st && timer->enable && timer->rate)
return timer->val - muldiv64(distance >> (timer->ptv + 1),
@@ -111,7 +111,7 @@
static inline void omap_timer_sync(struct omap_mpu_timer_s *timer)
{
timer->val = omap_timer_read(timer);
- timer->time = qemu_get_clock_ns(vm_clock);
+ timer->time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
static inline void omap_timer_update(struct omap_mpu_timer_s *timer)
@@ -130,11 +130,11 @@
* in a busy loop when it wants to sleep just a couple of CPU
* ticks. */
if (expires > (get_ticks_per_sec() >> 10) || timer->ar)
- qemu_mod_timer(timer->timer, timer->time + expires);
+ timer_mod(timer->timer, timer->time + expires);
else
qemu_bh_schedule(timer->tick);
} else
- qemu_del_timer(timer->timer);
+ timer_del(timer->timer);
}
static void omap_timer_fire(void *opaque)
@@ -240,7 +240,7 @@
static void omap_mpu_timer_reset(struct omap_mpu_timer_s *s)
{
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
s->enable = 0;
s->reset_val = 31337;
s->val = 0;
@@ -259,7 +259,7 @@
s->irq = irq;
s->clk = clk;
- s->timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, s);
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_timer_tick, s);
s->tick = qemu_bh_new(omap_timer_fire, s);
omap_mpu_timer_reset(s);
omap_timer_clk_setup(s);
@@ -363,7 +363,7 @@
static void omap_wd_timer_reset(struct omap_watchdog_timer_s *s)
{
- qemu_del_timer(s->timer.timer);
+ timer_del(s->timer.timer);
if (!s->mode)
omap_clk_get(s->timer.clk);
s->mode = 1;
@@ -388,7 +388,7 @@
s->timer.irq = irq;
s->timer.clk = clk;
- s->timer.timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, &s->timer);
+ s->timer.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_timer_tick, &s->timer);
omap_wd_timer_reset(s);
omap_timer_clk_setup(&s->timer);
@@ -475,7 +475,7 @@
static void omap_os_timer_reset(struct omap_32khz_timer_s *s)
{
- qemu_del_timer(s->timer.timer);
+ timer_del(s->timer.timer);
s->timer.enable = 0;
s->timer.it_ena = 0;
s->timer.reset_val = 0x00ffffff;
@@ -494,7 +494,7 @@
s->timer.irq = irq;
s->timer.clk = clk;
- s->timer.timer = qemu_new_timer_ns(vm_clock, omap_timer_tick, &s->timer);
+ s->timer.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_timer_tick, &s->timer);
omap_os_timer_reset(s);
omap_timer_clk_setup(&s->timer);
@@ -600,7 +600,7 @@
case 0x10: /* GAUGING_CTRL */
/* Bits 0 and 1 seem to be confused in the OMAP 310 TRM */
if ((s->ulpd_pm_regs[addr >> 2] ^ value) & 1) {
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (value & 1)
s->ulpd_gauge_start = now;
@@ -2881,7 +2881,7 @@
if (s->auto_comp && !s->current_tm.tm_sec && !s->current_tm.tm_min)
s->tick += s->comp_reg * 1000 / 32768;
- qemu_mod_timer(s->clk, s->tick);
+ timer_mod(s->clk, s->tick);
}
static void omap_rtc_reset(struct omap_rtc_s *s)
@@ -2894,7 +2894,7 @@
s->pm_am = 0;
s->auto_comp = 0;
s->round = 0;
- s->tick = qemu_get_clock_ms(rtc_clock);
+ s->tick = qemu_clock_get_ms(rtc_clock);
memset(&s->alarm_tm, 0, sizeof(s->alarm_tm));
s->alarm_tm.tm_mday = 0x01;
s->status = 1 << 7;
@@ -2915,7 +2915,7 @@
s->irq = timerirq;
s->alarm = alarmirq;
- s->clk = qemu_new_timer_ms(rtc_clock, omap_rtc_tick, s);
+ s->clk = timer_new_ms(rtc_clock, omap_rtc_tick, s);
omap_rtc_reset(s);
@@ -3009,7 +3009,7 @@
s->rx_req = s->rx_rate << bps[(s->rcr[0] >> 5) & 7];
omap_mcbsp_rx_newdata(s);
- qemu_mod_timer(s->source_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(s->source_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
get_ticks_per_sec());
}
@@ -3025,7 +3025,7 @@
static void omap_mcbsp_rx_stop(struct omap_mcbsp_s *s)
{
- qemu_del_timer(s->source_timer);
+ timer_del(s->source_timer);
}
static void omap_mcbsp_rx_done(struct omap_mcbsp_s *s)
@@ -3055,7 +3055,7 @@
s->tx_req = s->tx_rate << bps[(s->xcr[0] >> 5) & 7];
omap_mcbsp_tx_newdata(s);
- qemu_mod_timer(s->sink_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(s->sink_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
get_ticks_per_sec());
}
@@ -3082,7 +3082,7 @@
{
s->tx_req = 0;
omap_mcbsp_tx_done(s);
- qemu_del_timer(s->sink_timer);
+ timer_del(s->sink_timer);
}
static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
@@ -3432,8 +3432,8 @@
s->rx_req = 0;
s->tx_rate = 0;
s->rx_rate = 0;
- qemu_del_timer(s->source_timer);
- qemu_del_timer(s->sink_timer);
+ timer_del(s->source_timer);
+ timer_del(s->sink_timer);
}
static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory,
@@ -3448,8 +3448,8 @@
s->rxirq = rxirq;
s->txdrq = dma[0];
s->rxdrq = dma[1];
- s->sink_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_sink_tick, s);
- s->source_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_source_tick, s);
+ s->sink_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_mcbsp_sink_tick, s);
+ s->source_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_mcbsp_source_tick, s);
omap_mcbsp_reset(s);
memory_region_init_io(&s->iomem, NULL, &omap_mcbsp_ops, s, "omap-mcbsp", 0x800);
@@ -3503,9 +3503,9 @@
struct omap_lpg_s *s = opaque;
if (s->cycle)
- qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->period - s->on);
+ timer_mod(s->tm, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + s->period - s->on);
else
- qemu_mod_timer(s->tm, qemu_get_clock_ms(vm_clock) + s->on);
+ timer_mod(s->tm, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + s->on);
s->cycle = !s->cycle;
printf("%s: LED is %s\n", __FUNCTION__, s->cycle ? "on" : "off");
@@ -3527,7 +3527,7 @@
per[(s->control >> 3) & 7], 256) : 0; /* ONCTRL */
}
- qemu_del_timer(s->tm);
+ timer_del(s->tm);
if (on == period && s->on < s->period)
printf("%s: LED is on\n", __FUNCTION__);
else if (on == 0 && s->on)
@@ -3623,7 +3623,7 @@
struct omap_lpg_s *s = (struct omap_lpg_s *)
g_malloc0(sizeof(struct omap_lpg_s));
- s->tm = qemu_new_timer_ms(vm_clock, omap_lpg_tick, s);
+ s->tm = timer_new_ms(QEMU_CLOCK_VIRTUAL, omap_lpg_tick, s);
omap_lpg_reset(s);
@@ -3827,7 +3827,6 @@
int i;
struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
g_malloc0(sizeof(struct omap_mpu_state_s));
- qemu_irq *cpu_irq;
qemu_irq dma_irqs[6];
DriveInfo *dinfo;
SysBusDevice *busdev;
@@ -3860,14 +3859,15 @@
omap_clkm_init(system_memory, 0xfffece00, 0xe1008000, s);
- cpu_irq = arm_pic_init_cpu(s->cpu);
s->ih[0] = qdev_create(NULL, "omap-intc");
qdev_prop_set_uint32(s->ih[0], "size", 0x100);
qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck"));
qdev_init_nofail(s->ih[0]);
busdev = SYS_BUS_DEVICE(s->ih[0]);
- sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
- sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
+ sysbus_connect_irq(busdev, 0,
+ qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
+ sysbus_connect_irq(busdev, 1,
+ qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ));
sysbus_mmio_map(busdev, 0, 0xfffecb00);
s->ih[1] = qdev_create(NULL, "omap-intc");
qdev_prop_set_uint32(s->ih[1], "size", 0x800);
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
index ec9610b..36efde0 100644
--- a/hw/arm/omap2.c
+++ b/hw/arm/omap2.c
@@ -2244,7 +2244,6 @@
{
struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
g_malloc0(sizeof(struct omap_mpu_state_s));
- qemu_irq *cpu_irq;
qemu_irq dma_irqs[4];
DriveInfo *dinfo;
int i;
@@ -2277,15 +2276,16 @@
s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
/* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
- cpu_irq = arm_pic_init_cpu(s->cpu);
s->ih[0] = qdev_create(NULL, "omap2-intc");
qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
qdev_prop_set_ptr(s->ih[0], "iclk", omap_findclk(s, "mpu_intc_iclk"));
qdev_init_nofail(s->ih[0]);
busdev = SYS_BUS_DEVICE(s->ih[0]);
- sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
- sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
+ sysbus_connect_irq(busdev, 0,
+ qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
+ sysbus_connect_irq(busdev, 1,
+ qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ));
sysbus_mmio_map(busdev, 0, 0x480fe000);
s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
qdev_get_gpio_in(s->ih[0],
diff --git a/hw/arm/pic_cpu.c b/hw/arm/pic_cpu.c
deleted file mode 100644
index 875280a..0000000
--- a/hw/arm/pic_cpu.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Generic ARM Programmable Interrupt Controller support.
- *
- * Copyright (c) 2006 CodeSourcery.
- * Written by Paul Brook
- *
- * This code is licensed under the LGPL
- */
-
-#include "hw/hw.h"
-#include "hw/arm/arm.h"
-#include "sysemu/kvm.h"
-
-/* Input 0 is IRQ and input 1 is FIQ. */
-static void arm_pic_cpu_handler(void *opaque, int irq, int level)
-{
- ARMCPU *cpu = opaque;
- CPUState *cs = CPU(cpu);
-
- switch (irq) {
- case ARM_PIC_CPU_IRQ:
- if (level) {
- cpu_interrupt(cs, CPU_INTERRUPT_HARD);
- } else {
- cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
- }
- break;
- case ARM_PIC_CPU_FIQ:
- if (level) {
- cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
- } else {
- cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
- }
- break;
- default:
- hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
- }
-}
-
-static void kvm_arm_pic_cpu_handler(void *opaque, int irq, int level)
-{
-#ifdef CONFIG_KVM
- ARMCPU *cpu = opaque;
- CPUState *cs = CPU(cpu);
- int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
-
- switch (irq) {
- case ARM_PIC_CPU_IRQ:
- kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
- break;
- case ARM_PIC_CPU_FIQ:
- kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
- break;
- default:
- hw_error("kvm_arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
- }
- kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
- kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
-#endif
-}
-
-qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
-{
- if (kvm_enabled()) {
- return qemu_allocate_irqs(kvm_arm_pic_cpu_handler, cpu, 2);
- }
- return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
-}
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 3c520d7..02b7016 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -335,7 +335,7 @@
{
PXA2xxState *s = (PXA2xxState *)ri->opaque;
if (s->pmnc & 1) {
- *value = qemu_get_clock_ns(vm_clock);
+ *value = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
} else {
*value = 0;
}
@@ -457,9 +457,16 @@
}
};
+#define TYPE_PXA2XX_SSP "pxa2xx-ssp"
+#define PXA2XX_SSP(obj) \
+ OBJECT_CHECK(PXA2xxSSPState, (obj), TYPE_PXA2XX_SSP)
+
/* Synchronous Serial Ports */
typedef struct {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
qemu_irq irq;
int enable;
@@ -757,19 +764,20 @@
return 0;
}
-static int pxa2xx_ssp_init(SysBusDevice *dev)
+static int pxa2xx_ssp_init(SysBusDevice *sbd)
{
- PXA2xxSSPState *s = FROM_SYSBUS(PXA2xxSSPState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ PXA2xxSSPState *s = PXA2XX_SSP(dev);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_ssp_ops, s,
"pxa2xx-ssp", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0,
+ sysbus_init_mmio(sbd, &s->iomem);
+ register_savevm(dev, "pxa2xx_ssp", -1, 0,
pxa2xx_ssp_save, pxa2xx_ssp_load, s);
- s->bus = ssi_create_bus(&dev->qdev, "ssi");
+ s->bus = ssi_create_bus(dev, "ssi");
return 0;
}
@@ -790,8 +798,15 @@
#define RTCPICR 0x34 /* RTC Periodic Interrupt Counter register */
#define PIAR 0x38 /* RTC Periodic Interrupt Alarm register */
+#define TYPE_PXA2XX_RTC "pxa2xx_rtc"
+#define PXA2XX_RTC(obj) \
+ OBJECT_CHECK(PXA2xxRTCState, (obj), TYPE_PXA2XX_RTC)
+
typedef struct {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
uint32_t rttr;
uint32_t rtsr;
@@ -827,7 +842,7 @@
static void pxa2xx_rtc_hzupdate(PXA2xxRTCState *s)
{
- int64_t rt = qemu_get_clock_ms(rtc_clock);
+ int64_t rt = qemu_clock_get_ms(rtc_clock);
s->last_rcnr += ((rt - s->last_hz) << 15) /
(1000 * ((s->rttr & 0xffff) + 1));
s->last_rdcr += ((rt - s->last_hz) << 15) /
@@ -837,7 +852,7 @@
static void pxa2xx_rtc_swupdate(PXA2xxRTCState *s)
{
- int64_t rt = qemu_get_clock_ms(rtc_clock);
+ int64_t rt = qemu_clock_get_ms(rtc_clock);
if (s->rtsr & (1 << 12))
s->last_swcr += (rt - s->last_sw) / 10;
s->last_sw = rt;
@@ -845,7 +860,7 @@
static void pxa2xx_rtc_piupdate(PXA2xxRTCState *s)
{
- int64_t rt = qemu_get_clock_ms(rtc_clock);
+ int64_t rt = qemu_clock_get_ms(rtc_clock);
if (s->rtsr & (1 << 15))
s->last_swcr += rt - s->last_pi;
s->last_pi = rt;
@@ -855,43 +870,43 @@
uint32_t rtsr)
{
if ((rtsr & (1 << 2)) && !(rtsr & (1 << 0)))
- qemu_mod_timer(s->rtc_hz, s->last_hz +
+ timer_mod(s->rtc_hz, s->last_hz +
(((s->rtar - s->last_rcnr) * 1000 *
((s->rttr & 0xffff) + 1)) >> 15));
else
- qemu_del_timer(s->rtc_hz);
+ timer_del(s->rtc_hz);
if ((rtsr & (1 << 5)) && !(rtsr & (1 << 4)))
- qemu_mod_timer(s->rtc_rdal1, s->last_hz +
+ timer_mod(s->rtc_rdal1, s->last_hz +
(((s->rdar1 - s->last_rdcr) * 1000 *
((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
else
- qemu_del_timer(s->rtc_rdal1);
+ timer_del(s->rtc_rdal1);
if ((rtsr & (1 << 7)) && !(rtsr & (1 << 6)))
- qemu_mod_timer(s->rtc_rdal2, s->last_hz +
+ timer_mod(s->rtc_rdal2, s->last_hz +
(((s->rdar2 - s->last_rdcr) * 1000 *
((s->rttr & 0xffff) + 1)) >> 15)); /* TODO: fixup */
else
- qemu_del_timer(s->rtc_rdal2);
+ timer_del(s->rtc_rdal2);
if ((rtsr & 0x1200) == 0x1200 && !(rtsr & (1 << 8)))
- qemu_mod_timer(s->rtc_swal1, s->last_sw +
+ timer_mod(s->rtc_swal1, s->last_sw +
(s->swar1 - s->last_swcr) * 10); /* TODO: fixup */
else
- qemu_del_timer(s->rtc_swal1);
+ timer_del(s->rtc_swal1);
if ((rtsr & 0x1800) == 0x1800 && !(rtsr & (1 << 10)))
- qemu_mod_timer(s->rtc_swal2, s->last_sw +
+ timer_mod(s->rtc_swal2, s->last_sw +
(s->swar2 - s->last_swcr) * 10); /* TODO: fixup */
else
- qemu_del_timer(s->rtc_swal2);
+ timer_del(s->rtc_swal2);
if ((rtsr & 0xc000) == 0xc000 && !(rtsr & (1 << 13)))
- qemu_mod_timer(s->rtc_pi, s->last_pi +
+ timer_mod(s->rtc_pi, s->last_pi +
(s->piar & 0xffff) - s->last_rtcpicr);
else
- qemu_del_timer(s->rtc_pi);
+ timer_del(s->rtc_pi);
}
static inline void pxa2xx_rtc_hz_tick(void *opaque)
@@ -971,16 +986,19 @@
case PIAR:
return s->piar;
case RCNR:
- return s->last_rcnr + ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
- (1000 * ((s->rttr & 0xffff) + 1));
+ return s->last_rcnr +
+ ((qemu_clock_get_ms(rtc_clock) - s->last_hz) << 15) /
+ (1000 * ((s->rttr & 0xffff) + 1));
case RDCR:
- return s->last_rdcr + ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
- (1000 * ((s->rttr & 0xffff) + 1));
+ return s->last_rdcr +
+ ((qemu_clock_get_ms(rtc_clock) - s->last_hz) << 15) /
+ (1000 * ((s->rttr & 0xffff) + 1));
case RYCR:
return s->last_rycr;
case SWCR:
if (s->rtsr & (1 << 12))
- return s->last_swcr + (qemu_get_clock_ms(rtc_clock) - s->last_sw) / 10;
+ return s->last_swcr +
+ (qemu_clock_get_ms(rtc_clock) - s->last_sw) / 10;
else
return s->last_swcr;
default:
@@ -1102,7 +1120,7 @@
static int pxa2xx_rtc_init(SysBusDevice *dev)
{
- PXA2xxRTCState *s = FROM_SYSBUS(PXA2xxRTCState, dev);
+ PXA2xxRTCState *s = PXA2XX_RTC(dev);
struct tm tm;
int wom;
@@ -1120,14 +1138,14 @@
s->last_swcr = (tm.tm_hour << 19) |
(tm.tm_min << 13) | (tm.tm_sec << 7);
s->last_rtcpicr = 0;
- s->last_hz = s->last_sw = s->last_pi = qemu_get_clock_ms(rtc_clock);
+ s->last_hz = s->last_sw = s->last_pi = qemu_clock_get_ms(rtc_clock);
- s->rtc_hz = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_hz_tick, s);
- s->rtc_rdal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal1_tick, s);
- s->rtc_rdal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_rdal2_tick, s);
- s->rtc_swal1 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal1_tick, s);
- s->rtc_swal2 = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_swal2_tick, s);
- s->rtc_pi = qemu_new_timer_ms(rtc_clock, pxa2xx_rtc_pi_tick, s);
+ s->rtc_hz = timer_new_ms(rtc_clock, pxa2xx_rtc_hz_tick, s);
+ s->rtc_rdal1 = timer_new_ms(rtc_clock, pxa2xx_rtc_rdal1_tick, s);
+ s->rtc_rdal2 = timer_new_ms(rtc_clock, pxa2xx_rtc_rdal2_tick, s);
+ s->rtc_swal1 = timer_new_ms(rtc_clock, pxa2xx_rtc_swal1_tick, s);
+ s->rtc_swal2 = timer_new_ms(rtc_clock, pxa2xx_rtc_swal2_tick, s);
+ s->rtc_pi = timer_new_ms(rtc_clock, pxa2xx_rtc_pi_tick, s);
sysbus_init_irq(dev, &s->rtc_irq);
@@ -1197,7 +1215,7 @@
}
static const TypeInfo pxa2xx_rtc_sysbus_info = {
- .name = "pxa2xx_rtc",
+ .name = TYPE_PXA2XX_RTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxRTCState),
.class_init = pxa2xx_rtc_sysbus_class_init,
@@ -1209,8 +1227,15 @@
PXA2xxI2CState *host;
} PXA2xxI2CSlaveState;
+#define TYPE_PXA2XX_I2C "pxa2xx_i2c"
+#define PXA2XX_I2C(obj) \
+ OBJECT_CHECK(PXA2xxI2CState, (obj), TYPE_PXA2XX_I2C)
+
struct PXA2xxI2CState {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
PXA2xxI2CSlaveState *slave;
i2c_bus *bus;
@@ -1457,35 +1482,38 @@
DeviceState *dev;
SysBusDevice *i2c_dev;
PXA2xxI2CState *s;
+ i2c_bus *i2cbus;
- i2c_dev = SYS_BUS_DEVICE(qdev_create(NULL, "pxa2xx_i2c"));
- qdev_prop_set_uint32(&i2c_dev->qdev, "size", region_size + 1);
- qdev_prop_set_uint32(&i2c_dev->qdev, "offset", base & region_size);
+ dev = qdev_create(NULL, TYPE_PXA2XX_I2C);
+ qdev_prop_set_uint32(dev, "size", region_size + 1);
+ qdev_prop_set_uint32(dev, "offset", base & region_size);
+ qdev_init_nofail(dev);
- qdev_init_nofail(&i2c_dev->qdev);
-
+ i2c_dev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(i2c_dev, 0, base & ~region_size);
sysbus_connect_irq(i2c_dev, 0, irq);
- s = FROM_SYSBUS(PXA2xxI2CState, i2c_dev);
+ s = PXA2XX_I2C(i2c_dev);
/* FIXME: Should the slave device really be on a separate bus? */
- dev = i2c_create_slave(i2c_init_bus(NULL, "dummy"), "pxa2xx-i2c-slave", 0);
+ i2cbus = i2c_init_bus(dev, "dummy");
+ dev = i2c_create_slave(i2cbus, "pxa2xx-i2c-slave", 0);
s->slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, I2C_SLAVE(dev));
s->slave->host = s;
return s;
}
-static int pxa2xx_i2c_initfn(SysBusDevice *dev)
+static int pxa2xx_i2c_initfn(SysBusDevice *sbd)
{
- PXA2xxI2CState *s = FROM_SYSBUS(PXA2xxI2CState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ PXA2xxI2CState *s = PXA2XX_I2C(dev);
- s->bus = i2c_init_bus(&dev->qdev, "i2c");
+ s->bus = i2c_init_bus(dev, "i2c");
memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_i2c_ops, s,
"pxa2xx-i2c", s->region_size);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
return 0;
}
@@ -1513,7 +1541,7 @@
}
static const TypeInfo pxa2xx_i2c_info = {
- .name = "pxa2xx_i2c",
+ .name = TYPE_PXA2XX_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxI2CState),
.class_init = pxa2xx_i2c_class_init,
@@ -2107,7 +2135,7 @@
s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
for (i = 0; pxa27x_ssp[i].io_base; i ++) {
DeviceState *dev;
- dev = sysbus_create_simple("pxa2xx-ssp", pxa27x_ssp[i].io_base,
+ dev = sysbus_create_simple(TYPE_PXA2XX_SSP, pxa27x_ssp[i].io_base,
qdev_get_gpio_in(s->pic, pxa27x_ssp[i].irqn));
s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
}
@@ -2120,7 +2148,7 @@
s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
- sysbus_create_simple("pxa2xx_rtc", 0x40900000,
+ sysbus_create_simple(TYPE_PXA2XX_RTC, 0x40900000,
qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
s->i2c[0] = pxa2xx_i2c_init(0x40301600,
@@ -2238,7 +2266,7 @@
s->ssp = (SSIBus **)g_malloc0(sizeof(SSIBus *) * i);
for (i = 0; pxa255_ssp[i].io_base; i ++) {
DeviceState *dev;
- dev = sysbus_create_simple("pxa2xx-ssp", pxa255_ssp[i].io_base,
+ dev = sysbus_create_simple(TYPE_PXA2XX_SSP, pxa255_ssp[i].io_base,
qdev_get_gpio_in(s->pic, pxa255_ssp[i].irqn));
s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
}
@@ -2251,7 +2279,7 @@
s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20000000);
s->pcmcia[1] = pxa2xx_pcmcia_init(address_space, 0x30000000);
- sysbus_create_simple("pxa2xx_rtc", 0x40900000,
+ sysbus_create_simple(TYPE_PXA2XX_RTC, 0x40900000,
qdev_get_gpio_in(s->pic, PXA2XX_PIC_RTCALARM));
s->i2c[0] = pxa2xx_i2c_init(0x40301600,
@@ -2278,7 +2306,7 @@
}
static const TypeInfo pxa2xx_ssp_info = {
- .name = "pxa2xx-ssp",
+ .name = TYPE_PXA2XX_SSP,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxSSPState),
.class_init = pxa2xx_ssp_class_init,
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
index f8c3ee0..ca77f56 100644
--- a/hw/arm/pxa2xx_gpio.c
+++ b/hw/arm/pxa2xx_gpio.c
@@ -13,9 +13,16 @@
#define PXA2XX_GPIO_BANKS 4
+#define TYPE_PXA2XX_GPIO "pxa2xx-gpio"
+#define PXA2XX_GPIO(obj) \
+ OBJECT_CHECK(PXA2xxGPIOInfo, (obj), TYPE_PXA2XX_GPIO)
+
typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
struct PXA2xxGPIOInfo {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
qemu_irq irq0, irq1, irqX;
int lines;
@@ -256,7 +263,7 @@
CPUState *cs = CPU(cpu);
DeviceState *dev;
- dev = qdev_create(NULL, "pxa2xx-gpio");
+ dev = qdev_create(NULL, TYPE_PXA2XX_GPIO);
qdev_prop_set_int32(dev, "lines", lines);
qdev_prop_set_int32(dev, "ncpu", cs->cpu_index);
qdev_init_nofail(dev);
@@ -272,22 +279,21 @@
return dev;
}
-static int pxa2xx_gpio_initfn(SysBusDevice *dev)
+static int pxa2xx_gpio_initfn(SysBusDevice *sbd)
{
- PXA2xxGPIOInfo *s;
-
- s = FROM_SYSBUS(PXA2xxGPIOInfo, dev);
+ DeviceState *dev = DEVICE(sbd);
+ PXA2xxGPIOInfo *s = PXA2XX_GPIO(dev);
s->cpu = ARM_CPU(qemu_get_cpu(s->ncpu));
- qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
- qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
+ qdev_init_gpio_in(dev, pxa2xx_gpio_set, s->lines);
+ qdev_init_gpio_out(dev, s->handler, s->lines);
memory_region_init_io(&s->iomem, OBJECT(s), &pxa_gpio_ops, s, "pxa2xx-gpio", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq0);
- sysbus_init_irq(dev, &s->irq1);
- sysbus_init_irq(dev, &s->irqX);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq0);
+ sysbus_init_irq(sbd, &s->irq1);
+ sysbus_init_irq(sbd, &s->irqX);
return 0;
}
@@ -298,7 +304,8 @@
*/
void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler)
{
- PXA2xxGPIOInfo *s = FROM_SYSBUS(PXA2xxGPIOInfo, SYS_BUS_DEVICE(dev));
+ PXA2xxGPIOInfo *s = PXA2XX_GPIO(dev);
+
s->read_notify = handler;
}
@@ -337,7 +344,7 @@
}
static const TypeInfo pxa2xx_gpio_info = {
- .name = "pxa2xx-gpio",
+ .name = TYPE_PXA2XX_GPIO,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxGPIOInfo),
.class_init = pxa2xx_gpio_class_init,
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index 8929b6d..46d337c 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -31,8 +31,15 @@
#define PXA2XX_PIC_SRCS 40
+#define TYPE_PXA2XX_PIC "pxa2xx_pic"
+#define PXA2XX_PIC(obj) \
+ OBJECT_CHECK(PXA2xxPICState, (obj), TYPE_PXA2XX_PIC)
+
typedef struct {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
ARMCPU *cpu;
uint32_t int_enabled[2];
@@ -260,9 +267,8 @@
DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu)
{
- CPUARMState *env = &cpu->env;
- DeviceState *dev = qdev_create(NULL, "pxa2xx_pic");
- PXA2xxPICState *s = FROM_SYSBUS(PXA2xxPICState, SYS_BUS_DEVICE(dev));
+ DeviceState *dev = qdev_create(NULL, TYPE_PXA2XX_PIC);
+ PXA2xxPICState *s = PXA2XX_PIC(dev);
s->cpu = cpu;
@@ -284,7 +290,7 @@
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
/* Enable IC coprocessor access. */
- define_arm_cp_regs_with_opaque(arm_env_get_cpu(env), pxa_pic_cp_reginfo, s);
+ define_arm_cp_regs_with_opaque(cpu, pxa_pic_cp_reginfo, s);
return dev;
}
@@ -321,7 +327,7 @@
}
static const TypeInfo pxa2xx_pic_info = {
- .name = "pxa2xx_pic",
+ .name = TYPE_PXA2XX_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxPICState),
.class_init = pxa2xx_pic_class_init,
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index 3060f48..82ec02d 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -56,7 +56,6 @@
MemoryRegion *ram_hack = g_new(MemoryRegion, 1);
DeviceState *dev, *sysctl, *gpio2, *pl041;
SysBusDevice *busdev;
- qemu_irq *irqp;
qemu_irq pic[64];
qemu_irq mmc_irq[2];
PCIBus *pci_bus = NULL;
@@ -92,8 +91,7 @@
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- irqp = arm_pic_init_cpu(cpu);
- cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+ cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
}
env = &cpu->env;
if (arm_feature(env, ARM_FEATURE_V7)) {
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 593b75e..9b9ce95 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -50,8 +50,12 @@
#define FLASHCTL_RYBY (1 << 5)
#define FLASHCTL_NCE (FLASHCTL_CE0 | FLASHCTL_CE1)
+#define TYPE_SL_NAND "sl-nand"
+#define SL_NAND(obj) OBJECT_CHECK(SLNANDState, (obj), TYPE_SL_NAND)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
DeviceState *nand;
uint8_t ctl;
@@ -147,7 +151,7 @@
{
DeviceState *dev;
- dev = qdev_create(NULL, "sl-nand");
+ dev = qdev_create(NULL, TYPE_SL_NAND);
qdev_prop_set_uint8(dev, "manf_id", NAND_MFR_SAMSUNG);
if (size == FLASH_128M)
@@ -159,12 +163,11 @@
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, FLASH_BASE);
}
-static int sl_nand_init(SysBusDevice *dev) {
- SLNANDState *s;
+static int sl_nand_init(SysBusDevice *dev)
+{
+ SLNANDState *s = SL_NAND(dev);
DriveInfo *nand;
- s = FROM_SYSBUS(SLNANDState, dev);
-
s->ctl = 0;
nand = drive_get(IF_MTD, 0, 0);
s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id);
@@ -212,8 +215,13 @@
SPITZ_GPIO_SWA, SPITZ_GPIO_SWB,
};
+#define TYPE_SPITZ_KEYBOARD "spitz-keyboard"
+#define SPITZ_KEYBOARD(obj) \
+ OBJECT_CHECK(SpitzKeyboardState, (obj), TYPE_SPITZ_KEYBOARD)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
qemu_irq sense[SPITZ_KEY_SENSE_NUM];
qemu_irq gpiomap[5];
int keymap[0x80];
@@ -385,7 +393,7 @@
s->fifopos = 0;
}
- qemu_mod_timer(s->kbdtimer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(s->kbdtimer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
get_ticks_per_sec() / 32);
}
@@ -458,8 +466,8 @@
DeviceState *dev;
SpitzKeyboardState *s;
- dev = sysbus_create_simple("spitz-keyboard", -1, NULL);
- s = FROM_SYSBUS(SpitzKeyboardState, SYS_BUS_DEVICE(dev));
+ dev = sysbus_create_simple(TYPE_SPITZ_KEYBOARD, -1, NULL);
+ s = SPITZ_KEYBOARD(dev);
for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++)
qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(cpu->gpio, spitz_gpio_key_sense[i]));
@@ -477,18 +485,17 @@
qdev_connect_gpio_out(cpu->gpio, spitz_gpio_key_strobe[i],
qdev_get_gpio_in(dev, i));
- qemu_mod_timer(s->kbdtimer, qemu_get_clock_ns(vm_clock));
+ timer_mod(s->kbdtimer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
qemu_add_kbd_event_handler(spitz_keyboard_handler, s);
}
-static int spitz_keyboard_init(SysBusDevice *dev)
+static int spitz_keyboard_init(SysBusDevice *sbd)
{
- SpitzKeyboardState *s;
+ DeviceState *dev = DEVICE(sbd);
+ SpitzKeyboardState *s = SPITZ_KEYBOARD(dev);
int i, j;
- s = FROM_SYSBUS(SpitzKeyboardState, dev);
-
for (i = 0; i < 0x80; i ++)
s->keymap[i] = -1;
for (i = 0; i < SPITZ_KEY_SENSE_NUM + 1; i ++)
@@ -498,9 +505,9 @@
spitz_keyboard_pre_map(s);
- s->kbdtimer = qemu_new_timer_ns(vm_clock, spitz_keyboard_tick, s);
- qdev_init_gpio_in(&dev->qdev, spitz_keyboard_strobe, SPITZ_KEY_STROBE_NUM);
- qdev_init_gpio_out(&dev->qdev, s->sense, SPITZ_KEY_SENSE_NUM);
+ s->kbdtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, spitz_keyboard_tick, s);
+ qdev_init_gpio_in(dev, spitz_keyboard_strobe, SPITZ_KEY_STROBE_NUM);
+ qdev_init_gpio_out(dev, s->sense, SPITZ_KEY_SENSE_NUM);
return 0;
}
@@ -1027,7 +1034,7 @@
}
static const TypeInfo sl_nand_info = {
- .name = "sl-nand",
+ .name = TYPE_SL_NAND,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SLNANDState),
.class_init = sl_nand_class_init,
@@ -1062,7 +1069,7 @@
}
static const TypeInfo spitz_keyboard_info = {
- .name = "spitz-keyboard",
+ .name = TYPE_SPITZ_KEYBOARD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SpitzKeyboardState),
.class_init = spitz_keyboard_class_init,
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index a2b6b17..3237b30 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -43,8 +43,13 @@
/* General purpose timer module. */
+#define TYPE_STELLARIS_GPTM "stellaris-gptm"
+#define STELLARIS_GPTM(obj) \
+ OBJECT_CHECK(gptm_state, (obj), TYPE_STELLARIS_GPTM)
+
typedef struct gptm_state {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t config;
uint32_t mode[2];
@@ -73,14 +78,14 @@
static void gptm_stop(gptm_state *s, int n)
{
- qemu_del_timer(s->timer[n]);
+ timer_del(s->timer[n]);
}
static void gptm_reload(gptm_state *s, int n, int reset)
{
int64_t tick;
if (reset)
- tick = qemu_get_clock_ns(vm_clock);
+ tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
else
tick = s->tick[n];
@@ -98,7 +103,7 @@
hw_error("TODO: 16-bit timer mode 0x%x\n", s->mode[n]);
}
s->tick[n] = tick;
- qemu_mod_timer(s->timer[n], tick);
+ timer_mod(s->timer[n], tick);
}
static void gptm_tick(void *opaque)
@@ -300,21 +305,22 @@
}
};
-static int stellaris_gptm_init(SysBusDevice *dev)
+static int stellaris_gptm_init(SysBusDevice *sbd)
{
- gptm_state *s = FROM_SYSBUS(gptm_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ gptm_state *s = STELLARIS_GPTM(dev);
- sysbus_init_irq(dev, &s->irq);
- qdev_init_gpio_out(&dev->qdev, &s->trigger, 1);
+ sysbus_init_irq(sbd, &s->irq);
+ qdev_init_gpio_out(dev, &s->trigger, 1);
memory_region_init_io(&s->iomem, OBJECT(s), &gptm_ops, s,
"gptm", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
s->opaque[0] = s->opaque[1] = s;
- s->timer[0] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[0]);
- s->timer[1] = qemu_new_timer_ns(vm_clock, gptm_tick, &s->opaque[1]);
- vmstate_register(&dev->qdev, -1, &vmstate_stellaris_gptm, s);
+ s->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[0]);
+ s->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[1]);
+ vmstate_register(dev, -1, &vmstate_stellaris_gptm, s);
return 0;
}
@@ -679,8 +685,13 @@
/* I2C controller. */
+#define TYPE_STELLARIS_I2C "stellaris-i2c"
+#define STELLARIS_I2C(obj) \
+ OBJECT_CHECK(stellaris_i2c_state, (obj), TYPE_STELLARIS_I2C)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
i2c_bus *bus;
qemu_irq irq;
MemoryRegion iomem;
@@ -853,21 +864,22 @@
}
};
-static int stellaris_i2c_init(SysBusDevice * dev)
+static int stellaris_i2c_init(SysBusDevice *sbd)
{
- stellaris_i2c_state *s = FROM_SYSBUS(stellaris_i2c_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ stellaris_i2c_state *s = STELLARIS_I2C(dev);
i2c_bus *bus;
- sysbus_init_irq(dev, &s->irq);
- bus = i2c_init_bus(&dev->qdev, "i2c");
+ sysbus_init_irq(sbd, &s->irq);
+ bus = i2c_init_bus(dev, "i2c");
s->bus = bus;
memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_i2c_ops, s,
"i2c", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
/* ??? For now we only implement the master interface. */
stellaris_i2c_reset(s);
- vmstate_register(&dev->qdev, -1, &vmstate_stellaris_i2c, s);
+ vmstate_register(dev, -1, &vmstate_stellaris_i2c, s);
return 0;
}
@@ -885,9 +897,13 @@
#define STELLARIS_ADC_FIFO_EMPTY 0x0100
#define STELLARIS_ADC_FIFO_FULL 0x1000
-typedef struct
-{
- SysBusDevice busdev;
+#define TYPE_STELLARIS_ADC "stellaris-adc"
+#define STELLARIS_ADC(obj) \
+ OBJECT_CHECK(stellaris_adc_state, (obj), TYPE_STELLARIS_ADC)
+
+typedef struct StellarisADCState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t actss;
uint32_t ris;
@@ -1136,21 +1152,22 @@
}
};
-static int stellaris_adc_init(SysBusDevice *dev)
+static int stellaris_adc_init(SysBusDevice *sbd)
{
- stellaris_adc_state *s = FROM_SYSBUS(stellaris_adc_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ stellaris_adc_state *s = STELLARIS_ADC(dev);
int n;
for (n = 0; n < 4; n++) {
- sysbus_init_irq(dev, &s->irq[n]);
+ sysbus_init_irq(sbd, &s->irq[n]);
}
memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_adc_ops, s,
"adc", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
stellaris_adc_reset(s);
- qdev_init_gpio_in(&dev->qdev, stellaris_adc_trigger, 1);
- vmstate_register(&dev->qdev, -1, &vmstate_stellaris_adc, s);
+ qdev_init_gpio_in(dev, stellaris_adc_trigger, 1);
+ vmstate_register(dev, -1, &vmstate_stellaris_adc, s);
return 0;
}
@@ -1207,7 +1224,7 @@
flash_size, sram_size, kernel_filename, cpu_model);
if (board->dc1 & (1 << 16)) {
- dev = sysbus_create_varargs("stellaris-adc", 0x40038000,
+ dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000,
pic[14], pic[15], pic[16], pic[17], NULL);
adc = qdev_get_gpio_in(dev, 0);
} else {
@@ -1215,7 +1232,7 @@
}
for (i = 0; i < 4; i++) {
if (board->dc2 & (0x10000 << i)) {
- dev = sysbus_create_simple("stellaris-gptm",
+ dev = sysbus_create_simple(TYPE_STELLARIS_GPTM,
0x40030000 + i * 0x1000,
pic[timer_irq[i]]);
/* TODO: This is incorrect, but we get away with it because
@@ -1238,7 +1255,7 @@
}
if (board->dc2 & (1 << 12)) {
- dev = sysbus_create_simple("stellaris-i2c", 0x40020000, pic[8]);
+ dev = sysbus_create_simple(TYPE_STELLARIS_I2C, 0x40020000, pic[8]);
i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
if (board->peripherals & BP_OLED_I2C) {
i2c_create_slave(i2c, "ssd0303", 0x3d);
@@ -1357,7 +1374,7 @@
}
static const TypeInfo stellaris_i2c_info = {
- .name = "stellaris-i2c",
+ .name = TYPE_STELLARIS_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(stellaris_i2c_state),
.class_init = stellaris_i2c_class_init,
@@ -1371,7 +1388,7 @@
}
static const TypeInfo stellaris_gptm_info = {
- .name = "stellaris-gptm",
+ .name = TYPE_STELLARIS_GPTM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(gptm_state),
.class_init = stellaris_gptm_class_init,
@@ -1385,7 +1402,7 @@
}
static const TypeInfo stellaris_adc_info = {
- .name = "stellaris-adc",
+ .name = TYPE_STELLARIS_ADC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(stellaris_adc_state),
.class_init = stellaris_adc_class_init,
diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c
index feaaf45..170d0ce 100644
--- a/hw/arm/strongarm.c
+++ b/hw/arm/strongarm.c
@@ -70,8 +70,14 @@
};
/* Interrupt Controller */
-typedef struct {
- SysBusDevice busdev;
+
+#define TYPE_STRONGARM_PIC "strongarm_pic"
+#define STRONGARM_PIC(obj) \
+ OBJECT_CHECK(StrongARMPICState, (obj), TYPE_STRONGARM_PIC)
+
+typedef struct StrongARMPICState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq irq;
qemu_irq fiq;
@@ -168,16 +174,17 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int strongarm_pic_initfn(SysBusDevice *dev)
+static int strongarm_pic_initfn(SysBusDevice *sbd)
{
- StrongARMPICState *s = FROM_SYSBUS(StrongARMPICState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ StrongARMPICState *s = STRONGARM_PIC(dev);
- qdev_init_gpio_in(&dev->qdev, strongarm_pic_set_irq, SA_PIC_SRCS);
+ qdev_init_gpio_in(dev, strongarm_pic_set_irq, SA_PIC_SRCS);
memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_pic_ops, s,
"pic", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
- sysbus_init_irq(dev, &s->fiq);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+ sysbus_init_irq(sbd, &s->fiq);
return 0;
}
@@ -214,7 +221,7 @@
}
static const TypeInfo strongarm_pic_info = {
- .name = "strongarm_pic",
+ .name = TYPE_STRONGARM_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMPICState),
.class_init = strongarm_pic_class_init,
@@ -235,8 +242,13 @@
* trim delete isn't emulated, so
* f = 32 768 / (RTTR_trim + 1) */
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_STRONGARM_RTC "strongarm-rtc"
+#define STRONGARM_RTC(obj) \
+ OBJECT_CHECK(StrongARMRTCState, (obj), TYPE_STRONGARM_RTC)
+
+typedef struct StrongARMRTCState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t rttr;
uint32_t rtsr;
@@ -257,7 +269,7 @@
static void strongarm_rtc_hzupdate(StrongARMRTCState *s)
{
- int64_t rt = qemu_get_clock_ms(rtc_clock);
+ int64_t rt = qemu_clock_get_ms(rtc_clock);
s->last_rcnr += ((rt - s->last_hz) << 15) /
(1000 * ((s->rttr & 0xffff) + 1));
s->last_hz = rt;
@@ -266,17 +278,17 @@
static inline void strongarm_rtc_timer_update(StrongARMRTCState *s)
{
if ((s->rtsr & RTSR_HZE) && !(s->rtsr & RTSR_HZ)) {
- qemu_mod_timer(s->rtc_hz, s->last_hz + 1000);
+ timer_mod(s->rtc_hz, s->last_hz + 1000);
} else {
- qemu_del_timer(s->rtc_hz);
+ timer_del(s->rtc_hz);
}
if ((s->rtsr & RTSR_ALE) && !(s->rtsr & RTSR_AL)) {
- qemu_mod_timer(s->rtc_alarm, s->last_hz +
+ timer_mod(s->rtc_alarm, s->last_hz +
(((s->rtar - s->last_rcnr) * 1000 *
((s->rttr & 0xffff) + 1)) >> 15));
} else {
- qemu_del_timer(s->rtc_alarm);
+ timer_del(s->rtc_alarm);
}
}
@@ -310,7 +322,7 @@
return s->rtar;
case RCNR:
return s->last_rcnr +
- ((qemu_get_clock_ms(rtc_clock) - s->last_hz) << 15) /
+ ((qemu_clock_get_ms(rtc_clock) - s->last_hz) << 15) /
(1000 * ((s->rttr & 0xffff) + 1));
default:
printf("%s: Bad register 0x" TARGET_FMT_plx "\n", __func__, addr);
@@ -367,7 +379,7 @@
static int strongarm_rtc_init(SysBusDevice *dev)
{
- StrongARMRTCState *s = FROM_SYSBUS(StrongARMRTCState, dev);
+ StrongARMRTCState *s = STRONGARM_RTC(dev);
struct tm tm;
s->rttr = 0x0;
@@ -376,10 +388,10 @@
qemu_get_timedate(&tm, 0);
s->last_rcnr = (uint32_t) mktimegm(&tm);
- s->last_hz = qemu_get_clock_ms(rtc_clock);
+ s->last_hz = qemu_clock_get_ms(rtc_clock);
- s->rtc_alarm = qemu_new_timer_ms(rtc_clock, strongarm_rtc_alarm_tick, s);
- s->rtc_hz = qemu_new_timer_ms(rtc_clock, strongarm_rtc_hz_tick, s);
+ s->rtc_alarm = timer_new_ms(rtc_clock, strongarm_rtc_alarm_tick, s);
+ s->rtc_hz = timer_new_ms(rtc_clock, strongarm_rtc_hz_tick, s);
sysbus_init_irq(dev, &s->rtc_irq);
sysbus_init_irq(dev, &s->rtc_hz_irq);
@@ -436,7 +448,7 @@
}
static const TypeInfo strongarm_rtc_sysbus_info = {
- .name = "strongarm-rtc",
+ .name = TYPE_STRONGARM_RTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMRTCState),
.class_init = strongarm_rtc_sysbus_class_init,
@@ -452,6 +464,10 @@
#define GEDR 0x18
#define GAFR 0x1c
+#define TYPE_STRONGARM_GPIO "strongarm-gpio"
+#define STRONGARM_GPIO(obj) \
+ OBJECT_CHECK(StrongARMGPIOInfo, (obj), TYPE_STRONGARM_GPIO)
+
typedef struct StrongARMGPIOInfo StrongARMGPIOInfo;
struct StrongARMGPIOInfo {
SysBusDevice busdev;
@@ -618,7 +634,7 @@
DeviceState *dev;
int i;
- dev = qdev_create(NULL, "strongarm-gpio");
+ dev = qdev_create(NULL, TYPE_STRONGARM_GPIO);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
@@ -629,24 +645,23 @@
return dev;
}
-static int strongarm_gpio_initfn(SysBusDevice *dev)
+static int strongarm_gpio_initfn(SysBusDevice *sbd)
{
- StrongARMGPIOInfo *s;
+ DeviceState *dev = DEVICE(sbd);
+ StrongARMGPIOInfo *s = STRONGARM_GPIO(dev);
int i;
- s = FROM_SYSBUS(StrongARMGPIOInfo, dev);
-
- qdev_init_gpio_in(&dev->qdev, strongarm_gpio_set, 28);
- qdev_init_gpio_out(&dev->qdev, s->handler, 28);
+ qdev_init_gpio_in(dev, strongarm_gpio_set, 28);
+ qdev_init_gpio_out(dev, s->handler, 28);
memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_gpio_ops, s,
"gpio", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
for (i = 0; i < 11; i++) {
- sysbus_init_irq(dev, &s->irqs[i]);
+ sysbus_init_irq(sbd, &s->irqs[i]);
}
- sysbus_init_irq(dev, &s->irqX);
+ sysbus_init_irq(sbd, &s->irqX);
return 0;
}
@@ -678,7 +693,7 @@
}
static const TypeInfo strongarm_gpio_info = {
- .name = "strongarm-gpio",
+ .name = TYPE_STRONGARM_GPIO,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMGPIOInfo),
.class_init = strongarm_gpio_class_init,
@@ -691,9 +706,14 @@
#define PSDR 0x0c
#define PPFR 0x10
+#define TYPE_STRONGARM_PPC "strongarm-ppc"
+#define STRONGARM_PPC(obj) \
+ OBJECT_CHECK(StrongARMPPCInfo, (obj), TYPE_STRONGARM_PPC)
+
typedef struct StrongARMPPCInfo StrongARMPPCInfo;
struct StrongARMPPCInfo {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq handler[28];
@@ -802,19 +822,18 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int strongarm_ppc_init(SysBusDevice *dev)
+static int strongarm_ppc_init(SysBusDevice *sbd)
{
- StrongARMPPCInfo *s;
+ DeviceState *dev = DEVICE(sbd);
+ StrongARMPPCInfo *s = STRONGARM_PPC(dev);
- s = FROM_SYSBUS(StrongARMPPCInfo, dev);
-
- qdev_init_gpio_in(&dev->qdev, strongarm_ppc_set, 22);
- qdev_init_gpio_out(&dev->qdev, s->handler, 22);
+ qdev_init_gpio_in(dev, strongarm_ppc_set, 22);
+ qdev_init_gpio_out(dev, s->handler, 22);
memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_ppc_ops, s,
"ppc", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
return 0;
}
@@ -845,7 +864,7 @@
}
static const TypeInfo strongarm_ppc_info = {
- .name = "strongarm-ppc",
+ .name = TYPE_STRONGARM_PPC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMPPCInfo),
.class_init = strongarm_ppc_class_init,
@@ -889,8 +908,13 @@
#define RX_FIFO_FRE (1 << 9)
#define RX_FIFO_ROR (1 << 10)
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_STRONGARM_UART "strongarm-uart"
+#define STRONGARM_UART(obj) \
+ OBJECT_CHECK(StrongARMUARTState, (obj), TYPE_STRONGARM_UART)
+
+typedef struct StrongARMUARTState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
CharDriverState *chr;
qemu_irq irq;
@@ -1061,8 +1085,8 @@
}
/* call the timeout receive callback in 3 char transmit time */
- qemu_mod_timer(s->rx_timeout_timer,
- qemu_get_clock_ns(vm_clock) + s->char_transmit_time * 3);
+ timer_mod(s->rx_timeout_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time * 3);
strongarm_uart_update_status(s);
strongarm_uart_update_int_status(s);
@@ -1083,7 +1107,7 @@
static void strongarm_uart_tx(void *opaque)
{
StrongARMUARTState *s = opaque;
- uint64_t new_xmit_ts = qemu_get_clock_ns(vm_clock);
+ uint64_t new_xmit_ts = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (s->utcr3 & UTCR3_LBM) /* loopback */ {
strongarm_uart_receive(s, &s->tx_fifo[s->tx_start], 1);
@@ -1094,7 +1118,7 @@
s->tx_start = (s->tx_start + 1) % 8;
s->tx_len--;
if (s->tx_len) {
- qemu_mod_timer(s->tx_timer, new_xmit_ts + s->char_transmit_time);
+ timer_mod(s->tx_timer, new_xmit_ts + s->char_transmit_time);
}
strongarm_uart_update_status(s);
strongarm_uart_update_int_status(s);
@@ -1206,15 +1230,15 @@
static int strongarm_uart_init(SysBusDevice *dev)
{
- StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev);
+ StrongARMUARTState *s = STRONGARM_UART(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_uart_ops, s,
"uart", 0x10000);
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
- s->rx_timeout_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_rx_to, s);
- s->tx_timer = qemu_new_timer_ns(vm_clock, strongarm_uart_tx, s);
+ s->rx_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_rx_to, s);
+ s->tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_tx, s);
if (s->chr) {
qemu_chr_add_handlers(s->chr,
@@ -1229,7 +1253,7 @@
static void strongarm_uart_reset(DeviceState *dev)
{
- StrongARMUARTState *s = DO_UPCAST(StrongARMUARTState, busdev.qdev, dev);
+ StrongARMUARTState *s = STRONGARM_UART(dev);
s->utcr0 = UTCR0_DSS; /* 8 data, no parity */
s->brd = 23; /* 9600 */
@@ -1258,8 +1282,8 @@
/* restart rx timeout timer */
if (s->rx_len) {
- qemu_mod_timer(s->rx_timeout_timer,
- qemu_get_clock_ns(vm_clock) + s->char_transmit_time * 3);
+ timer_mod(s->rx_timeout_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time * 3);
}
return 0;
@@ -1305,15 +1329,21 @@
}
static const TypeInfo strongarm_uart_info = {
- .name = "strongarm-uart",
+ .name = TYPE_STRONGARM_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMUARTState),
.class_init = strongarm_uart_class_init,
};
/* Synchronous Serial Ports */
-typedef struct {
- SysBusDevice busdev;
+
+#define TYPE_STRONGARM_SSP "strongarm-ssp"
+#define STRONGARM_SSP(obj) \
+ OBJECT_CHECK(StrongARMSSPState, (obj), TYPE_STRONGARM_SSP)
+
+typedef struct StrongARMSSPState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq irq;
SSIBus *bus;
@@ -1495,23 +1525,25 @@
return 0;
}
-static int strongarm_ssp_init(SysBusDevice *dev)
+static int strongarm_ssp_init(SysBusDevice *sbd)
{
- StrongARMSSPState *s = FROM_SYSBUS(StrongARMSSPState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ StrongARMSSPState *s = STRONGARM_SSP(dev);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_ssp_ops, s,
"ssp", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
- s->bus = ssi_create_bus(&dev->qdev, "ssi");
+ s->bus = ssi_create_bus(dev, "ssi");
return 0;
}
static void strongarm_ssp_reset(DeviceState *dev)
{
- StrongARMSSPState *s = DO_UPCAST(StrongARMSSPState, busdev.qdev, dev);
+ StrongARMSSPState *s = STRONGARM_SSP(dev);
+
s->sssr = 0x03; /* 3 bit data, SPI, disabled */
s->rx_start = 0;
s->rx_level = 0;
@@ -1545,7 +1577,7 @@
}
static const TypeInfo strongarm_ssp_info = {
- .name = "strongarm-ssp",
+ .name = TYPE_STRONGARM_SSP,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(StrongARMSSPState),
.class_init = strongarm_ssp_class_init,
@@ -1556,7 +1588,6 @@
unsigned int sdram_size, const char *rev)
{
StrongARMState *s;
- qemu_irq *pic;
int i;
s = g_malloc0(sizeof(StrongARMState));
@@ -1581,9 +1612,10 @@
vmstate_register_ram_global(&s->sdram);
memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram);
- pic = arm_pic_init_cpu(s->cpu);
s->pic = sysbus_create_varargs("strongarm_pic", 0x90050000,
- pic[ARM_PIC_CPU_IRQ], pic[ARM_PIC_CPU_FIQ], NULL);
+ qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ),
+ qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ),
+ NULL);
sysbus_create_varargs("pxa25x-timer", 0x90000000,
qdev_get_gpio_in(s->pic, SA_PIC_OSTC0),
@@ -1592,15 +1624,15 @@
qdev_get_gpio_in(s->pic, SA_PIC_OSTC3),
NULL);
- sysbus_create_simple("strongarm-rtc", 0x90010000,
+ sysbus_create_simple(TYPE_STRONGARM_RTC, 0x90010000,
qdev_get_gpio_in(s->pic, SA_PIC_RTC_ALARM));
s->gpio = strongarm_gpio_init(0x90040000, s->pic);
- s->ppc = sysbus_create_varargs("strongarm-ppc", 0x90060000, NULL);
+ s->ppc = sysbus_create_varargs(TYPE_STRONGARM_PPC, 0x90060000, NULL);
for (i = 0; sa_serial[i].io_base; i++) {
- DeviceState *dev = qdev_create(NULL, "strongarm-uart");
+ DeviceState *dev = qdev_create(NULL, TYPE_STRONGARM_UART);
qdev_prop_set_chr(dev, "chardev", serial_hds[i]);
qdev_init_nofail(dev);
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0,
@@ -1609,7 +1641,7 @@
qdev_get_gpio_in(s->pic, sa_serial[i].irq));
}
- s->ssp = sysbus_create_varargs("strongarm-ssp", 0x80070000,
+ s->ssp = sysbus_create_varargs(TYPE_STRONGARM_SSP, 0x80070000,
qdev_get_gpio_in(s->pic, SA_PIC_SSP), NULL);
s->ssp_bus = (SSIBus *)qdev_get_child_bus(s->ssp, "ssi");
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index 725f60f..4a6fcee 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -25,15 +25,19 @@
/* Primary interrupt controller. */
-typedef struct vpb_sic_state
-{
- SysBusDevice busdev;
- MemoryRegion iomem;
- uint32_t level;
- uint32_t mask;
- uint32_t pic_enable;
- qemu_irq parent[32];
- int irq;
+#define TYPE_VERSATILE_PB_SIC "versatilepb_sic"
+#define VERSATILE_PB_SIC(obj) \
+ OBJECT_CHECK(vpb_sic_state, (obj), TYPE_VERSATILE_PB_SIC)
+
+typedef struct vpb_sic_state {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ uint32_t level;
+ uint32_t mask;
+ uint32_t pic_enable;
+ qemu_irq parent[32];
+ int irq;
} vpb_sic_state;
static const VMStateDescription vmstate_vpb_sic = {
@@ -144,19 +148,20 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int vpb_sic_init(SysBusDevice *dev)
+static int vpb_sic_init(SysBusDevice *sbd)
{
- vpb_sic_state *s = FROM_SYSBUS(vpb_sic_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ vpb_sic_state *s = VERSATILE_PB_SIC(dev);
int i;
- qdev_init_gpio_in(&dev->qdev, vpb_sic_set_irq, 32);
+ qdev_init_gpio_in(dev, vpb_sic_set_irq, 32);
for (i = 0; i < 32; i++) {
- sysbus_init_irq(dev, &s->parent[i]);
+ sysbus_init_irq(sbd, &s->parent[i]);
}
s->irq = 31;
memory_region_init_io(&s->iomem, OBJECT(s), &vpb_sic_ops, s,
"vpb-sic", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
return 0;
}
@@ -173,7 +178,6 @@
ARMCPU *cpu;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
- qemu_irq *cpu_pic;
qemu_irq pic[32];
qemu_irq sic[32];
DeviceState *dev, *sysctl;
@@ -206,14 +210,14 @@
qdev_init_nofail(sysctl);
sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000);
- cpu_pic = arm_pic_init_cpu(cpu);
dev = sysbus_create_varargs("pl190", 0x10140000,
- cpu_pic[ARM_PIC_CPU_IRQ],
- cpu_pic[ARM_PIC_CPU_FIQ], NULL);
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
+ NULL);
for (n = 0; n < 32; n++) {
pic[n] = qdev_get_gpio_in(dev, n);
}
- dev = sysbus_create_simple("versatilepb_sic", 0x10003000, NULL);
+ dev = sysbus_create_simple(TYPE_VERSATILE_PB_SIC, 0x10003000, NULL);
for (n = 0; n < 32; n++) {
sysbus_connect_irq(SYS_BUS_DEVICE(dev), n, pic[n]);
sic[n] = qdev_get_gpio_in(dev, n);
@@ -393,7 +397,7 @@
}
static const TypeInfo vpb_sic_info = {
- .name = "versatilepb_sic",
+ .name = TYPE_VERSATILE_PB_SIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(vpb_sic_state),
.class_init = vpb_sic_class_init,
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 9586e38..fbd71a7 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -183,7 +183,6 @@
MemoryRegion *lowram = g_new(MemoryRegion, 1);
DeviceState *dev;
SysBusDevice *busdev;
- qemu_irq *irqp;
int n;
qemu_irq cpu_irq[4];
ram_addr_t low_ram_size;
@@ -198,8 +197,7 @@
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- irqp = arm_pic_init_cpu(cpu);
- cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+ cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
}
if (ram_size > 0x40000000) {
@@ -312,15 +310,13 @@
for (n = 0; n < smp_cpus; n++) {
ARMCPU *cpu;
- qemu_irq *irqp;
cpu = cpu_arm_init(cpu_model);
if (!cpu) {
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- irqp = arm_pic_init_cpu(cpu);
- cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+ cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ);
}
{
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 3444823..0f18c85 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -108,11 +108,9 @@
MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
DeviceState *dev;
SysBusDevice *busdev;
- qemu_irq *irqp;
qemu_irq pic[64];
NICInfo *nd;
int n;
- qemu_irq cpu_irq;
if (!cpu_model) {
cpu_model = "cortex-a9";
@@ -123,8 +121,6 @@
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
- irqp = arm_pic_init_cpu(cpu);
- cpu_irq = irqp[ARM_PIC_CPU_IRQ];
/* max 2GB ram */
if (ram_size > 0x80000000) {
@@ -159,7 +155,8 @@
qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(busdev, 0, 0xF8F00000);
- sysbus_connect_irq(busdev, 0, cpu_irq);
+ sysbus_connect_irq(busdev, 0,
+ qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ));
for (n = 0; n < 64; n++) {
pic[n] = qdev_get_gpio_in(dev, n);
diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c
index 365b2f1..01b4dfb 100644
--- a/hw/audio/ac97.c
+++ b/hw/audio/ac97.c
@@ -1420,6 +1420,7 @@
k->device_id = PCI_DEVICE_ID_INTEL_82801AA_5;
k->revision = 0x01;
k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "Intel 82801AA AC97 Audio";
dc->vmsd = &vmstate_ac97;
dc->props = ac97_properties;
diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c
index f72e6ee..0c79247 100644
--- a/hw/audio/adlib.c
+++ b/hw/audio/adlib.c
@@ -173,7 +173,7 @@
s->ticking[n] = 1;
#ifdef DEBUG
interval = get_ticks_per_sec () * interval_Sec;
- exp = qemu_get_clock_ns (vm_clock) + interval;
+ exp = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + interval;
s->exp[n] = exp;
#endif
@@ -364,6 +364,7 @@
DeviceClass *dc = DEVICE_CLASS (klass);
dc->realize = adlib_realizefn;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = ADLIB_DESC;
dc->props = adlib_properties;
}
diff --git a/hw/audio/cs4231.c b/hw/audio/cs4231.c
index fabe9e6..d19195a 100644
--- a/hw/audio/cs4231.c
+++ b/hw/audio/cs4231.c
@@ -33,8 +33,13 @@
#define CS_DREGS 32
#define CS_MAXDREG (CS_DREGS - 1)
+#define TYPE_CS4231 "SUNW,CS4231"
+#define CS4231(obj) \
+ OBJECT_CHECK(CSState, (obj), TYPE_CS4231)
+
typedef struct CSState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq irq;
uint32_t regs[CS_REGS];
@@ -47,7 +52,7 @@
static void cs_reset(DeviceState *d)
{
- CSState *s = container_of(d, CSState, busdev.qdev);
+ CSState *s = CS4231(d);
memset(s->regs, 0, CS_REGS * 4);
memset(s->dregs, 0, CS_DREGS);
@@ -111,7 +116,7 @@
break;
case 4:
if (val & 1) {
- cs_reset(&s->busdev.qdev);
+ cs_reset(DEVICE(s));
}
val &= 0x7f;
s->regs[saddr] = val;
@@ -142,7 +147,7 @@
static int cs4231_init1(SysBusDevice *dev)
{
- CSState *s = FROM_SYSBUS(CSState, dev);
+ CSState *s = CS4231(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &cs_mem_ops, s, "cs4321",
CS_SIZE);
@@ -168,7 +173,7 @@
}
static const TypeInfo cs4231_info = {
- .name = "SUNW,CS4231",
+ .name = TYPE_CS4231,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(CSState),
.class_init = cs4231_class_init,
diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c
index 7365c3c..666096b 100644
--- a/hw/audio/cs4231a.c
+++ b/hw/audio/cs4231a.c
@@ -685,6 +685,7 @@
dc->realize = cs4231a_realizefn;
dc->reset = cs4231a_reset;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "Crystal Semiconductor CS4231A";
dc->vmsd = &vmstate_cs4231a;
dc->props = cs4231a_properties;
diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c
index f2c40da..adb66ce 100644
--- a/hw/audio/es1370.c
+++ b/hw/audio/es1370.c
@@ -1069,6 +1069,7 @@
k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
k->subsystem_vendor_id = 0x4942;
k->subsystem_id = 0x4c4c;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "ENSONIQ AudioPCI ES1370";
dc->vmsd = &vmstate_es1370;
}
diff --git a/hw/audio/gus.c b/hw/audio/gus.c
index f45ed0b..71be3c6 100644
--- a/hw/audio/gus.c
+++ b/hw/audio/gus.c
@@ -315,6 +315,7 @@
DeviceClass *dc = DEVICE_CLASS (klass);
dc->realize = gus_realizefn;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "Gravis Ultrasound GF1";
dc->vmsd = &vmstate_gus;
dc->props = gus_properties;
diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
index 362d8c0..9550c97 100644
--- a/hw/audio/hda-codec.c
+++ b/hw/audio/hda-codec.c
@@ -1034,6 +1034,7 @@
k->exit = hda_audio_exit;
k->command = hda_audio_command;
k->stream = hda_audio_stream;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "HDA Audio Codec, output-only (line-out)";
dc->vmsd = &vmstate_hda_audio;
dc->props = hda_audio_properties;
@@ -1055,6 +1056,7 @@
k->exit = hda_audio_exit;
k->command = hda_audio_command;
k->stream = hda_audio_stream;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "HDA Audio Codec, duplex (line-out, line-in)";
dc->vmsd = &vmstate_hda_audio;
dc->props = hda_audio_properties;
@@ -1076,6 +1078,7 @@
k->exit = hda_audio_exit;
k->command = hda_audio_command;
k->stream = hda_audio_stream;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "HDA Audio Codec, duplex (speaker, microphone)";
dc->vmsd = &vmstate_hda_audio;
dc->props = hda_audio_properties;
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index 58984dc..78f9d28 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -526,7 +526,7 @@
{
int64_t ns;
- ns = qemu_get_clock_ns(vm_clock) - d->wall_base_ns;
+ ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - d->wall_base_ns;
d->wall_clk = (uint32_t)(ns * 24 / 1000); /* 24 MHz */
}
@@ -1111,7 +1111,7 @@
HDACodecDevice *cdev;
intel_hda_regs_reset(d);
- d->wall_base_ns = qemu_get_clock_ns(vm_clock);
+ d->wall_base_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
/* reset codecs */
QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
@@ -1258,6 +1258,7 @@
k->device_id = 0x2668;
k->revision = 1;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "Intel HD Audio Controller (ich6)";
}
@@ -1268,6 +1269,7 @@
k->device_id = 0x293e;
k->revision = 3;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "Intel HD Audio Controller (ich9)";
}
@@ -1296,6 +1298,7 @@
DeviceClass *k = DEVICE_CLASS(klass);
k->init = hda_codec_dev_init;
k->exit = hda_codec_dev_exit;
+ set_bit(DEVICE_CATEGORY_SOUND, k->categories);
k->bus_type = TYPE_HDA_BUS;
k->props = hda_props;
}
diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
index b40ea43..97194ce 100644
--- a/hw/audio/marvell_88w8618.c
+++ b/hw/audio/marvell_88w8618.c
@@ -36,8 +36,13 @@
#define MP_AUDIO_CLOCK_24MHZ (1 << 9)
#define MP_AUDIO_MONO (1 << 14)
+#define TYPE_MV88W8618_AUDIO "mv88w8618_audio"
+#define MV88W8618_AUDIO(obj) \
+ OBJECT_CHECK(mv88w8618_audio_state, (obj), TYPE_MV88W8618_AUDIO)
+
typedef struct mv88w8618_audio_state {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq irq;
uint32_t playback_mode;
@@ -219,8 +224,7 @@
static void mv88w8618_audio_reset(DeviceState *d)
{
- mv88w8618_audio_state *s = FROM_SYSBUS(mv88w8618_audio_state,
- SYS_BUS_DEVICE(d));
+ mv88w8618_audio_state *s = MV88W8618_AUDIO(d);
s->playback_mode = 0;
s->status = 0;
@@ -238,7 +242,7 @@
static int mv88w8618_audio_init(SysBusDevice *dev)
{
- mv88w8618_audio_state *s = FROM_SYSBUS(mv88w8618_audio_state, dev);
+ mv88w8618_audio_state *s = MV88W8618_AUDIO(dev);
sysbus_init_irq(dev, &s->irq);
@@ -287,7 +291,7 @@
}
static const TypeInfo mv88w8618_audio_info = {
- .name = "mv88w8618_audio",
+ .name = TYPE_MV88W8618_AUDIO,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(mv88w8618_audio_state),
.class_init = mv88w8618_audio_class_init,
diff --git a/hw/audio/milkymist-ac97.c b/hw/audio/milkymist-ac97.c
index 133de4e..9c0f7a0 100644
--- a/hw/audio/milkymist-ac97.c
+++ b/hw/audio/milkymist-ac97.c
@@ -51,8 +51,13 @@
CTRL_EN = (1<<0),
};
+#define TYPE_MILKYMIST_AC97 "milkymist-ac97"
+#define MILKYMIST_AC97(obj) \
+ OBJECT_CHECK(MilkymistAC97State, (obj), TYPE_MILKYMIST_AC97)
+
struct MilkymistAC97State {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion regs_region;
QEMUSoundCard card;
@@ -258,7 +263,7 @@
static void milkymist_ac97_reset(DeviceState *d)
{
- MilkymistAC97State *s = container_of(d, MilkymistAC97State, busdev.qdev);
+ MilkymistAC97State *s = MILKYMIST_AC97(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -280,7 +285,7 @@
static int milkymist_ac97_init(SysBusDevice *dev)
{
- MilkymistAC97State *s = FROM_SYSBUS(typeof(*s), dev);
+ MilkymistAC97State *s = MILKYMIST_AC97(dev);
struct audsettings as;
sysbus_init_irq(dev, &s->crrequest_irq);
@@ -330,7 +335,7 @@
}
static const TypeInfo milkymist_ac97_info = {
- .name = "milkymist-ac97",
+ .name = TYPE_MILKYMIST_AC97,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistAC97State),
.class_init = milkymist_ac97_class_init,
diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
index 7ad59a1..9004ce3 100644
--- a/hw/audio/pcspk.c
+++ b/hw/audio/pcspk.c
@@ -191,6 +191,7 @@
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = pcspk_realizefn;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->no_user = 1;
dc->props = pcspk_properties;
}
diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c
index 7d331b9..5393b52 100644
--- a/hw/audio/pl041.c
+++ b/hw/audio/pl041.c
@@ -70,8 +70,12 @@
uint8_t rx_sample_size;
} pl041_channel;
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PL041 "pl041"
+#define PL041(obj) OBJECT_CHECK(PL041State, (obj), TYPE_PL041)
+
+typedef struct PL041State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq irq;
@@ -80,7 +84,7 @@
pl041_regfile regs;
pl041_channel fifo1;
lm4549_state codec;
-} pl041_state;
+} PL041State;
static const unsigned char pl041_default_id[8] = {
@@ -107,7 +111,7 @@
}
#endif
-static uint8_t pl041_compute_periphid3(pl041_state *s)
+static uint8_t pl041_compute_periphid3(PL041State *s)
{
uint8_t id3 = 1; /* One channel */
@@ -142,7 +146,7 @@
return id3;
}
-static void pl041_reset(pl041_state *s)
+static void pl041_reset(PL041State *s)
{
DBG_L1("pl041_reset\n");
@@ -156,7 +160,7 @@
}
-static void pl041_fifo1_write(pl041_state *s, uint32_t value)
+static void pl041_fifo1_write(PL041State *s, uint32_t value)
{
pl041_channel *channel = &s->fifo1;
pl041_fifo *fifo = &s->fifo1.tx_fifo;
@@ -239,7 +243,7 @@
DBG_L2("fifo1_push sr1 = 0x%08x\n", s->regs.sr1);
}
-static void pl041_fifo1_transmit(pl041_state *s)
+static void pl041_fifo1_transmit(PL041State *s)
{
pl041_channel *channel = &s->fifo1;
pl041_fifo *fifo = &s->fifo1.tx_fifo;
@@ -291,7 +295,7 @@
}
}
-static void pl041_isr1_update(pl041_state *s)
+static void pl041_isr1_update(PL041State *s)
{
/* Update ISR1 */
if (s->regs.sr1 & TXUNDERRUN) {
@@ -320,7 +324,7 @@
static void pl041_request_data(void *opaque)
{
- pl041_state *s = (pl041_state *)opaque;
+ PL041State *s = (PL041State *)opaque;
/* Trigger pending transfers */
pl041_fifo1_transmit(s);
@@ -330,7 +334,7 @@
static uint64_t pl041_read(void *opaque, hwaddr offset,
unsigned size)
{
- pl041_state *s = (pl041_state *)opaque;
+ PL041State *s = (PL041State *)opaque;
int value;
if ((offset >= PL041_periphid0) && (offset <= PL041_pcellid3)) {
@@ -364,7 +368,7 @@
static void pl041_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
- pl041_state *s = (pl041_state *)opaque;
+ PL041State *s = (PL041State *)opaque;
uint16_t control, data;
uint32_t result;
@@ -504,7 +508,7 @@
static void pl041_device_reset(DeviceState *d)
{
- pl041_state *s = DO_UPCAST(pl041_state, busdev.qdev, d);
+ PL041State *s = PL041(d);
pl041_reset(s);
}
@@ -517,7 +521,7 @@
static int pl041_init(SysBusDevice *dev)
{
- pl041_state *s = FROM_SYSBUS(pl041_state, dev);
+ PL041State *s = PL041(dev);
DBG_L1("pl041_init 0x%08x\n", (uint32_t)s);
@@ -603,12 +607,12 @@
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(fifo_depth, pl041_state),
- VMSTATE_STRUCT(regs, pl041_state, 0,
+ VMSTATE_UINT32(fifo_depth, PL041State),
+ VMSTATE_STRUCT(regs, PL041State, 0,
vmstate_pl041_regfile, pl041_regfile),
- VMSTATE_STRUCT(fifo1, pl041_state, 0,
+ VMSTATE_STRUCT(fifo1, PL041State, 0,
vmstate_pl041_channel, pl041_channel),
- VMSTATE_STRUCT(codec, pl041_state, 0,
+ VMSTATE_STRUCT(codec, PL041State, 0,
vmstate_lm4549_state, lm4549_state),
VMSTATE_END_OF_LIST()
}
@@ -616,7 +620,8 @@
static Property pl041_device_properties[] = {
/* Non-compact FIFO depth property */
- DEFINE_PROP_UINT32("nc_fifo_depth", pl041_state, fifo_depth, DEFAULT_FIFO_DEPTH),
+ DEFINE_PROP_UINT32("nc_fifo_depth", PL041State, fifo_depth,
+ DEFAULT_FIFO_DEPTH),
DEFINE_PROP_END_OF_LIST(),
};
@@ -626,6 +631,7 @@
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = pl041_init;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->no_user = 1;
dc->reset = pl041_device_reset;
dc->vmsd = &vmstate_pl041;
@@ -633,9 +639,9 @@
}
static const TypeInfo pl041_device_info = {
- .name = "pl041",
+ .name = TYPE_PL041,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl041_state),
+ .instance_size = sizeof(PL041State),
.class_init = pl041_device_class_init,
};
diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c
index e697bc1..db79131 100644
--- a/hw/audio/sb16.c
+++ b/hw/audio/sb16.c
@@ -768,9 +768,9 @@
}
else {
if (s->aux_ts) {
- qemu_mod_timer (
+ timer_mod (
s->aux_ts,
- qemu_get_clock_ns (vm_clock) + ticks
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ticks
);
}
}
@@ -1378,7 +1378,7 @@
s->csp_regs[9] = 0xf8;
reset_mixer (s);
- s->aux_ts = qemu_new_timer_ns (vm_clock, aux_timer, s);
+ s->aux_ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, aux_timer, s);
if (!s->aux_ts) {
dolog ("warning: Could not create auxiliary timer\n");
}
@@ -1412,6 +1412,7 @@
DeviceClass *dc = DEVICE_CLASS (klass);
dc->realize = sb16_realizefn;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "Creative Sound Blaster 16";
dc->vmsd = &vmstate_sb16;
dc->props = sb16_properties;
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
index 25acc67..bf46f03 100644
--- a/hw/block/Makefile.objs
+++ b/hw/block/Makefile.objs
@@ -7,7 +7,6 @@
common-obj-$(CONFIG_XEN_BACKEND) += xen_disk.o
common-obj-$(CONFIG_ECC) += ecc.o
common-obj-$(CONFIG_ONENAND) += onenand.o
-common-obj-$(CONFIG_PC_SYSFW) += pc_sysfw.o
common-obj-$(CONFIG_NVME_PCI) += nvme.o
obj-$(CONFIG_SH4) += tc58128.o
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 2faed43..5a96ccd 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -18,7 +18,6 @@
#include "qemu/error-report.h"
#include "hw/virtio/dataplane/vring.h"
#include "ioq.h"
-#include "migration/migration.h"
#include "block/block.h"
#include "hw/virtio/virtio-blk.h"
#include "virtio-blk.h"
@@ -69,8 +68,6 @@
queue */
unsigned int num_reqs;
-
- Error *migration_blocker;
};
/* Raise an interrupt to signal guest, if necessary */
@@ -264,11 +261,6 @@
}
}
-static int flush_true(EventNotifier *e)
-{
- return true;
-}
-
static void handle_notify(EventNotifier *e)
{
VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
@@ -348,14 +340,6 @@
}
}
-static int flush_io(EventNotifier *e)
-{
- VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
- io_notifier);
-
- return s->num_reqs > 0;
-}
-
static void handle_io(EventNotifier *e)
{
VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
@@ -379,9 +363,9 @@
{
VirtIOBlockDataPlane *s = opaque;
- do {
+ while (!s->stopping || s->num_reqs > 0) {
aio_poll(s->ctx, true);
- } while (!s->stopping || s->num_reqs > 0);
+ }
return NULL;
}
@@ -418,6 +402,14 @@
return false;
}
+ /* If dataplane is (re-)enabled while the guest is running there could be
+ * block jobs that can conflict.
+ */
+ if (bdrv_in_use(blk->conf.bs)) {
+ error_report("cannot start dataplane thread while device is in use");
+ return false;
+ }
+
fd = raw_get_aio_fd(blk->conf.bs);
if (fd < 0) {
error_report("drive is incompatible with x-data-plane, "
@@ -433,10 +425,6 @@
/* Prevent block operations that conflict with data plane thread */
bdrv_set_in_use(blk->conf.bs, 1);
- error_setg(&s->migration_blocker,
- "x-data-plane does not support migration");
- migrate_add_blocker(s->migration_blocker);
-
*dataplane = s;
return true;
}
@@ -448,8 +436,6 @@
}
virtio_blk_data_plane_stop(s);
- migrate_del_blocker(s->migration_blocker);
- error_free(s->migration_blocker);
bdrv_set_in_use(s->blk->conf.bs, 0);
g_free(s);
}
@@ -486,7 +472,7 @@
exit(1);
}
s->host_notifier = *virtio_queue_get_host_notifier(vq);
- aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify, flush_true);
+ aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify);
/* Set up ioqueue */
ioq_init(&s->ioqueue, s->fd, REQ_MAX);
@@ -494,7 +480,7 @@
ioq_put_iocb(&s->ioqueue, &s->requests[i].iocb);
}
s->io_notifier = *ioq_get_notifier(&s->ioqueue);
- aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io, flush_io);
+ aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io);
s->started = true;
trace_virtio_blk_data_plane_start(s);
@@ -526,10 +512,10 @@
qemu_thread_join(&s->thread);
}
- aio_set_event_notifier(s->ctx, &s->io_notifier, NULL, NULL);
+ aio_set_event_notifier(s->ctx, &s->io_notifier, NULL);
ioq_cleanup(&s->ioqueue);
- aio_set_event_notifier(s->ctx, &s->host_notifier, NULL, NULL);
+ aio_set_event_notifier(s->ctx, &s->host_notifier, NULL);
k->set_host_notifier(qbus->parent, 0, false);
aio_context_unref(s->ctx);
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index d32f6ba..c5a6c21 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -544,7 +544,7 @@
uint8_t timer1;
};
-#define TYPE_SYSBUS_FDC "sysbus-fdc"
+#define TYPE_SYSBUS_FDC "base-sysbus-fdc"
#define SYSBUS_FDC(obj) OBJECT_CHECK(FDCtrlSysBus, (obj), TYPE_SYSBUS_FDC)
typedef struct FDCtrlSysBus {
@@ -1647,8 +1647,8 @@
FDrive *cur_drv = get_cur_drv(fdctrl);
cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
- qemu_mod_timer(fdctrl->result_timer,
- qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / 50));
+ timer_mod(fdctrl->result_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (get_ticks_per_sec() / 50));
}
static void fdctrl_handle_format_track(FDCtrl *fdctrl, int direction)
@@ -2055,7 +2055,7 @@
SysBusDevice *sbd;
FDCtrlSysBus *sys;
- dev = qdev_create(NULL, TYPE_SYSBUS_FDC);
+ dev = qdev_create(NULL, "sysbus-fdc");
sys = SYSBUS_FDC(dev);
fdctrl = &sys->state;
fdctrl->dma_chann = dma_chann; /* FIXME */
@@ -2108,7 +2108,7 @@
FLOPPY_DPRINTF("init controller\n");
fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN);
fdctrl->fifo_size = 512;
- fdctrl->result_timer = qemu_new_timer_ns(vm_clock,
+ fdctrl->result_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
fdctrl_result_timer, fdctrl);
fdctrl->version = 0x90; /* Intel 82078 controller */
@@ -2153,60 +2153,49 @@
static void sysbus_fdc_initfn(Object *obj)
{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
FDCtrlSysBus *sys = SYSBUS_FDC(obj);
FDCtrl *fdctrl = &sys->state;
- memory_region_init_io(&fdctrl->iomem, obj, &fdctrl_mem_ops, fdctrl,
- "fdc", 0x08);
-}
-
-static void sysbus_fdc_realize(DeviceState *dev, Error **errp)
-{
- FDCtrlSysBus *sys = SYSBUS_FDC(dev);
- FDCtrl *fdctrl = &sys->state;
- SysBusDevice *b = SYS_BUS_DEVICE(dev);
- Error *err = NULL;
-
- sysbus_init_mmio(b, &fdctrl->iomem);
- sysbus_init_irq(b, &fdctrl->irq);
- qdev_init_gpio_in(dev, fdctrl_handle_tc, 1);
fdctrl->dma_chann = -1;
- qdev_set_legacy_instance_id(dev, 0 /* io */, 2); /* FIXME */
- fdctrl_realize_common(fdctrl, &err);
- if (err != NULL) {
- error_propagate(errp, err);
- return;
- }
+ memory_region_init_io(&fdctrl->iomem, obj, &fdctrl_mem_ops, fdctrl,
+ "fdc", 0x08);
+ sysbus_init_mmio(sbd, &fdctrl->iomem);
}
static void sun4m_fdc_initfn(Object *obj)
{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
FDCtrlSysBus *sys = SYSBUS_FDC(obj);
FDCtrl *fdctrl = &sys->state;
+ fdctrl->sun4m = 1;
+
memory_region_init_io(&fdctrl->iomem, obj, &fdctrl_mem_strict_ops,
fdctrl, "fdctrl", 0x08);
+ sysbus_init_mmio(sbd, &fdctrl->iomem);
}
-static void sun4m_fdc_realize(DeviceState *dev, Error **errp)
+static void sysbus_fdc_common_initfn(Object *obj)
+{
+ DeviceState *dev = DEVICE(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ FDCtrlSysBus *sys = SYSBUS_FDC(obj);
+ FDCtrl *fdctrl = &sys->state;
+
+ qdev_set_legacy_instance_id(dev, 0 /* io */, 2); /* FIXME */
+
+ sysbus_init_irq(sbd, &fdctrl->irq);
+ qdev_init_gpio_in(dev, fdctrl_handle_tc, 1);
+}
+
+static void sysbus_fdc_common_realize(DeviceState *dev, Error **errp)
{
FDCtrlSysBus *sys = SYSBUS_FDC(dev);
FDCtrl *fdctrl = &sys->state;
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
- Error *err = NULL;
- sysbus_init_mmio(sbd, &fdctrl->iomem);
- sysbus_init_irq(sbd, &fdctrl->irq);
- qdev_init_gpio_in(dev, fdctrl_handle_tc, 1);
-
- fdctrl->sun4m = 1;
- qdev_set_legacy_instance_id(dev, 0 /* io */, 2); /* FIXME */
- fdctrl_realize_common(fdctrl, &err);
- if (err != NULL) {
- error_propagate(errp, err);
- return;
- }
+ fdctrl_realize_common(fdctrl, errp);
}
FDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
@@ -2249,6 +2238,7 @@
dc->reset = fdctrl_external_reset_isa;
dc->vmsd = &vmstate_isa_fdc;
dc->props = isa_fdc_properties;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo isa_fdc_info = {
@@ -2278,16 +2268,13 @@
{
DeviceClass *dc = DEVICE_CLASS(klass);
- dc->realize = sysbus_fdc_realize;
- dc->reset = fdctrl_external_reset_sysbus;
- dc->vmsd = &vmstate_sysbus_fdc;
dc->props = sysbus_fdc_properties;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo sysbus_fdc_info = {
- .name = TYPE_SYSBUS_FDC,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(FDCtrlSysBus),
+ .name = "sysbus-fdc",
+ .parent = TYPE_SYSBUS_FDC,
.instance_init = sysbus_fdc_initfn,
.class_init = sysbus_fdc_class_init,
};
@@ -2301,23 +2288,39 @@
{
DeviceClass *dc = DEVICE_CLASS(klass);
- dc->realize = sun4m_fdc_realize;
- dc->reset = fdctrl_external_reset_sysbus;
- dc->vmsd = &vmstate_sysbus_fdc;
dc->props = sun4m_fdc_properties;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo sun4m_fdc_info = {
.name = "SUNW,fdtwo",
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(FDCtrlSysBus),
+ .parent = TYPE_SYSBUS_FDC,
.instance_init = sun4m_fdc_initfn,
.class_init = sun4m_fdc_class_init,
};
+static void sysbus_fdc_common_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = sysbus_fdc_common_realize;
+ dc->reset = fdctrl_external_reset_sysbus;
+ dc->vmsd = &vmstate_sysbus_fdc;
+}
+
+static const TypeInfo sysbus_fdc_type_info = {
+ .name = TYPE_SYSBUS_FDC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(FDCtrlSysBus),
+ .instance_init = sysbus_fdc_common_initfn,
+ .abstract = true,
+ .class_init = sysbus_fdc_common_class_init,
+};
+
static void fdc_register_types(void)
{
type_register_static(&isa_fdc_info);
+ type_register_static(&sysbus_fdc_type_info);
type_register_static(&sysbus_fdc_info);
type_register_static(&sun4m_fdc_info);
}
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index f15f04a..5dee229 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -187,7 +187,7 @@
assert(cq->cqid == req->sq->cqid);
QTAILQ_REMOVE(&req->sq->out_req_list, req, entry);
QTAILQ_INSERT_TAIL(&cq->req_list, req, entry);
- qemu_mod_timer(cq->timer, qemu_get_clock_ns(vm_clock) + 500);
+ timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
}
static void nvme_rw_cb(void *opaque, int ret)
@@ -264,8 +264,8 @@
static void nvme_free_sq(NvmeSQueue *sq, NvmeCtrl *n)
{
n->sq[sq->sqid] = NULL;
- qemu_del_timer(sq->timer);
- qemu_free_timer(sq->timer);
+ timer_del(sq->timer);
+ timer_free(sq->timer);
g_free(sq->io_req);
if (sq->sqid) {
g_free(sq);
@@ -327,7 +327,7 @@
sq->io_req[i].sq = sq;
QTAILQ_INSERT_TAIL(&(sq->req_list), &sq->io_req[i], entry);
}
- sq->timer = qemu_new_timer_ns(vm_clock, nvme_process_sq, sq);
+ sq->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, nvme_process_sq, sq);
assert(n->cq[cqid]);
cq = n->cq[cqid];
@@ -369,8 +369,8 @@
static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n)
{
n->cq[cq->cqid] = NULL;
- qemu_del_timer(cq->timer);
- qemu_free_timer(cq->timer);
+ timer_del(cq->timer);
+ timer_free(cq->timer);
msix_vector_unuse(&n->parent_obj, cq->vector);
if (cq->cqid) {
g_free(cq);
@@ -410,7 +410,7 @@
QTAILQ_INIT(&cq->sq_list);
msix_vector_use(&n->parent_obj, cq->vector);
n->cq[cqid] = cq;
- cq->timer = qemu_new_timer_ns(vm_clock, nvme_post_cqes, cq);
+ cq->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, nvme_post_cqes, cq);
}
static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeCmd *cmd)
@@ -691,9 +691,9 @@
if (start_sqs) {
NvmeSQueue *sq;
QTAILQ_FOREACH(sq, &cq->sq_list, entry) {
- qemu_mod_timer(sq->timer, qemu_get_clock_ns(vm_clock) + 500);
+ timer_mod(sq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
}
- qemu_mod_timer(cq->timer, qemu_get_clock_ns(vm_clock) + 500);
+ timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
}
if (cq->tail != cq->head) {
@@ -714,7 +714,7 @@
}
sq->tail = new_tail;
- qemu_mod_timer(sq->timer, qemu_get_clock_ns(vm_clock) + 500);
+ timer_mod(sq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
}
}
@@ -866,6 +866,7 @@
pc->revision = 1;
pc->is_express = 1;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->desc = "Non-Volatile Memory Express";
dc->props = nvme_props;
dc->vmsd = &nvme_vmstate;
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
index 2776f64..aae9ee7 100644
--- a/hw/block/onenand.c
+++ b/hw/block/onenand.c
@@ -34,8 +34,12 @@
/* Fixed */
#define BLOCK_SHIFT (PAGE_SHIFT + 6)
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_ONE_NAND "onenand"
+#define ONE_NAND(obj) OBJECT_CHECK(OneNANDState, (obj), TYPE_ONE_NAND)
+
+typedef struct OneNANDState {
+ SysBusDevice parent_obj;
+
struct {
uint16_t man;
uint16_t dev;
@@ -226,7 +230,9 @@
static void onenand_system_reset(DeviceState *dev)
{
- onenand_reset(FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(dev)), 1);
+ OneNANDState *s = ONE_NAND(dev);
+
+ onenand_reset(s, 1);
}
static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
@@ -757,11 +763,13 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int onenand_initfn(SysBusDevice *dev)
+static int onenand_initfn(SysBusDevice *sbd)
{
- OneNANDState *s = (OneNANDState *)dev;
+ DeviceState *dev = DEVICE(sbd);
+ OneNANDState *s = ONE_NAND(dev);
uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7));
void *ram;
+
s->base = (hwaddr)-1;
s->rdy = NULL;
s->blocks = size >> BLOCK_SHIFT;
@@ -794,9 +802,9 @@
s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift);
s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
onenand_mem_setup(s);
- sysbus_init_irq(dev, &s->intr);
- sysbus_init_mmio(dev, &s->container);
- vmstate_register(&dev->qdev,
+ sysbus_init_irq(sbd, &s->intr);
+ sysbus_init_mmio(sbd, &s->container);
+ vmstate_register(dev,
((s->shift & 0x7f) << 24)
| ((s->id.man & 0xff) << 16)
| ((s->id.dev & 0xff) << 8)
@@ -825,7 +833,7 @@
}
static const TypeInfo onenand_info = {
- .name = "onenand",
+ .name = TYPE_ONE_NAND,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(OneNANDState),
.class_init = onenand_class_init,
@@ -838,7 +846,9 @@
void *onenand_raw_otp(DeviceState *onenand_device)
{
- return FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(onenand_device))->otp;
+ OneNANDState *s = ONE_NAND(onenand_device);
+
+ return s->otp;
}
type_init(onenand_register_types)
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 2bcd731..018a967 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -192,6 +192,9 @@
case 0xe8: /* Write block */
/* Status register read */
ret = pfl->status;
+ if (width > 2) {
+ ret |= pfl->status << 16;
+ }
DPRINTF("%s: status %x\n", __func__, ret);
break;
case 0x90:
@@ -610,7 +613,7 @@
pfl->ro = 0;
}
- pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
+ pfl->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);
pfl->wcycle = 0;
pfl->cmd = 0;
pfl->status = 0;
@@ -720,6 +723,7 @@
dc->realize = pflash_cfi01_realize;
dc->props = pflash_cfi01_properties;
dc->vmsd = &vmstate_pflash;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 9fc02e3..99445b0 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -430,8 +430,8 @@
}
pfl->status = 0x00;
/* Let's wait 5 seconds before chip erase is done */
- qemu_mod_timer(pfl->timer,
- qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() * 5));
+ timer_mod(pfl->timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (get_ticks_per_sec() * 5));
break;
case 0x30:
/* Sector erase */
@@ -445,8 +445,8 @@
}
pfl->status = 0x00;
/* Let's wait 1/2 second before sector erase is done */
- qemu_mod_timer(pfl->timer,
- qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / 2));
+ timer_mod(pfl->timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (get_ticks_per_sec() / 2));
break;
default:
DPRINTF("%s: invalid command %02x (wc 5)\n", __func__, cmd);
@@ -633,7 +633,7 @@
pfl->ro = 0;
}
- pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
+ pfl->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);
pfl->wcycle = 0;
pfl->cmd = 0;
pfl->status = 0;
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index cf12469..e2f55cc 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -19,6 +19,7 @@
#include "hw/virtio/virtio-blk.h"
#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
# include "dataplane/virtio-blk.h"
+# include "migration/migration.h"
#endif
#include "block/scsi.h"
#ifdef __linux__
@@ -628,6 +629,34 @@
memcpy(&(s->blk), blk, sizeof(struct VirtIOBlkConf));
}
+#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+/* Disable dataplane thread during live migration since it does not
+ * update the dirty memory bitmap yet.
+ */
+static void virtio_blk_migration_state_changed(Notifier *notifier, void *data)
+{
+ VirtIOBlock *s = container_of(notifier, VirtIOBlock,
+ migration_state_notifier);
+ MigrationState *mig = data;
+
+ if (migration_in_setup(mig)) {
+ if (!s->dataplane) {
+ return;
+ }
+ virtio_blk_data_plane_destroy(s->dataplane);
+ s->dataplane = NULL;
+ } else if (migration_has_finished(mig) ||
+ migration_has_failed(mig)) {
+ if (s->dataplane) {
+ return;
+ }
+ bdrv_drain_all(); /* complete in-flight non-dataplane requests */
+ virtio_blk_data_plane_create(VIRTIO_DEVICE(s), &s->blk,
+ &s->dataplane);
+ }
+}
+#endif /* CONFIG_VIRTIO_BLK_DATA_PLANE */
+
static int virtio_blk_device_init(VirtIODevice *vdev)
{
DeviceState *qdev = DEVICE(vdev);
@@ -664,6 +693,8 @@
virtio_cleanup(vdev);
return -1;
}
+ s->migration_state_notifier.notify = virtio_blk_migration_state_changed;
+ add_migration_state_change_notifier(&s->migration_state_notifier);
#endif
s->change = qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
@@ -683,6 +714,7 @@
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOBlock *s = VIRTIO_BLK(dev);
#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE
+ remove_migration_state_change_notifier(&s->migration_state_notifier);
virtio_blk_data_plane_destroy(s->dataplane);
s->dataplane = NULL;
#endif
@@ -704,6 +736,7 @@
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->exit = virtio_blk_device_exit;
dc->props = virtio_blk_properties;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->init = virtio_blk_device_init;
vdc->get_config = virtio_blk_update_config;
vdc->set_config = virtio_blk_set_config;
diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
index 247f32f..727f433 100644
--- a/hw/block/xen_disk.c
+++ b/hw/block/xen_disk.c
@@ -93,6 +93,7 @@
char *type;
char *dev;
char *devtype;
+ bool directiosafe;
const char *fileproto;
const char *filename;
int ring_ref;
@@ -701,6 +702,7 @@
{
struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
int info = 0;
+ char *directiosafe = NULL;
/* read xenstore entries */
if (blkdev->params == NULL) {
@@ -733,6 +735,8 @@
if (blkdev->devtype == NULL) {
blkdev->devtype = xenstore_read_be_str(&blkdev->xendev, "device-type");
}
+ directiosafe = xenstore_read_be_str(&blkdev->xendev, "direct-io-safe");
+ blkdev->directiosafe = (directiosafe && atoi(directiosafe));
/* do we have all we need? */
if (blkdev->params == NULL ||
@@ -760,6 +764,8 @@
xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1);
xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1);
xenstore_write_be_int(&blkdev->xendev, "info", info);
+
+ g_free(directiosafe);
return 0;
out_error:
@@ -773,6 +779,8 @@
blkdev->dev = NULL;
g_free(blkdev->devtype);
blkdev->devtype = NULL;
+ g_free(directiosafe);
+ blkdev->directiosafe = false;
return -1;
}
@@ -783,7 +791,11 @@
bool readonly = true;
/* read-only ? */
- qflags = BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO;
+ if (blkdev->directiosafe) {
+ qflags = BDRV_O_NOCACHE | BDRV_O_NATIVE_AIO;
+ } else {
+ qflags = BDRV_O_CACHE_WB;
+ }
if (strcmp(blkdev->mode, "w") == 0) {
qflags |= BDRV_O_RDWR;
readonly = false;
diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c
index 16a25cb..7b9b916 100644
--- a/hw/bt/hci-csr.c
+++ b/hw/bt/hci-csr.c
@@ -87,7 +87,7 @@
}
if (s->out_len)
- qemu_mod_timer(s->out_tm, qemu_get_clock_ns(vm_clock) + s->baud_delay);
+ timer_mod(s->out_tm, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->baud_delay);
}
#define csrhci_out_packetz(s, len) memset(csrhci_out_packet(s, len), 0, len)
@@ -446,7 +446,7 @@
s->hci->evt_recv = csrhci_out_hci_packet_event;
s->hci->acl_recv = csrhci_out_hci_packet_acl;
- s->out_tm = qemu_new_timer_ns(vm_clock, csrhci_out_tick, s);
+ s->out_tm = timer_new_ns(QEMU_CLOCK_VIRTUAL, csrhci_out_tick, s);
s->pins = qemu_allocate_irqs(csrhci_pins, s, __csrhci_pins);
csrhci_reset(s);
diff --git a/hw/bt/hci.c b/hw/bt/hci.c
index b53cd5d..d1c0604 100644
--- a/hw/bt/hci.c
+++ b/hw/bt/hci.c
@@ -576,7 +576,7 @@
static void bt_hci_mod_timer_1280ms(QEMUTimer *timer, int period)
{
- qemu_mod_timer(timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
muldiv64(period << 7, get_ticks_per_sec(), 100));
}
@@ -657,7 +657,7 @@
if (master) {
link->acl_mode = acl_active;
hci->lm.handle[hci->lm.last_handle].acl_mode_timer =
- qemu_new_timer_ns(vm_clock, bt_hci_mode_tick, link);
+ timer_new_ns(QEMU_CLOCK_VIRTUAL, bt_hci_mode_tick, link);
}
}
@@ -667,8 +667,8 @@
hci->lm.handle[handle].link = NULL;
if (bt_hci_role_master(hci, handle)) {
- qemu_del_timer(hci->lm.handle[handle].acl_mode_timer);
- qemu_free_timer(hci->lm.handle[handle].acl_mode_timer);
+ timer_del(hci->lm.handle[handle].acl_mode_timer);
+ timer_free(hci->lm.handle[handle].acl_mode_timer);
}
}
@@ -1080,7 +1080,7 @@
bt_hci_event_status(hci, HCI_SUCCESS);
- qemu_mod_timer(link->acl_mode_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(link->acl_mode_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
muldiv64(interval * 625, get_ticks_per_sec(), 1000000));
bt_hci_lmp_mode_change_master(hci, link->link, mode, interval);
@@ -1103,7 +1103,7 @@
bt_hci_event_status(hci, HCI_SUCCESS);
- qemu_del_timer(link->acl_mode_timer);
+ timer_del(link->acl_mode_timer);
bt_hci_lmp_mode_change_master(hci, link->link, acl_active, 0);
return 0;
@@ -1146,10 +1146,10 @@
hci->psb_handle = 0x000;
hci->asb_handle = 0x000;
- /* XXX: qemu_del_timer(sl->acl_mode_timer); for all links */
- qemu_del_timer(hci->lm.inquiry_done);
- qemu_del_timer(hci->lm.inquiry_next);
- qemu_del_timer(hci->conn_accept_timer);
+ /* XXX: timer_del(sl->acl_mode_timer); for all links */
+ timer_del(hci->lm.inquiry_done);
+ timer_del(hci->lm.inquiry_next);
+ timer_del(hci->conn_accept_timer);
}
static void bt_hci_read_local_version_rp(struct bt_hci_s *hci)
@@ -1514,7 +1514,7 @@
}
hci->lm.inquire = 0;
- qemu_del_timer(hci->lm.inquiry_done);
+ timer_del(hci->lm.inquiry_done);
bt_hci_event_complete_status(hci, HCI_SUCCESS);
break;
@@ -1552,8 +1552,8 @@
break;
}
hci->lm.inquire = 0;
- qemu_del_timer(hci->lm.inquiry_done);
- qemu_del_timer(hci->lm.inquiry_next);
+ timer_del(hci->lm.inquiry_done);
+ timer_del(hci->lm.inquiry_next);
bt_hci_event_complete_status(hci, HCI_SUCCESS);
break;
@@ -2141,10 +2141,10 @@
{
struct bt_hci_s *s = g_malloc0(sizeof(struct bt_hci_s));
- s->lm.inquiry_done = qemu_new_timer_ns(vm_clock, bt_hci_inquiry_done, s);
- s->lm.inquiry_next = qemu_new_timer_ns(vm_clock, bt_hci_inquiry_next, s);
+ s->lm.inquiry_done = timer_new_ns(QEMU_CLOCK_VIRTUAL, bt_hci_inquiry_done, s);
+ s->lm.inquiry_next = timer_new_ns(QEMU_CLOCK_VIRTUAL, bt_hci_inquiry_next, s);
s->conn_accept_timer =
- qemu_new_timer_ns(vm_clock, bt_hci_conn_accept_timeout, s);
+ timer_new_ns(QEMU_CLOCK_VIRTUAL, bt_hci_conn_accept_timeout, s);
s->evt_packet = bt_hci_evt_packet;
s->evt_submit = bt_hci_evt_submit;
@@ -2209,9 +2209,9 @@
* s->device.lmp_connection_complete to free the remaining bits once
* hci->lm.awaiting_bdaddr[] is empty. */
- qemu_free_timer(hci->lm.inquiry_done);
- qemu_free_timer(hci->lm.inquiry_next);
- qemu_free_timer(hci->conn_accept_timer);
+ timer_free(hci->lm.inquiry_done);
+ timer_free(hci->lm.inquiry_next);
+ timer_free(hci->conn_accept_timer);
g_free(hci);
}
diff --git a/hw/bt/l2cap.c b/hw/bt/l2cap.c
index 521587a..2301d6f 100644
--- a/hw/bt/l2cap.c
+++ b/hw/bt/l2cap.c
@@ -166,9 +166,9 @@
{
#if 0
if (ch->mode != L2CAP_MODE_BASIC && ch->rexmit)
- qemu_mod_timer(ch->retransmission_timer);
+ timer_mod(ch->retransmission_timer);
else
- qemu_del_timer(ch->retransmission_timer);
+ timer_del(ch->retransmission_timer);
#endif
}
@@ -176,9 +176,9 @@
{
#if 0
if (ch->mode != L2CAP_MODE_BASIC && !ch->rexmit)
- qemu_mod_timer(ch->monitor_timer);
+ timer_mod(ch->monitor_timer);
else
- qemu_del_timer(ch->monitor_timer);
+ timer_del(ch->monitor_timer);
#endif
}
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 4d457f8..f8ccbdd 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -106,8 +106,12 @@
#define R_MAX (R_TTRIG + 1)
+#define TYPE_CADENCE_UART "cadence_uart"
+#define CADENCE_UART(obj) OBJECT_CHECK(UartState, (obj), TYPE_CADENCE_UART)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t r[R_MAX];
uint8_t r_fifo[RX_FIFO_SIZE];
@@ -137,9 +141,9 @@
static void uart_tx_redo(UartState *s)
{
- uint64_t new_tx_time = qemu_get_clock_ns(vm_clock);
+ uint64_t new_tx_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- qemu_mod_timer(s->tx_time_handle, new_tx_time + s->char_tx_time);
+ timer_mod(s->tx_time_handle, new_tx_time + s->char_tx_time);
s->r[R_SR] |= UART_SR_INTR_TEMPTY;
@@ -261,7 +265,7 @@
static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
{
UartState *s = (UartState *)opaque;
- uint64_t new_rx_time = qemu_get_clock_ns(vm_clock);
+ uint64_t new_rx_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
int i;
if ((s->r[R_CR] & UART_CR_RX_DIS) || !(s->r[R_CR] & UART_CR_RX_EN)) {
@@ -287,7 +291,7 @@
s->r[R_SR] |= UART_SR_INTR_RTRIG;
}
}
- qemu_mod_timer(s->fifo_trigger_handle, new_rx_time +
+ timer_mod(s->fifo_trigger_handle, new_rx_time +
(s->char_tx_time * 4));
}
uart_update_status(s);
@@ -442,16 +446,16 @@
static int cadence_uart_init(SysBusDevice *dev)
{
- UartState *s = FROM_SYSBUS(UartState, dev);
+ UartState *s = CADENCE_UART(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &uart_ops, s, "uart", 0x1000);
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
- s->fifo_trigger_handle = qemu_new_timer_ns(vm_clock,
+ s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
(QEMUTimerCB *)fifo_trigger_update, s);
- s->tx_time_handle = qemu_new_timer_ns(vm_clock,
+ s->tx_time_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
(QEMUTimerCB *)uart_tx_write, s);
s->char_tx_time = (get_ticks_per_sec() / 9600) * 10;
@@ -504,7 +508,7 @@
}
static const TypeInfo cadence_uart_info = {
- .name = "cadence_uart",
+ .name = TYPE_CADENCE_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(UartState),
.class_init = cadence_uart_class_init,
diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c
index 03db12f..02d0d57 100644
--- a/hw/char/debugcon.c
+++ b/hw/char/debugcon.c
@@ -122,6 +122,7 @@
dc->realize = debugcon_isa_realizefn;
dc->props = debugcon_isa_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo debugcon_isa_info = {
diff --git a/hw/char/escc.c b/hw/char/escc.c
index 4c42198..6397f6f 100644
--- a/hw/char/escc.c
+++ b/hw/char/escc.c
@@ -96,8 +96,11 @@
uint8_t rx, tx;
} ChannelState;
+#define ESCC(obj) OBJECT_CHECK(ESCCState, (obj), TYPE_ESCC)
+
typedef struct ESCCState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
struct ChannelState chn[2];
uint32_t it_shift;
MemoryRegion mmio;
@@ -309,7 +312,7 @@
static void escc_reset(DeviceState *d)
{
- ESCCState *s = container_of(d, ESCCState, busdev.qdev);
+ ESCCState *s = ESCC(d);
escc_reset_chn(&s->chn[0]);
escc_reset_chn(&s->chn[1]);
@@ -534,7 +537,7 @@
escc_reset_chn(&serial->chn[1]);
return;
case MINTR_RST_ALL:
- escc_reset(&serial->busdev.qdev);
+ escc_reset(DEVICE(serial));
return;
}
break;
@@ -691,7 +694,7 @@
SysBusDevice *s;
ESCCState *d;
- dev = qdev_create(NULL, "escc");
+ dev = qdev_create(NULL, TYPE_ESCC);
qdev_prop_set_uint32(dev, "disabled", 0);
qdev_prop_set_uint32(dev, "frequency", clock);
qdev_prop_set_uint32(dev, "it_shift", it_shift);
@@ -707,7 +710,7 @@
sysbus_mmio_map(s, 0, base);
}
- d = FROM_SYSBUS(ESCCState, s);
+ d = ESCC(s);
return &d->mmio;
}
@@ -852,7 +855,7 @@
DeviceState *dev;
SysBusDevice *s;
- dev = qdev_create(NULL, "escc");
+ dev = qdev_create(NULL, TYPE_ESCC);
qdev_prop_set_uint32(dev, "disabled", disabled);
qdev_prop_set_uint32(dev, "frequency", clock);
qdev_prop_set_uint32(dev, "it_shift", it_shift);
@@ -869,7 +872,7 @@
static int escc_init1(SysBusDevice *dev)
{
- ESCCState *s = FROM_SYSBUS(ESCCState, dev);
+ ESCCState *s = ESCC(dev);
unsigned int i;
s->chn[0].disabled = s->disabled;
@@ -924,7 +927,7 @@
}
static const TypeInfo escc_info = {
- .name = "escc",
+ .name = TYPE_ESCC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ESCCState),
.class_init = escc_class_init,
diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c
index d19af00..460094e 100644
--- a/hw/char/etraxfs_ser.c
+++ b/hw/char/etraxfs_ser.c
@@ -44,9 +44,13 @@
#define STAT_TR_IDLE 22
#define STAT_TR_RDY 24
-struct etrax_serial
-{
- SysBusDevice busdev;
+#define TYPE_ETRAX_FS_SERIAL "etraxfs,serial"
+#define ETRAX_SERIAL(obj) \
+ OBJECT_CHECK(ETRAXSerial, (obj), TYPE_ETRAX_FS_SERIAL)
+
+typedef struct ETRAXSerial {
+ SysBusDevice parent_obj;
+
MemoryRegion mmio;
CharDriverState *chr;
qemu_irq irq;
@@ -59,9 +63,9 @@
/* Control registers. */
uint32_t regs[R_MAX];
-};
+} ETRAXSerial;
-static void ser_update_irq(struct etrax_serial *s)
+static void ser_update_irq(ETRAXSerial *s)
{
if (s->rx_fifo_len) {
@@ -77,7 +81,7 @@
static uint64_t
ser_read(void *opaque, hwaddr addr, unsigned int size)
{
- struct etrax_serial *s = opaque;
+ ETRAXSerial *s = opaque;
uint32_t r = 0;
addr >>= 2;
@@ -112,7 +116,7 @@
ser_write(void *opaque, hwaddr addr,
uint64_t val64, unsigned int size)
{
- struct etrax_serial *s = opaque;
+ ETRAXSerial *s = opaque;
uint32_t value = val64;
unsigned char ch = val64;
@@ -156,7 +160,7 @@
static void serial_receive(void *opaque, const uint8_t *buf, int size)
{
- struct etrax_serial *s = opaque;
+ ETRAXSerial *s = opaque;
int i;
/* Got a byte. */
@@ -177,7 +181,7 @@
static int serial_can_receive(void *opaque)
{
- struct etrax_serial *s = opaque;
+ ETRAXSerial *s = opaque;
int r;
/* Is the receiver enabled? */
@@ -196,7 +200,7 @@
static void etraxfs_ser_reset(DeviceState *d)
{
- struct etrax_serial *s = container_of(d, typeof(*s), busdev.qdev);
+ ETRAXSerial *s = ETRAX_SERIAL(d);
/* transmitter begins ready and idle. */
s->regs[RS_STAT_DIN] |= (1 << STAT_TR_RDY);
@@ -208,7 +212,7 @@
static int etraxfs_ser_init(SysBusDevice *dev)
{
- struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
+ ETRAXSerial *s = ETRAX_SERIAL(dev);
sysbus_init_irq(dev, &s->irq);
memory_region_init_io(&s->mmio, OBJECT(s), &ser_ops, s,
@@ -216,10 +220,11 @@
sysbus_init_mmio(dev, &s->mmio);
s->chr = qemu_char_get_next_serial();
- if (s->chr)
+ if (s->chr) {
qemu_chr_add_handlers(s->chr,
- serial_can_receive, serial_receive,
- serial_event, s);
+ serial_can_receive, serial_receive,
+ serial_event, s);
+ }
return 0;
}
@@ -233,9 +238,9 @@
}
static const TypeInfo etraxfs_ser_info = {
- .name = "etraxfs,serial",
+ .name = TYPE_ETRAX_FS_SERIAL,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(struct etrax_serial),
+ .instance_size = sizeof(ETRAXSerial),
.class_init = etraxfs_ser_class_init,
};
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c
index 855ce7a..eef23a0 100644
--- a/hw/char/exynos4210_uart.c
+++ b/hw/char/exynos4210_uart.c
@@ -166,8 +166,13 @@
uint32_t size;
} Exynos4210UartFIFO;
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_EXYNOS4210_UART "exynos4210.uart"
+#define EXYNOS4210_UART(obj) \
+ OBJECT_CHECK(Exynos4210UartState, (obj), TYPE_EXYNOS4210_UART)
+
+typedef struct Exynos4210UartState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t reg[EXYNOS4210_UART_REGS_MEM_SIZE / sizeof(uint32_t)];
@@ -538,8 +543,7 @@
static void exynos4210_uart_reset(DeviceState *dev)
{
- Exynos4210UartState *s =
- container_of(dev, Exynos4210UartState, busdev.qdev);
+ Exynos4210UartState *s = EXYNOS4210_UART(dev);
int regs_number = sizeof(exynos4210_uart_regs)/sizeof(Exynos4210UartReg);
int i;
@@ -582,10 +586,10 @@
};
DeviceState *exynos4210_uart_create(hwaddr addr,
- int fifo_size,
- int channel,
- CharDriverState *chr,
- qemu_irq irq)
+ int fifo_size,
+ int channel,
+ CharDriverState *chr,
+ qemu_irq irq)
{
DeviceState *dev;
SysBusDevice *bus;
@@ -593,7 +597,7 @@
const char chr_name[] = "serial";
char label[ARRAY_SIZE(chr_name) + 1];
- dev = qdev_create(NULL, "exynos4210.uart");
+ dev = qdev_create(NULL, TYPE_EXYNOS4210_UART);
if (!chr) {
if (channel >= MAX_SERIAL_PORTS) {
@@ -627,7 +631,7 @@
static int exynos4210_uart_init(SysBusDevice *dev)
{
- Exynos4210UartState *s = FROM_SYSBUS(Exynos4210UartState, dev);
+ Exynos4210UartState *s = EXYNOS4210_UART(dev);
/* memory mapping */
memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_uart_ops, s,
@@ -662,7 +666,7 @@
}
static const TypeInfo exynos4210_uart_info = {
- .name = "exynos4210.uart",
+ .name = TYPE_EXYNOS4210_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210UartState),
.class_init = exynos4210_uart_class_init,
diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c
index 82e1b95..35ef661 100644
--- a/hw/char/grlib_apbuart.c
+++ b/hw/char/grlib_apbuart.c
@@ -67,8 +67,13 @@
#define FIFO_LENGTH 1024
+#define TYPE_GRLIB_APB_UART "grlib,apbuart"
+#define GRLIB_APB_UART(obj) \
+ OBJECT_CHECK(UART, (obj), TYPE_GRLIB_APB_UART)
+
typedef struct UART {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq irq;
@@ -232,7 +237,7 @@
static int grlib_apbuart_init(SysBusDevice *dev)
{
- UART *uart = FROM_SYSBUS(typeof(*uart), dev);
+ UART *uart = GRLIB_APB_UART(dev);
qemu_chr_add_handlers(uart->chr,
grlib_apbuart_can_receive,
@@ -252,7 +257,7 @@
static void grlib_apbuart_reset(DeviceState *d)
{
- UART *uart = container_of(d, UART, busdev.qdev);
+ UART *uart = GRLIB_APB_UART(d);
/* Transmitter FIFO and shift registers are always empty in QEMU */
uart->status = UART_TRANSMIT_FIFO_EMPTY | UART_TRANSMIT_SHIFT_EMPTY;
@@ -279,7 +284,7 @@
}
static const TypeInfo grlib_apbuart_info = {
- .name = "grlib,apbuart",
+ .name = TYPE_GRLIB_APB_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(UART),
.class_init = grlib_apbuart_class_init,
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index 69b9ed2..7f16835 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -43,8 +43,12 @@
# define IPRINTF(fmt, args...) do {} while (0)
#endif
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_IMX_SERIAL "imx-serial"
+#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL)
+
+typedef struct IMXSerialState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
int32_t readbuff;
@@ -169,7 +173,7 @@
static void imx_serial_reset_at_boot(DeviceState *dev)
{
- IMXSerialState *s = container_of(dev, IMXSerialState, busdev.qdev);
+ IMXSerialState *s = IMX_SERIAL(dev);
imx_serial_reset(s);
@@ -383,7 +387,7 @@
static int imx_serial_init(SysBusDevice *dev)
{
- IMXSerialState *s = FROM_SYSBUS(IMXSerialState, dev);
+ IMXSerialState *s = IMX_SERIAL(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &imx_serial_ops, s,
@@ -410,7 +414,7 @@
const char chr_name[] = "serial";
char label[ARRAY_SIZE(chr_name) + 1];
- dev = qdev_create(NULL, "imx-serial");
+ dev = qdev_create(NULL, TYPE_IMX_SERIAL);
if (uart >= MAX_SERIAL_PORTS) {
hw_error("Cannot assign uart %d: QEMU supports only %d ports\n",
@@ -449,12 +453,13 @@
k->init = imx_serial_init;
dc->vmsd = &vmstate_imx_serial;
dc->reset = imx_serial_reset_at_boot;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->desc = "i.MX series UART";
dc->props = imx32_serial_properties;
}
static const TypeInfo imx_serial_info = {
- .name = "imx-serial",
+ .name = TYPE_IMX_SERIAL,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IMXSerialState),
.class_init = imx_serial_class_init,
diff --git a/hw/char/ipack.c b/hw/char/ipack.c
index e15540d..f890471 100644
--- a/hw/char/ipack.c
+++ b/hw/char/ipack.c
@@ -74,6 +74,7 @@
static void ipack_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
+ set_bit(DEVICE_CATEGORY_INPUT, k->categories);
k->bus_type = TYPE_IPACK_BUS;
k->init = ipack_device_dev_init;
k->exit = ipack_device_dev_exit;
diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c
index c9698a6..88e2cca 100644
--- a/hw/char/ipoctal232.c
+++ b/hw/char/ipoctal232.c
@@ -585,6 +585,7 @@
ic->mem_read8 = mem_read8;
ic->mem_write8 = mem_write8;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->desc = "GE IP-Octal 232 8-channel RS-232 IndustryPack";
dc->props = ipoctal_properties;
dc->vmsd = &vmstate_ipoctal;
diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c
index 839f3eb..252fe46 100644
--- a/hw/char/lm32_juart.c
+++ b/hw/char/lm32_juart.c
@@ -22,7 +22,7 @@
#include "trace.h"
#include "sysemu/char.h"
-#include "hw/lm32/lm32_juart.h"
+#include "hw/char/lm32_juart.h"
enum {
LM32_JUART_MIN_SAVE_VERSION = 0,
@@ -38,8 +38,11 @@
JRX_FULL = (1<<8),
};
+#define LM32_JUART(obj) OBJECT_CHECK(LM32JuartState, (obj), TYPE_LM32_JUART)
+
struct LM32JuartState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
CharDriverState *chr;
uint32_t jtx;
@@ -49,7 +52,7 @@
uint32_t lm32_juart_get_jtx(DeviceState *d)
{
- LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+ LM32JuartState *s = LM32_JUART(d);
trace_lm32_juart_get_jtx(s->jtx);
return s->jtx;
@@ -57,7 +60,7 @@
uint32_t lm32_juart_get_jrx(DeviceState *d)
{
- LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+ LM32JuartState *s = LM32_JUART(d);
trace_lm32_juart_get_jrx(s->jrx);
return s->jrx;
@@ -65,7 +68,7 @@
void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx)
{
- LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+ LM32JuartState *s = LM32_JUART(d);
unsigned char ch = jtx & 0xff;
trace_lm32_juart_set_jtx(s->jtx);
@@ -78,7 +81,7 @@
void lm32_juart_set_jrx(DeviceState *d, uint32_t jtx)
{
- LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+ LM32JuartState *s = LM32_JUART(d);
trace_lm32_juart_set_jrx(s->jrx);
s->jrx &= ~JRX_FULL;
@@ -104,7 +107,7 @@
static void juart_reset(DeviceState *d)
{
- LM32JuartState *s = container_of(d, LM32JuartState, busdev.qdev);
+ LM32JuartState *s = LM32_JUART(d);
s->jtx = 0;
s->jrx = 0;
@@ -112,7 +115,7 @@
static int lm32_juart_init(SysBusDevice *dev)
{
- LM32JuartState *s = FROM_SYSBUS(typeof(*s), dev);
+ LM32JuartState *s = LM32_JUART(dev);
s->chr = qemu_char_get_next_serial();
if (s->chr) {
@@ -145,7 +148,7 @@
}
static const TypeInfo lm32_juart_info = {
- .name = "lm32-juart",
+ .name = TYPE_LM32_JUART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LM32JuartState),
.class_init = lm32_juart_class_init,
diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c
index 37b38ba..85d7265 100644
--- a/hw/char/lm32_uart.c
+++ b/hw/char/lm32_uart.c
@@ -89,8 +89,12 @@
MSR_DCD = (1<<7),
};
+#define TYPE_LM32_UART "lm32-uart"
+#define LM32_UART(obj) OBJECT_CHECK(LM32UartState, (obj), TYPE_LM32_UART)
+
struct LM32UartState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
CharDriverState *chr;
qemu_irq irq;
@@ -233,7 +237,7 @@
static void uart_reset(DeviceState *d)
{
- LM32UartState *s = container_of(d, LM32UartState, busdev.qdev);
+ LM32UartState *s = LM32_UART(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -246,7 +250,7 @@
static int lm32_uart_init(SysBusDevice *dev)
{
- LM32UartState *s = FROM_SYSBUS(typeof(*s), dev);
+ LM32UartState *s = LM32_UART(dev);
sysbus_init_irq(dev, &s->irq);
@@ -284,7 +288,7 @@
}
static const TypeInfo lm32_uart_info = {
- .name = "lm32-uart",
+ .name = TYPE_LM32_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LM32UartState),
.class_init = lm32_uart_class_init,
diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c
index 46deab2..2e4b5c5 100644
--- a/hw/char/milkymist-uart.c
+++ b/hw/char/milkymist-uart.c
@@ -52,8 +52,13 @@
DBG_BREAK_EN = (1<<0),
};
+#define TYPE_MILKYMIST_UART "milkymist-uart"
+#define MILKYMIST_UART(obj) \
+ OBJECT_CHECK(MilkymistUartState, (obj), TYPE_MILKYMIST_UART)
+
struct MilkymistUartState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion regs_region;
CharDriverState *chr;
qemu_irq irq;
@@ -179,7 +184,7 @@
static void milkymist_uart_reset(DeviceState *d)
{
- MilkymistUartState *s = container_of(d, MilkymistUartState, busdev.qdev);
+ MilkymistUartState *s = MILKYMIST_UART(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -192,12 +197,12 @@
static int milkymist_uart_init(SysBusDevice *dev)
{
- MilkymistUartState *s = FROM_SYSBUS(typeof(*s), dev);
+ MilkymistUartState *s = MILKYMIST_UART(dev);
sysbus_init_irq(dev, &s->irq);
memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s,
- "milkymist-uart", R_MAX * 4);
+ "milkymist-uart", R_MAX * 4);
sysbus_init_mmio(dev, &s->regs_region);
s->chr = qemu_char_get_next_serial();
@@ -230,7 +235,7 @@
}
static const TypeInfo milkymist_uart_info = {
- .name = "milkymist-uart",
+ .name = TYPE_MILKYMIST_UART,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistUartState),
.class_init = milkymist_uart_class_init,
diff --git a/hw/char/parallel.c b/hw/char/parallel.c
index ad96ea5..7a3b264 100644
--- a/hw/char/parallel.c
+++ b/hw/char/parallel.c
@@ -607,6 +607,7 @@
dc->realize = parallel_isa_realizefn;
dc->props = parallel_isa_properties;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo parallel_isa_info = {
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
index ebec64f..a8ae6f4 100644
--- a/hw/char/pl011.c
+++ b/hw/char/pl011.c
@@ -10,8 +10,12 @@
#include "hw/sysbus.h"
#include "sysemu/char.h"
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PL011 "pl011"
+#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
+
+typedef struct PL011State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t readbuff;
uint32_t flags;
@@ -31,7 +35,7 @@
CharDriverState *chr;
qemu_irq irq;
const unsigned char *id;
-} pl011_state;
+} PL011State;
#define PL011_INT_TX 0x20
#define PL011_INT_RX 0x10
@@ -46,7 +50,7 @@
static const unsigned char pl011_id_luminary[8] =
{ 0x11, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
-static void pl011_update(pl011_state *s)
+static void pl011_update(PL011State *s)
{
uint32_t flags;
@@ -57,7 +61,7 @@
static uint64_t pl011_read(void *opaque, hwaddr offset,
unsigned size)
{
- pl011_state *s = (pl011_state *)opaque;
+ PL011State *s = (PL011State *)opaque;
uint32_t c;
if (offset >= 0xfe0 && offset < 0x1000) {
@@ -113,7 +117,7 @@
}
}
-static void pl011_set_read_trigger(pl011_state *s)
+static void pl011_set_read_trigger(PL011State *s)
{
#if 0
/* The docs say the RX interrupt is triggered when the FIFO exceeds
@@ -130,7 +134,7 @@
static void pl011_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
- pl011_state *s = (pl011_state *)opaque;
+ PL011State *s = (PL011State *)opaque;
unsigned char ch;
switch (offset >> 2) {
@@ -191,7 +195,7 @@
static int pl011_can_receive(void *opaque)
{
- pl011_state *s = (pl011_state *)opaque;
+ PL011State *s = (PL011State *)opaque;
if (s->lcr & 0x10)
return s->read_count < 16;
@@ -201,7 +205,7 @@
static void pl011_put_fifo(void *opaque, uint32_t value)
{
- pl011_state *s = (pl011_state *)opaque;
+ PL011State *s = (PL011State *)opaque;
int slot;
slot = s->read_pos + s->read_count;
@@ -242,83 +246,81 @@
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(readbuff, pl011_state),
- VMSTATE_UINT32(flags, pl011_state),
- VMSTATE_UINT32(lcr, pl011_state),
- VMSTATE_UINT32(cr, pl011_state),
- VMSTATE_UINT32(dmacr, pl011_state),
- VMSTATE_UINT32(int_enabled, pl011_state),
- VMSTATE_UINT32(int_level, pl011_state),
- VMSTATE_UINT32_ARRAY(read_fifo, pl011_state, 16),
- VMSTATE_UINT32(ilpr, pl011_state),
- VMSTATE_UINT32(ibrd, pl011_state),
- VMSTATE_UINT32(fbrd, pl011_state),
- VMSTATE_UINT32(ifl, pl011_state),
- VMSTATE_INT32(read_pos, pl011_state),
- VMSTATE_INT32(read_count, pl011_state),
- VMSTATE_INT32(read_trigger, pl011_state),
+ VMSTATE_UINT32(readbuff, PL011State),
+ VMSTATE_UINT32(flags, PL011State),
+ VMSTATE_UINT32(lcr, PL011State),
+ VMSTATE_UINT32(cr, PL011State),
+ VMSTATE_UINT32(dmacr, PL011State),
+ VMSTATE_UINT32(int_enabled, PL011State),
+ VMSTATE_UINT32(int_level, PL011State),
+ VMSTATE_UINT32_ARRAY(read_fifo, PL011State, 16),
+ VMSTATE_UINT32(ilpr, PL011State),
+ VMSTATE_UINT32(ibrd, PL011State),
+ VMSTATE_UINT32(fbrd, PL011State),
+ VMSTATE_UINT32(ifl, PL011State),
+ VMSTATE_INT32(read_pos, PL011State),
+ VMSTATE_INT32(read_count, PL011State),
+ VMSTATE_INT32(read_trigger, PL011State),
VMSTATE_END_OF_LIST()
}
};
-static int pl011_init(SysBusDevice *dev, const unsigned char *id)
+static void pl011_init(Object *obj)
{
- pl011_state *s = FROM_SYSBUS(pl011_state, dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ PL011State *s = PL011(obj);
memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
- s->id = id;
- s->chr = qemu_char_get_next_serial();
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
s->read_trigger = 1;
s->ifl = 0x12;
s->cr = 0x300;
s->flags = 0x90;
+
+ s->id = pl011_id_arm;
+}
+
+static void pl011_realize(DeviceState *dev, Error **errp)
+{
+ PL011State *s = PL011(dev);
+
+ s->chr = qemu_char_get_next_serial();
+
if (s->chr) {
qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
pl011_event, s);
}
- vmstate_register(&dev->qdev, -1, &vmstate_pl011, s);
- return 0;
}
-static int pl011_arm_init(SysBusDevice *dev)
+static void pl011_class_init(ObjectClass *oc, void *data)
{
- return pl011_init(dev, pl011_id_arm);
-}
+ DeviceClass *dc = DEVICE_CLASS(oc);
-static int pl011_luminary_init(SysBusDevice *dev)
-{
- return pl011_init(dev, pl011_id_luminary);
-}
-
-static void pl011_arm_class_init(ObjectClass *klass, void *data)
-{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
- sdc->init = pl011_arm_init;
+ dc->realize = pl011_realize;
+ dc->vmsd = &vmstate_pl011;
}
static const TypeInfo pl011_arm_info = {
- .name = "pl011",
+ .name = TYPE_PL011,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl011_state),
- .class_init = pl011_arm_class_init,
+ .instance_size = sizeof(PL011State),
+ .instance_init = pl011_init,
+ .class_init = pl011_class_init,
};
-static void pl011_luminary_class_init(ObjectClass *klass, void *data)
+static void pl011_luminary_init(Object *obj)
{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ PL011State *s = PL011(obj);
- sdc->init = pl011_luminary_init;
+ s->id = pl011_id_luminary;
}
static const TypeInfo pl011_luminary_info = {
.name = "pl011_luminary",
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl011_state),
- .class_init = pl011_luminary_class_init,
+ .parent = TYPE_PL011,
+ .instance_init = pl011_luminary_init,
};
static void pl011_register_types(void)
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index bcc7893..eb3988c 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -184,8 +184,6 @@
static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf,
size_t len)
{
- ssize_t ret = 0;
- const uint8_t *iov_offset;
SCLPConsole *scon = DO_UPCAST(SCLPConsole, event, event);
if (!scon->chr) {
@@ -193,21 +191,7 @@
return len;
}
- iov_offset = buf;
- while (len > 0) {
- ret = qemu_chr_fe_write(scon->chr, buf, len);
- if (ret == 0) {
- /* a pty doesn't seem to be connected - no error */
- len = 0;
- } else if (ret == -EAGAIN || (ret > 0 && ret < len)) {
- len -= ret;
- iov_offset += ret;
- } else {
- len = 0;
- }
- }
-
- return ret;
+ return qemu_chr_fe_write_all(scon->chr, buf, len);
}
static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr)
diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c
index cea8212..5cb77b3 100644
--- a/hw/char/serial-isa.c
+++ b/hw/char/serial-isa.c
@@ -102,6 +102,7 @@
dc->realize = serial_isa_realizefn;
dc->vmsd = &vmstate_isa_serial;
dc->props = serial_isa_properties;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo serial_isa_info = {
diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c
index a17c702..aec6705 100644
--- a/hw/char/serial-pci.c
+++ b/hw/char/serial-pci.c
@@ -205,6 +205,7 @@
pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
dc->vmsd = &vmstate_pci_serial;
dc->props = serial_pci_properties;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static void multi_2x_serial_pci_class_initfn(ObjectClass *klass, void *data)
@@ -219,6 +220,7 @@
pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
dc->vmsd = &vmstate_pci_multi_serial;
dc->props = multi_2x_serial_pci_properties;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data)
@@ -233,6 +235,7 @@
pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL;
dc->vmsd = &vmstate_pci_multi_serial;
dc->props = multi_4x_serial_pci_properties;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo serial_pci_info = {
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 6025592..27dab7d 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -27,6 +27,7 @@
#include "sysemu/char.h"
#include "qemu/timer.h"
#include "exec/address-spaces.h"
+#include "qemu/error-report.h"
//#define DEBUG_SERIAL
@@ -188,7 +189,7 @@
uint8_t omsr;
int flags;
- qemu_del_timer(s->modem_status_poll);
+ timer_del(s->modem_status_poll);
if (qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP) {
s->poll_msl = -1;
@@ -215,7 +216,7 @@
We'll be lazy and poll only every 10ms, and only poll it at all if MSI interrupts are turned on */
if (s->poll_msl)
- qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 100);
+ timer_mod(s->modem_status_poll, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + get_ticks_per_sec() / 100);
}
static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
@@ -252,7 +253,7 @@
s->tsr_retry = 0;
}
- s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
+ s->last_xmit_ts = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (s->lsr & UART_LSR_THRE) {
s->lsr |= UART_LSR_TEMT;
@@ -306,7 +307,7 @@
s->poll_msl = 1;
serial_update_msl(s);
} else {
- qemu_del_timer(s->modem_status_poll);
+ timer_del(s->modem_status_poll);
s->poll_msl = 0;
}
}
@@ -329,7 +330,7 @@
/* FIFO clear */
if (val & UART_FCR_RFR) {
- qemu_del_timer(s->fifo_timeout_timer);
+ timer_del(s->fifo_timeout_timer);
s->timeout_ipending=0;
fifo8_reset(&s->recv_fifo);
}
@@ -397,7 +398,7 @@
qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
/* Update the modem status after a one-character-send wait-time, since there may be a response
from the device/computer at the other end of the serial line */
- qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + s->char_transmit_time);
+ timer_mod(s->modem_status_poll, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time);
}
}
break;
@@ -429,7 +430,7 @@
if (s->recv_fifo.num == 0) {
s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
} else {
- qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
+ timer_mod(s->fifo_timeout_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time * 4);
}
s->timeout_ipending = 0;
} else {
@@ -556,7 +557,7 @@
}
s->lsr |= UART_LSR_DR;
/* call the timeout receive callback in 4 char transmit time */
- qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
+ timer_mod(s->fifo_timeout_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time * 4);
} else {
if (s->lsr & UART_LSR_DR)
s->lsr |= UART_LSR_OE;
@@ -635,7 +636,7 @@
fifo8_reset(&s->recv_fifo);
fifo8_reset(&s->xmit_fifo);
- s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
+ s->last_xmit_ts = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->thr_ipending = 0;
s->last_break_enable = 0;
@@ -649,9 +650,9 @@
return;
}
- s->modem_status_poll = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) serial_update_msl, s);
+ s->modem_status_poll = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) serial_update_msl, s);
- s->fifo_timeout_timer = qemu_new_timer_ns(vm_clock, (QEMUTimerCB *) fifo_timeout_int, s);
+ s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) fifo_timeout_int, s);
qemu_register_reset(serial_reset, s);
qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
@@ -696,7 +697,7 @@
s->chr = chr;
serial_realize_core(s, &err);
if (err != NULL) {
- fprintf(stderr, "%s\n", error_get_pretty(err));
+ error_report("%s", error_get_pretty(err));
error_free(err);
exit(1);
}
@@ -760,7 +761,7 @@
serial_realize_core(s, &err);
if (err != NULL) {
- fprintf(stderr, "%s\n", error_get_pretty(err));
+ error_report("%s", error_get_pretty(err));
error_free(err);
exit(1);
}
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c
index 2993848..a799721 100644
--- a/hw/char/spapr_vty.c
+++ b/hw/char/spapr_vty.c
@@ -142,6 +142,21 @@
DEFINE_PROP_END_OF_LIST(),
};
+static const VMStateDescription vmstate_spapr_vty = {
+ .name = "spapr_vty",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_SPAPR_VIO(sdev, VIOsPAPRVTYDevice),
+
+ VMSTATE_UINT32(in, VIOsPAPRVTYDevice),
+ VMSTATE_UINT32(out, VIOsPAPRVTYDevice),
+ VMSTATE_BUFFER(buf, VIOsPAPRVTYDevice),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static void spapr_vty_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -152,6 +167,7 @@
k->dt_type = "serial";
k->dt_compatible = "hvterm1";
dc->props = spapr_vty_properties;
+ dc->vmsd = &vmstate_spapr_vty;
}
static const TypeInfo spapr_vty_info = {
diff --git a/hw/char/tpci200.c b/hw/char/tpci200.c
index a199e57..d9e17b2 100644
--- a/hw/char/tpci200.c
+++ b/hw/char/tpci200.c
@@ -652,6 +652,7 @@
k->class_id = PCI_CLASS_BRIDGE_OTHER;
k->subsystem_vendor_id = PCI_VENDOR_ID_TEWS;
k->subsystem_id = 0x300A;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->desc = "TEWS TPCI200 IndustryPack carrier";
dc->vmsd = &vmstate_tpci200;
}
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index 6759e51..2e00ad2 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -185,6 +185,7 @@
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_CLASS(klass);
k->init = virtconsole_initfn;
+ k->exit = virtconsole_exitfn;
k->have_data = flush_buf;
k->set_guest_connected = set_guest_connected;
dc->props = virtserialport_properties;
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index cc3d1dd..f23f555 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -603,7 +603,7 @@
}
}
g_free(s->post_load->connected);
- qemu_free_timer(s->post_load->timer);
+ timer_free(s->post_load->timer);
g_free(s->post_load);
s->post_load = NULL;
}
@@ -618,7 +618,7 @@
s->post_load->connected =
g_malloc0(sizeof(*s->post_load->connected) * nr_active_ports);
- s->post_load->timer = qemu_new_timer_ns(vm_clock,
+ s->post_load->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
virtio_serial_post_load_timer_cb,
s);
@@ -660,7 +660,7 @@
}
}
}
- qemu_mod_timer(s->post_load->timer, 1);
+ timer_mod(s->post_load->timer, 1);
return 0;
}
@@ -971,6 +971,7 @@
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = virtser_port_qdev_init;
+ set_bit(DEVICE_CATEGORY_INPUT, k->categories);
k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
k->exit = virtser_port_qdev_exit;
k->unplug = qdev_simple_unplug_cb;
@@ -998,8 +999,8 @@
g_free(vser->ports_map);
if (vser->post_load) {
g_free(vser->post_load->connected);
- qemu_del_timer(vser->post_load->timer);
- qemu_free_timer(vser->post_load->timer);
+ timer_del(vser->post_load->timer);
+ timer_free(vser->post_load->timer);
g_free(vser->post_load);
}
virtio_cleanup(vdev);
@@ -1017,6 +1018,7 @@
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->exit = virtio_serial_device_exit;
dc->props = virtio_serial_properties;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
vdc->init = virtio_serial_device_init;
vdc->get_features = get_features;
vdc->get_config = get_config;
diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index feca497..b0d1d04 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -46,9 +46,13 @@
#define CONTROL_RST_RX 0x02
#define CONTROL_IE 0x10
-struct xlx_uartlite
-{
- SysBusDevice busdev;
+#define TYPE_XILINX_UARTLITE "xlnx.xps-uartlite"
+#define XILINX_UARTLITE(obj) \
+ OBJECT_CHECK(XilinxUARTLite, (obj), TYPE_XILINX_UARTLITE)
+
+typedef struct XilinxUARTLite {
+ SysBusDevice parent_obj;
+
MemoryRegion mmio;
CharDriverState *chr;
qemu_irq irq;
@@ -58,9 +62,9 @@
unsigned int rx_fifo_len;
uint32_t regs[R_MAX];
-};
+} XilinxUARTLite;
-static void uart_update_irq(struct xlx_uartlite *s)
+static void uart_update_irq(XilinxUARTLite *s)
{
unsigned int irq;
@@ -71,7 +75,7 @@
qemu_set_irq(s->irq, irq);
}
-static void uart_update_status(struct xlx_uartlite *s)
+static void uart_update_status(XilinxUARTLite *s)
{
uint32_t r;
@@ -86,7 +90,7 @@
static uint64_t
uart_read(void *opaque, hwaddr addr, unsigned int size)
{
- struct xlx_uartlite *s = opaque;
+ XilinxUARTLite *s = opaque;
uint32_t r = 0;
addr >>= 2;
switch (addr)
@@ -113,7 +117,7 @@
uart_write(void *opaque, hwaddr addr,
uint64_t val64, unsigned int size)
{
- struct xlx_uartlite *s = opaque;
+ XilinxUARTLite *s = opaque;
uint32_t value = val64;
unsigned char ch = value;
@@ -164,7 +168,7 @@
static void uart_rx(void *opaque, const uint8_t *buf, int size)
{
- struct xlx_uartlite *s = opaque;
+ XilinxUARTLite *s = opaque;
/* Got a byte. */
if (s->rx_fifo_len >= 8) {
@@ -182,7 +186,7 @@
static int uart_can_rx(void *opaque)
{
- struct xlx_uartlite *s = opaque;
+ XilinxUARTLite *s = opaque;
return s->rx_fifo_len < sizeof(s->rx_fifo);
}
@@ -194,7 +198,7 @@
static int xilinx_uartlite_init(SysBusDevice *dev)
{
- struct xlx_uartlite *s = FROM_SYSBUS(typeof (*s), dev);
+ XilinxUARTLite *s = XILINX_UARTLITE(dev);
sysbus_init_irq(dev, &s->irq);
@@ -217,9 +221,9 @@
}
static const TypeInfo xilinx_uartlite_info = {
- .name = "xlnx.xps-uartlite",
+ .name = TYPE_XILINX_UARTLITE,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof (struct xlx_uartlite),
+ .instance_size = sizeof(XilinxUARTLite),
.class_init = xilinx_uartlite_class_init,
};
diff --git a/hw/core/empty_slot.c b/hw/core/empty_slot.c
index e624991..612b109 100644
--- a/hw/core/empty_slot.c
+++ b/hw/core/empty_slot.c
@@ -22,8 +22,12 @@
#define DPRINTF(fmt, ...) do {} while (0)
#endif
+#define TYPE_EMPTY_SLOT "empty_slot"
+#define EMPTY_SLOT(obj) OBJECT_CHECK(EmptySlot, (obj), TYPE_EMPTY_SLOT)
+
typedef struct EmptySlot {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint64_t size;
} EmptySlot;
@@ -55,9 +59,9 @@
SysBusDevice *s;
EmptySlot *e;
- dev = qdev_create(NULL, "empty_slot");
+ dev = qdev_create(NULL, TYPE_EMPTY_SLOT);
s = SYS_BUS_DEVICE(dev);
- e = FROM_SYSBUS(EmptySlot, s);
+ e = EMPTY_SLOT(dev);
e->size = slot_size;
qdev_init_nofail(dev);
@@ -68,7 +72,7 @@
static int empty_slot_init1(SysBusDevice *dev)
{
- EmptySlot *s = FROM_SYSBUS(EmptySlot, dev);
+ EmptySlot *s = EMPTY_SLOT(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &empty_slot_ops, s,
"empty-slot", s->size);
@@ -84,7 +88,7 @@
}
static const TypeInfo empty_slot_info = {
- .name = "empty_slot",
+ .name = TYPE_EMPTY_SLOT,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(EmptySlot),
.class_init = empty_slot_class_init,
diff --git a/hw/core/loader.c b/hw/core/loader.c
index c3c28cf..7b3d3ee 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -54,6 +54,8 @@
#include <zlib.h>
+bool rom_file_in_ram = true;
+
static int roms_loaded;
/* return the size or -1 if error */
@@ -576,6 +578,7 @@
size_t datasize;
uint8_t *data;
+ MemoryRegion *mr;
int isrom;
char *fw_dir;
char *fw_file;
@@ -605,6 +608,21 @@
QTAILQ_INSERT_TAIL(&roms, rom, next);
}
+static void *rom_set_mr(Rom *rom, Object *owner, const char *name)
+{
+ void *data;
+
+ rom->mr = g_malloc(sizeof(*rom->mr));
+ memory_region_init_ram(rom->mr, owner, name, rom->datasize);
+ memory_region_set_readonly(rom->mr, true);
+ vmstate_register_ram_global(rom->mr);
+
+ data = memory_region_get_ram_ptr(rom->mr);
+ memcpy(data, rom->data, rom->datasize);
+
+ return data;
+}
+
int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex)
{
@@ -646,6 +664,7 @@
if (rom->fw_file && fw_cfg) {
const char *basename;
char fw_file_name[56];
+ void *data;
basename = strrchr(rom->fw_file, '/');
if (basename) {
@@ -655,8 +674,15 @@
}
snprintf(fw_file_name, sizeof(fw_file_name), "%s/%s", rom->fw_dir,
basename);
- fw_cfg_add_file(fw_cfg, fw_file_name, rom->data, rom->romsize);
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
+
+ if (rom_file_in_ram) {
+ data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
+ } else {
+ data = rom->data;
+ }
+
+ fw_cfg_add_file(fw_cfg, fw_file_name, data, rom->romsize);
} else {
snprintf(devpath, sizeof(devpath), "/rom@" TARGET_FMT_plx, addr);
}
@@ -731,7 +757,12 @@
if (rom->data == NULL) {
continue;
}
- cpu_physical_memory_write_rom(rom->addr, rom->data, rom->datasize);
+ if (rom->mr) {
+ void *host = memory_region_get_ram_ptr(rom->mr);
+ memcpy(host, rom->data, rom->datasize);
+ } else {
+ cpu_physical_memory_write_rom(rom->addr, rom->data, rom->datasize);
+ }
if (rom->isrom) {
/* rom needs to be written only once */
g_free(rom->data);
@@ -781,6 +812,9 @@
if (rom->fw_file) {
continue;
}
+ if (rom->mr) {
+ continue;
+ }
if (rom->addr > addr) {
continue;
}
@@ -808,15 +842,15 @@
if (rom->fw_file) {
continue;
}
+ if (rom->mr) {
+ continue;
+ }
if (rom->addr + rom->romsize < addr) {
continue;
}
if (rom->addr > end) {
break;
}
- if (!rom->data) {
- continue;
- }
d = dest + (rom->addr - addr);
s = rom->data;
@@ -826,7 +860,9 @@
l = dest - d;
}
- memcpy(d, s, l);
+ if (l > 0) {
+ memcpy(d, s, l);
+ }
if (rom->romsize > rom->datasize) {
/* If datasize is less than romsize, it means that we didn't
@@ -867,7 +903,13 @@
Rom *rom;
QTAILQ_FOREACH(rom, &roms, next) {
- if (!rom->fw_file) {
+ if (rom->mr) {
+ monitor_printf(mon, "%s"
+ " size=0x%06zx name=\"%s\"\n",
+ rom->mr->name,
+ rom->romsize,
+ rom->name);
+ } else if (!rom->fw_file) {
monitor_printf(mon, "addr=" TARGET_FMT_plx
" size=0x%06zx mem=%s name=\"%s\"\n",
rom->addr, rom->romsize,
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
index 4bc96c9..3036bde 100644
--- a/hw/core/ptimer.c
+++ b/hw/core/ptimer.c
@@ -48,7 +48,7 @@
if (s->period_frac) {
s->next_event += ((int64_t)s->period_frac * s->delta) >> 32;
}
- qemu_mod_timer(s->timer, s->next_event);
+ timer_mod(s->timer, s->next_event);
}
static void ptimer_tick(void *opaque)
@@ -69,7 +69,7 @@
uint64_t counter;
if (s->enabled) {
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
/* Figure out the current counter value. */
if (now - s->next_event > 0
|| s->period == 0) {
@@ -123,7 +123,7 @@
{
s->delta = count;
if (s->enabled) {
- s->next_event = qemu_get_clock_ns(vm_clock);
+ s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ptimer_reload(s);
}
}
@@ -138,7 +138,7 @@
return;
}
s->enabled = oneshot ? 2 : 1;
- s->next_event = qemu_get_clock_ns(vm_clock);
+ s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ptimer_reload(s);
}
@@ -150,7 +150,7 @@
return;
s->delta = ptimer_get_count(s);
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
s->enabled = 0;
}
@@ -160,7 +160,7 @@
s->period = period;
s->period_frac = 0;
if (s->enabled) {
- s->next_event = qemu_get_clock_ns(vm_clock);
+ s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ptimer_reload(s);
}
}
@@ -171,7 +171,7 @@
s->period = 1000000000ll / freq;
s->period_frac = (1000000000ll << 32) / freq;
if (s->enabled) {
- s->next_event = qemu_get_clock_ns(vm_clock);
+ s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ptimer_reload(s);
}
}
@@ -197,7 +197,7 @@
if (reload)
s->delta = limit;
if (s->enabled && reload) {
- s->next_event = qemu_get_clock_ns(vm_clock);
+ s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ptimer_reload(s);
}
}
@@ -226,6 +226,6 @@
s = (ptimer_state *)g_malloc0(sizeof(ptimer_state));
s->bh = bh;
- s->timer = qemu_new_timer_ns(vm_clock, ptimer_tick, s);
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ptimer_tick, s);
return s;
}
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 3a324fb..dc8ae69 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -74,13 +74,14 @@
}
}
-static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
+static int prop_print_bit(DeviceState *dev, Property *prop, char *dest,
+ size_t len)
{
uint32_t *p = qdev_get_prop_ptr(dev, prop);
return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
}
-static void get_bit(Object *obj, Visitor *v, void *opaque,
+static void prop_get_bit(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
@@ -91,7 +92,7 @@
visit_type_bool(v, &value, name, errp);
}
-static void set_bit(Object *obj, Visitor *v, void *opaque,
+static void prop_set_bit(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
DeviceState *dev = DEVICE(obj);
@@ -115,9 +116,9 @@
PropertyInfo qdev_prop_bit = {
.name = "boolean",
.legacy_name = "on/off",
- .print = print_bit,
- .get = get_bit,
- .set = set_bit,
+ .print = prop_print_bit,
+ .get = prop_get_bit,
+ .set = prop_set_bit,
};
/* --- bool --- */
@@ -1134,3 +1135,64 @@
class = object_class_get_parent(class);
} while (class);
}
+
+/* --- 64bit unsigned int 'size' type --- */
+
+static void get_size(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
+
+ visit_type_size(v, ptr, name, errp);
+}
+
+static void set_size(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
+ uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
+
+ visit_type_size(v, ptr, name, errp);
+}
+
+static int parse_size(DeviceState *dev, Property *prop, const char *str)
+{
+ uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
+ Error *errp = NULL;
+
+ if (str != NULL) {
+ parse_option_size(prop->name, str, ptr, &errp);
+ }
+ assert_no_error(errp);
+ return 0;
+}
+
+static int print_size(DeviceState *dev, Property *prop, char *dest, size_t len)
+{
+ static const char suffixes[] = { 'B', 'K', 'M', 'G', 'T' };
+ uint64_t div, val = *(uint64_t *)qdev_get_prop_ptr(dev, prop);
+ int i;
+
+ /* Compute floor(log2(val)). */
+ i = 64 - clz64(val);
+
+ /* Find the power of 1024 that we'll display as the units. */
+ i /= 10;
+ if (i >= ARRAY_SIZE(suffixes)) {
+ i = ARRAY_SIZE(suffixes) - 1;
+ }
+ div = 1ULL << (i * 10);
+
+ return snprintf(dest, len, "%0.03f%c", (double)val/div, suffixes[i]);
+}
+
+PropertyInfo qdev_prop_size = {
+ .name = "size",
+ .parse = parse_size,
+ .print = print_size,
+ .get = get_size,
+ .set = set_size,
+};
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 9190a7e..758de9f 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -752,7 +752,6 @@
}
class = object_class_get_parent(class);
} while (class != object_class_by_name(TYPE_DEVICE));
- qdev_prop_set_globals(dev, &err);
if (err != NULL) {
qerror_report_err(err);
error_free(err);
@@ -764,6 +763,15 @@
assert_no_error(err);
}
+static void device_post_init(Object *obj)
+{
+ DeviceState *dev = DEVICE(obj);
+ Error *err = NULL;
+
+ qdev_prop_set_globals(dev, &err);
+ assert_no_error(err);
+}
+
/* Unlink device from bus and free the structure. */
static void device_finalize(Object *obj)
{
@@ -853,6 +861,7 @@
.parent = TYPE_OBJECT,
.instance_size = sizeof(DeviceState),
.instance_init = device_initfn,
+ .instance_post_init = device_post_init,
.instance_finalize = device_finalize,
.class_base_init = device_class_base_init,
.class_init = device_class_init,
diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs
index 4461ece..df287c1 100644
--- a/hw/cpu/Makefile.objs
+++ b/hw/cpu/Makefile.objs
@@ -1,5 +1,5 @@
obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
-obj-$(CONFIG_ARM9MPCORE) += a9mpcore.o
-obj-$(CONFIG_ARM15MPCORE) += a15mpcore.o
+obj-$(CONFIG_A9MPCORE) += a9mpcore.o
+obj-$(CONFIG_A15MPCORE) += a15mpcore.o
obj-$(CONFIG_ICC_BUS) += icc_bus.o
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index c736257..af182da 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -23,8 +23,15 @@
/* A15MP private memory region. */
+#define TYPE_A15MPCORE_PRIV "a15mpcore_priv"
+#define A15MPCORE_PRIV(obj) \
+ OBJECT_CHECK(A15MPPrivState, (obj), TYPE_A15MPCORE_PRIV)
+
typedef struct A15MPPrivState {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
uint32_t num_cpu;
uint32_t num_irq;
MemoryRegion container;
@@ -39,9 +46,11 @@
static int a15mp_priv_init(SysBusDevice *dev)
{
- A15MPPrivState *s = FROM_SYSBUS(A15MPPrivState, dev);
+ A15MPPrivState *s = A15MPCORE_PRIV(dev);
SysBusDevice *busdev;
const char *gictype = "arm_gic";
+ int i;
+ CPUState *cpu;
if (kvm_irqchip_in_kernel()) {
gictype = "kvm-arm-gic";
@@ -58,7 +67,23 @@
sysbus_pass_irq(dev, busdev);
/* Pass through inbound GPIO lines to the GIC */
- qdev_init_gpio_in(&s->busdev.qdev, a15mp_priv_set_irq, s->num_irq - 32);
+ qdev_init_gpio_in(DEVICE(dev), a15mp_priv_set_irq, s->num_irq - 32);
+
+ /* Wire the outputs from each CPU's generic timer to the
+ * appropriate GIC PPI inputs
+ */
+ for (i = 0, cpu = first_cpu; i < s->num_cpu; i++, cpu = cpu->next_cpu) {
+ DeviceState *cpudev = DEVICE(cpu);
+ int ppibase = s->num_irq - 32 + i * 32;
+ /* physical timer; we wire it up to the non-secure timer's ID,
+ * since a real A15 always has TrustZone but QEMU doesn't.
+ */
+ qdev_connect_gpio_out(cpudev, 0,
+ qdev_get_gpio_in(s->gic, ppibase + 30));
+ /* virtual timer */
+ qdev_connect_gpio_out(cpudev, 1,
+ qdev_get_gpio_in(s->gic, ppibase + 27));
+ }
/* Memory map (addresses are offsets from PERIPHBASE):
* 0x0000-0x0fff -- reserved
@@ -101,7 +126,7 @@
}
static const TypeInfo a15mp_priv_info = {
- .name = "a15mpcore_priv",
+ .name = TYPE_A15MPCORE_PRIV,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(A15MPPrivState),
.class_init = a15mp_priv_class_init,
diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c
index 6c00a59..3e675e3 100644
--- a/hw/cpu/a9mpcore.c
+++ b/hw/cpu/a9mpcore.c
@@ -10,8 +10,15 @@
#include "hw/sysbus.h"
+#define TYPE_A9MPCORE_PRIV "a9mpcore_priv"
+#define A9MPCORE_PRIV(obj) \
+ OBJECT_CHECK(A9MPPrivState, (obj), TYPE_A9MPCORE_PRIV)
+
typedef struct A9MPPrivState {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
uint32_t num_cpu;
MemoryRegion container;
DeviceState *mptimer;
@@ -29,7 +36,7 @@
static int a9mp_priv_init(SysBusDevice *dev)
{
- A9MPPrivState *s = FROM_SYSBUS(A9MPPrivState, dev);
+ A9MPPrivState *s = A9MPCORE_PRIV(dev);
SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev;
int i;
@@ -43,7 +50,7 @@
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);
+ qdev_init_gpio_in(DEVICE(dev), a9mp_priv_set_irq, s->num_irq - 32);
s->scu = qdev_create(NULL, "a9-scu");
qdev_prop_set_uint32(s->scu, "num-cpu", s->num_cpu);
@@ -124,7 +131,7 @@
}
static const TypeInfo a9mp_priv_info = {
- .name = "a9mpcore_priv",
+ .name = TYPE_A9MPCORE_PRIV,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(A9MPPrivState),
.class_init = a9mp_priv_class_init,
diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c
index 8eeb53e..a786c62 100644
--- a/hw/cpu/arm11mpcore.c
+++ b/hw/cpu/arm11mpcore.c
@@ -12,8 +12,13 @@
/* MPCore private memory region. */
+#define TYPE_ARM11MPCORE_PRIV "arm11mpcore_priv"
+#define ARM11MPCORE_PRIV(obj) \
+ OBJECT_CHECK(ARM11MPCorePriveState, (obj), TYPE_ARM11MPCORE_PRIV)
+
typedef struct ARM11MPCorePriveState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
uint32_t scu_control;
int iomemtype;
uint32_t old_timer_status[8];
@@ -125,9 +130,10 @@
}
}
-static int mpcore_priv_init(SysBusDevice *dev)
+static int mpcore_priv_init(SysBusDevice *sbd)
{
- ARM11MPCorePriveState *s = FROM_SYSBUS(ARM11MPCorePriveState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ ARM11MPCorePriveState *s = ARM11MPCORE_PRIV(dev);
s->gic = qdev_create(NULL, "arm_gic");
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
@@ -137,10 +143,10 @@
qdev_init_nofail(s->gic);
/* Pass through outbound IRQ lines from the GIC */
- sysbus_pass_irq(dev, SYS_BUS_DEVICE(s->gic));
+ sysbus_pass_irq(sbd, SYS_BUS_DEVICE(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);
+ qdev_init_gpio_in(dev, mpcore_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);
@@ -151,15 +157,20 @@
qdev_init_nofail(s->wdtimer);
mpcore_priv_map_setup(s);
- sysbus_init_mmio(dev, &s->container);
+ sysbus_init_mmio(sbd, &s->container);
return 0;
}
+#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
+#define REALVIEW_MPCORE_RIRQ(obj) \
+ OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ)
+
/* Dummy PIC to route IRQ lines. The baseboard has 4 independent IRQ
controllers. The output of these, plus some of the raw input lines
are fed into a single SMP-aware interrupt controller on the CPU. */
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
SysBusDevice *priv;
qemu_irq cpuic[32];
qemu_irq rvic[4][64];
@@ -190,19 +201,20 @@
}
}
-static int realview_mpcore_init(SysBusDevice *dev)
+static int realview_mpcore_init(SysBusDevice *sbd)
{
- mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev);
DeviceState *gic;
DeviceState *priv;
int n;
int i;
- priv = qdev_create(NULL, "arm11mpcore_priv");
+ priv = qdev_create(NULL, TYPE_ARM11MPCORE_PRIV);
qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
qdev_init_nofail(priv);
s->priv = SYS_BUS_DEVICE(priv);
- sysbus_pass_irq(dev, s->priv);
+ sysbus_pass_irq(sbd, s->priv);
for (i = 0; i < 32; i++) {
s->cpuic[i] = qdev_get_gpio_in(priv, i);
}
@@ -214,8 +226,8 @@
s->rvic[n][i] = qdev_get_gpio_in(gic, i);
}
}
- qdev_init_gpio_in(&dev->qdev, mpcore_rirq_set_irq, 64);
- sysbus_init_mmio(dev, sysbus_mmio_get_region(s->priv, 0));
+ qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64);
+ sysbus_init_mmio(sbd, sysbus_mmio_get_region(s->priv, 0));
return 0;
}
@@ -234,7 +246,7 @@
}
static const TypeInfo mpcore_rirq_info = {
- .name = "realview_mpcore",
+ .name = TYPE_REALVIEW_MPCORE_RIRQ,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(mpcore_rirq_state),
.class_init = mpcore_rirq_class_init,
@@ -264,7 +276,7 @@
}
static const TypeInfo mpcore_priv_info = {
- .name = "arm11mpcore_priv",
+ .name = TYPE_ARM11MPCORE_PRIV,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ARM11MPCorePriveState),
.class_init = mpcore_priv_class_init,
diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c
index 8788144..8748cc5 100644
--- a/hw/cpu/icc_bus.c
+++ b/hw/cpu/icc_bus.c
@@ -101,11 +101,19 @@
s->icc_bus.apic_address_space = &s->apic_container;
}
+static void icc_bridge_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+}
+
static const TypeInfo icc_bridge_info = {
.name = TYPE_ICC_BRIDGE,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_init = icc_bridge_init,
.instance_size = sizeof(ICCBridgeState),
+ .class_init = icc_bridge_class_init,
};
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index a440575..dbd1f4a 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -2937,6 +2937,7 @@
dc->vmsd = &vmstate_cirrus_vga;
dc->realize = isa_cirrus_vga_realizefn;
dc->props = isa_cirrus_vga_properties;
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
}
static const TypeInfo isa_cirrus_vga_info = {
@@ -3002,6 +3003,7 @@
k->vendor_id = PCI_VENDOR_ID_CIRRUS;
k->device_id = CIRRUS_ID_CLGD5446;
k->class_id = PCI_CLASS_DISPLAY_VGA;
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
dc->desc = "Cirrus CLGD 54xx VGA";
dc->vmsd = &vmstate_pci_cirrus_vga;
dc->props = pci_vga_cirrus_properties;
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index eb168ea..65cca1d 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -292,8 +292,13 @@
hwaddr fb_len; /* Framebuffer length */
};
+#define TYPE_EXYNOS4210_FIMD "exynos4210.fimd"
+#define EXYNOS4210_FIMD(obj) \
+ OBJECT_CHECK(Exynos4210fimdState, (obj), TYPE_EXYNOS4210_FIMD)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
QemuConsole *console;
qemu_irq irq[3];
@@ -1108,6 +1113,7 @@
* VIDOSDA, VIDOSDB, VIDWADDx and SHADOWCON registers */
static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(s);
Exynos4210fimdWindow *w = &s->window[win];
hwaddr fb_start_addr, fb_mapped_len;
@@ -1131,8 +1137,8 @@
* does not support hot-unplug.
*/
memory_region_unref(w->mem_section.mr);
- w->mem_section = memory_region_find(sysbus_address_space(&s->busdev),
- fb_start_addr, w->fb_len);
+ w->mem_section = memory_region_find(sysbus_address_space(sbd),
+ fb_start_addr, w->fb_len);
assert(w->mem_section.mr);
assert(w->mem_section.offset_within_address_space == fb_start_addr);
DPRINT_TRACE("Window %u framebuffer changed: address=0x%08x, len=0x%x\n",
@@ -1328,7 +1334,7 @@
static void exynos4210_fimd_reset(DeviceState *d)
{
- Exynos4210fimdState *s = DO_UPCAST(Exynos4210fimdState, busdev.qdev, d);
+ Exynos4210fimdState *s = EXYNOS4210_FIMD(d);
unsigned w;
DPRINT_TRACE("Display controller reset\n");
@@ -1900,7 +1906,7 @@
static int exynos4210_fimd_init(SysBusDevice *dev)
{
- Exynos4210fimdState *s = FROM_SYSBUS(Exynos4210fimdState, dev);
+ Exynos4210fimdState *s = EXYNOS4210_FIMD(dev);
s->ifb = NULL;
@@ -1927,7 +1933,7 @@
}
static const TypeInfo exynos4210_fimd_info = {
- .name = "exynos4210.fimd",
+ .name = TYPE_EXYNOS4210_FIMD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210fimdState),
.class_init = exynos4210_fimd_class_init,
diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c
index 79a0a50..7082171 100644
--- a/hw/display/g364fb.c
+++ b/hw/display/g364fb.c
@@ -493,26 +493,33 @@
memory_region_set_coalescing(&s->mem_vram);
}
+#define TYPE_G364 "sysbus-g364"
+#define G364(obj) OBJECT_CHECK(G364SysBusState, (obj), TYPE_G364)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
G364State g364;
} G364SysBusState;
-static int g364fb_sysbus_init(SysBusDevice *dev)
+static int g364fb_sysbus_init(SysBusDevice *sbd)
{
- G364State *s = &FROM_SYSBUS(G364SysBusState, dev)->g364;
+ DeviceState *dev = DEVICE(sbd);
+ G364SysBusState *sbs = G364(dev);
+ G364State *s = &sbs->g364;
- g364fb_init(&dev->qdev, s);
- sysbus_init_irq(dev, &s->irq);
- sysbus_init_mmio(dev, &s->mem_ctrl);
- sysbus_init_mmio(dev, &s->mem_vram);
+ g364fb_init(dev, s);
+ sysbus_init_irq(sbd, &s->irq);
+ sysbus_init_mmio(sbd, &s->mem_ctrl);
+ sysbus_init_mmio(sbd, &s->mem_vram);
return 0;
}
static void g364fb_sysbus_reset(DeviceState *d)
{
- G364SysBusState *s = DO_UPCAST(G364SysBusState, busdev.qdev, d);
+ G364SysBusState *s = G364(d);
+
g364fb_reset(&s->g364);
}
@@ -528,6 +535,7 @@
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = g364fb_sysbus_init;
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
dc->desc = "G364 framebuffer";
dc->reset = g364fb_sysbus_reset;
dc->vmsd = &vmstate_g364fb;
@@ -535,7 +543,7 @@
}
static const TypeInfo g364fb_sysbus_info = {
- .name = "sysbus-g364",
+ .name = TYPE_G364,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(G364SysBusState),
.class_init = g364fb_sysbus_class_init,
diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c
index 7f82037..8407e6c 100644
--- a/hw/display/jazz_led.c
+++ b/hw/display/jazz_led.c
@@ -32,8 +32,12 @@
REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
} screen_state_t;
+#define TYPE_JAZZ_LED "jazz-led"
+#define JAZZ_LED(obj) OBJECT_CHECK(LedState, (obj), TYPE_JAZZ_LED)
+
typedef struct LedState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint8_t segments;
QemuConsole *con;
@@ -262,7 +266,7 @@
static int jazz_led_init(SysBusDevice *dev)
{
- LedState *s = FROM_SYSBUS(LedState, dev);
+ LedState *s = JAZZ_LED(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &led_ops, s, "led", 1);
sysbus_init_mmio(dev, &s->iomem);
@@ -274,7 +278,7 @@
static void jazz_led_reset(DeviceState *d)
{
- LedState *s = DO_UPCAST(LedState, busdev.qdev, d);
+ LedState *s = JAZZ_LED(d);
s->segments = 0;
s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
@@ -293,7 +297,7 @@
}
static const TypeInfo jazz_led_info = {
- .name = "jazz-led",
+ .name = TYPE_JAZZ_LED,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LedState),
.class_init = jazz_led_class_init,
diff --git a/hw/display/milkymist-tmu2.c b/hw/display/milkymist-tmu2.c
index efda082..b2a5fba 100644
--- a/hw/display/milkymist-tmu2.c
+++ b/hw/display/milkymist-tmu2.c
@@ -75,8 +75,13 @@
int y;
} QEMU_PACKED;
+#define TYPE_MILKYMIST_TMU2 "milkymist-tmu2"
+#define MILKYMIST_TMU2(obj) \
+ OBJECT_CHECK(MilkymistTMU2State, (obj), TYPE_MILKYMIST_TMU2)
+
struct MilkymistTMU2State {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion regs_region;
CharDriverState *chr;
qemu_irq irq;
@@ -429,7 +434,7 @@
static void milkymist_tmu2_reset(DeviceState *d)
{
- MilkymistTMU2State *s = container_of(d, MilkymistTMU2State, busdev.qdev);
+ MilkymistTMU2State *s = MILKYMIST_TMU2(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -439,7 +444,7 @@
static int milkymist_tmu2_init(SysBusDevice *dev)
{
- MilkymistTMU2State *s = FROM_SYSBUS(typeof(*s), dev);
+ MilkymistTMU2State *s = MILKYMIST_TMU2(dev);
if (tmu2_glx_init(s)) {
return 1;
@@ -476,7 +481,7 @@
}
static const TypeInfo milkymist_tmu2_info = {
- .name = "milkymist-tmu2",
+ .name = TYPE_MILKYMIST_TMU2,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistTMU2State),
.class_init = milkymist_tmu2_class_init,
diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c
index 870b339..5150cb4 100644
--- a/hw/display/milkymist-vgafb.c
+++ b/hw/display/milkymist-vgafb.c
@@ -63,8 +63,13 @@
CTRL_RESET = (1<<0),
};
+#define TYPE_MILKYMIST_VGAFB "milkymist-vgafb"
+#define MILKYMIST_VGAFB(obj) \
+ OBJECT_CHECK(MilkymistVgafbState, (obj), TYPE_MILKYMIST_VGAFB)
+
struct MilkymistVgafbState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion regs_region;
QemuConsole *con;
@@ -84,6 +89,7 @@
static void vgafb_update_display(void *opaque)
{
MilkymistVgafbState *s = opaque;
+ SysBusDevice *sbd;
DisplaySurface *surface = qemu_console_surface(s->con);
int first = 0;
int last = 0;
@@ -93,6 +99,7 @@
return;
}
+ sbd = SYS_BUS_DEVICE(s);
int dest_width = s->regs[R_HRES];
switch (surface_bits_per_pixel(surface)) {
@@ -122,7 +129,7 @@
break;
}
- framebuffer_update_display(surface, sysbus_address_space(&s->busdev),
+ framebuffer_update_display(surface, sysbus_address_space(sbd),
s->regs[R_BASEADDRESS] + s->fb_offset,
s->regs[R_HRES],
s->regs[R_VRES],
@@ -256,7 +263,7 @@
static void milkymist_vgafb_reset(DeviceState *d)
{
- MilkymistVgafbState *s = container_of(d, MilkymistVgafbState, busdev.qdev);
+ MilkymistVgafbState *s = MILKYMIST_VGAFB(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -277,7 +284,7 @@
static int milkymist_vgafb_init(SysBusDevice *dev)
{
- MilkymistVgafbState *s = FROM_SYSBUS(typeof(*s), dev);
+ MilkymistVgafbState *s = MILKYMIST_VGAFB(dev);
memory_region_init_io(&s->regs_region, OBJECT(s), &vgafb_mmio_ops, s,
"milkymist-vgafb", R_MAX * 4);
@@ -324,7 +331,7 @@
}
static const TypeInfo milkymist_vgafb_info = {
- .name = "milkymist-vgafb",
+ .name = TYPE_MILKYMIST_VGAFB,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistVgafbState),
.class_init = milkymist_vgafb_class_init,
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
index 60afcf3..e79ab4b 100644
--- a/hw/display/pl110.c
+++ b/hw/display/pl110.c
@@ -39,8 +39,12 @@
PL111
};
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PL110 "pl110"
+#define PL110(obj) OBJECT_CHECK(PL110State, (obj), TYPE_PL110)
+
+typedef struct PL110State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
QemuConsole *con;
@@ -59,7 +63,7 @@
uint32_t palette[256];
uint32_t raw_palette[128];
qemu_irq irq;
-} pl110_state;
+} PL110State;
static int vmstate_pl110_post_load(void *opaque, int version_id);
@@ -69,20 +73,20 @@
.minimum_version_id = 1,
.post_load = vmstate_pl110_post_load,
.fields = (VMStateField[]) {
- VMSTATE_INT32(version, pl110_state),
- VMSTATE_UINT32_ARRAY(timing, pl110_state, 4),
- VMSTATE_UINT32(cr, pl110_state),
- VMSTATE_UINT32(upbase, pl110_state),
- VMSTATE_UINT32(lpbase, pl110_state),
- VMSTATE_UINT32(int_status, pl110_state),
- VMSTATE_UINT32(int_mask, pl110_state),
- VMSTATE_INT32(cols, pl110_state),
- VMSTATE_INT32(rows, pl110_state),
- VMSTATE_UINT32(bpp, pl110_state),
- VMSTATE_INT32(invalidate, pl110_state),
- VMSTATE_UINT32_ARRAY(palette, pl110_state, 256),
- VMSTATE_UINT32_ARRAY(raw_palette, pl110_state, 128),
- VMSTATE_UINT32_V(mux_ctrl, pl110_state, 2),
+ VMSTATE_INT32(version, PL110State),
+ VMSTATE_UINT32_ARRAY(timing, PL110State, 4),
+ VMSTATE_UINT32(cr, PL110State),
+ VMSTATE_UINT32(upbase, PL110State),
+ VMSTATE_UINT32(lpbase, PL110State),
+ VMSTATE_UINT32(int_status, PL110State),
+ VMSTATE_UINT32(int_mask, PL110State),
+ VMSTATE_INT32(cols, PL110State),
+ VMSTATE_INT32(rows, PL110State),
+ VMSTATE_UINT32(bpp, PL110State),
+ VMSTATE_INT32(invalidate, PL110State),
+ VMSTATE_UINT32_ARRAY(palette, PL110State, 256),
+ VMSTATE_UINT32_ARRAY(raw_palette, PL110State, 128),
+ VMSTATE_UINT32_V(mux_ctrl, PL110State, 2),
VMSTATE_END_OF_LIST()
}
};
@@ -121,14 +125,15 @@
#define BITS 32
#include "pl110_template.h"
-static int pl110_enabled(pl110_state *s)
+static int pl110_enabled(PL110State *s)
{
return (s->cr & PL110_CR_EN) && (s->cr & PL110_CR_PWR);
}
static void pl110_update_display(void *opaque)
{
- pl110_state *s = (pl110_state *)opaque;
+ PL110State *s = (PL110State *)opaque;
+ SysBusDevice *sbd;
DisplaySurface *surface = qemu_console_surface(s->con);
drawfn* fntable;
drawfn fn;
@@ -138,8 +143,11 @@
int first;
int last;
- if (!pl110_enabled(s))
+ if (!pl110_enabled(s)) {
return;
+ }
+
+ sbd = SYS_BUS_DEVICE(s);
switch (surface_bits_per_pixel(surface)) {
case 0:
@@ -232,7 +240,7 @@
}
dest_width *= s->cols;
first = 0;
- framebuffer_update_display(surface, sysbus_address_space(&s->busdev),
+ framebuffer_update_display(surface, sysbus_address_space(sbd),
s->upbase, s->cols, s->rows,
src_width, dest_width, 0,
s->invalidate,
@@ -246,14 +254,14 @@
static void pl110_invalidate_display(void * opaque)
{
- pl110_state *s = (pl110_state *)opaque;
+ PL110State *s = (PL110State *)opaque;
s->invalidate = 1;
if (pl110_enabled(s)) {
qemu_console_resize(s->con, s->cols, s->rows);
}
}
-static void pl110_update_palette(pl110_state *s, int n)
+static void pl110_update_palette(PL110State *s, int n)
{
DisplaySurface *surface = qemu_console_surface(s->con);
int i;
@@ -289,7 +297,7 @@
}
}
-static void pl110_resize(pl110_state *s, int width, int height)
+static void pl110_resize(PL110State *s, int width, int height)
{
if (width != s->cols || height != s->rows) {
if (pl110_enabled(s)) {
@@ -301,7 +309,7 @@
}
/* Update interrupts. */
-static void pl110_update(pl110_state *s)
+static void pl110_update(PL110State *s)
{
/* TODO: Implement interrupts. */
}
@@ -309,7 +317,7 @@
static uint64_t pl110_read(void *opaque, hwaddr offset,
unsigned size)
{
- pl110_state *s = (pl110_state *)opaque;
+ PL110State *s = (PL110State *)opaque;
if (offset >= 0xfe0 && offset < 0x1000) {
return idregs[s->version][(offset - 0xfe0) >> 2];
@@ -359,7 +367,7 @@
static void pl110_write(void *opaque, hwaddr offset,
uint64_t val, unsigned size)
{
- pl110_state *s = (pl110_state *)opaque;
+ PL110State *s = (PL110State *)opaque;
int n;
/* For simplicity invalidate the display whenever a control register
@@ -432,13 +440,13 @@
static void pl110_mux_ctrl_set(void *opaque, int line, int level)
{
- pl110_state *s = (pl110_state *)opaque;
+ PL110State *s = (PL110State *)opaque;
s->mux_ctrl = level;
}
static int vmstate_pl110_post_load(void *opaque, int version_id)
{
- pl110_state *s = opaque;
+ PL110State *s = opaque;
/* Make sure we redraw, and at the right size */
pl110_invalidate_display(s);
return 0;
@@ -449,30 +457,38 @@
.gfx_update = pl110_update_display,
};
-static int pl110_init(SysBusDevice *dev)
+static int pl110_initfn(SysBusDevice *sbd)
{
- pl110_state *s = FROM_SYSBUS(pl110_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ PL110State *s = PL110(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &pl110_ops, s, "pl110", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
- qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1);
- s->con = graphic_console_init(DEVICE(dev), &pl110_gfx_ops, s);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+ qdev_init_gpio_in(dev, pl110_mux_ctrl_set, 1);
+ s->con = graphic_console_init(dev, &pl110_gfx_ops, s);
return 0;
}
-static int pl110_versatile_init(SysBusDevice *dev)
+static void pl110_init(Object *obj)
{
- pl110_state *s = FROM_SYSBUS(pl110_state, dev);
- s->version = PL110_VERSATILE;
- return pl110_init(dev);
+ PL110State *s = PL110(obj);
+
+ s->version = PL110;
}
-static int pl111_init(SysBusDevice *dev)
+static void pl110_versatile_init(Object *obj)
{
- pl110_state *s = FROM_SYSBUS(pl110_state, dev);
+ PL110State *s = PL110(obj);
+
+ s->version = PL110_VERSATILE;
+}
+
+static void pl111_init(Object *obj)
+{
+ PL110State *s = PL110(obj);
+
s->version = PL111;
- return pl110_init(dev);
}
static void pl110_class_init(ObjectClass *klass, void *data)
@@ -480,50 +496,30 @@
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = pl110_init;
+ k->init = pl110_initfn;
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
dc->no_user = 1;
dc->vmsd = &vmstate_pl110;
}
static const TypeInfo pl110_info = {
- .name = "pl110",
+ .name = TYPE_PL110,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl110_state),
+ .instance_size = sizeof(PL110State),
+ .instance_init = pl110_init,
.class_init = pl110_class_init,
};
-static void pl110_versatile_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = pl110_versatile_init;
- dc->no_user = 1;
- dc->vmsd = &vmstate_pl110;
-}
-
static const TypeInfo pl110_versatile_info = {
.name = "pl110_versatile",
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl110_state),
- .class_init = pl110_versatile_class_init,
+ .parent = TYPE_PL110,
+ .instance_init = pl110_versatile_init,
};
-static void pl111_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = pl111_init;
- dc->no_user = 1;
- dc->vmsd = &vmstate_pl110;
-}
-
static const TypeInfo pl111_info = {
.name = "pl111",
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl110_state),
- .class_init = pl111_class_init,
+ .parent = TYPE_PL110,
+ .instance_init = pl111_init,
};
static void pl110_register_types(void)
diff --git a/hw/display/qxl-logger.c b/hw/display/qxl-logger.c
index 3cd85d9..c900c2c 100644
--- a/hw/display/qxl-logger.c
+++ b/hw/display/qxl-logger.c
@@ -242,7 +242,7 @@
if (!qxl->cmdlog) {
return 0;
}
- fprintf(stderr, "%" PRId64 " qxl-%d/%s:", qemu_get_clock_ns(vm_clock),
+ fprintf(stderr, "%" PRId64 " qxl-%d/%s:", qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
qxl->id, ring);
fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data,
qxl_name(qxl_type, ext->cmd.type),
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index ddefa06..7649f2b 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1596,7 +1596,7 @@
trace_qxl_io_log(d->id, d->ram->log_buf);
if (d->guestdebug) {
fprintf(stderr, "qxl/guest-%d: %" PRId64 ": %s", d->id,
- qemu_get_clock_ns(vm_clock), d->ram->log_buf);
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), d->ram->log_buf);
}
break;
case QXL_IO_RESET:
@@ -2323,6 +2323,7 @@
k->vendor_id = REDHAT_PCI_VENDOR_ID;
k->device_id = QXL_DEVICE_ID_STABLE;
k->class_id = PCI_CLASS_DISPLAY_VGA;
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
dc->desc = "Spice QXL GPU (primary, vga compatible)";
dc->reset = qxl_reset_handler;
dc->vmsd = &qxl_vmstate;
@@ -2345,6 +2346,7 @@
k->vendor_id = REDHAT_PCI_VENDOR_ID;
k->device_id = QXL_DEVICE_ID_STABLE;
k->class_id = PCI_CLASS_DISPLAY_OTHER;
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
dc->desc = "Spice QXL GPU (secondary)";
dc->reset = qxl_reset_handler;
dc->vmsd = &qxl_vmstate;
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index 9fd48b5..24876d3 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -34,8 +34,12 @@
#define TCX_THC_NREGS_24 0x1000
#define TCX_TEC_NREGS 0x1000
+#define TYPE_TCX "SUNW,tcx"
+#define TCX(obj) OBJECT_CHECK(TCXState, (obj), TYPE_TCX)
+
typedef struct TCXState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
QemuConsole *con;
uint8_t *vram;
uint32_t *vram24, *cplane;
@@ -423,7 +427,7 @@
static void tcx_reset(DeviceState *d)
{
- TCXState *s = container_of(d, TCXState, busdev.qdev);
+ TCXState *s = TCX(d);
/* Initialize palette */
memset(s->r, 0, 256);
@@ -523,7 +527,7 @@
static int tcx_init1(SysBusDevice *dev)
{
- TCXState *s = FROM_SYSBUS(TCXState, dev);
+ TCXState *s = TCX(dev);
ram_addr_t vram_offset = 0;
int size;
uint8_t *vram_base;
@@ -609,7 +613,7 @@
}
static const TypeInfo tcx_info = {
- .name = "SUNW,tcx",
+ .name = TYPE_TCX,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(TCXState),
.class_init = tcx_class_init,
diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c
index 8d560ec..c2a19ad 100644
--- a/hw/display/vga-isa.c
+++ b/hw/display/vga-isa.c
@@ -87,6 +87,7 @@
dc->reset = vga_isa_reset;
dc->vmsd = &vmstate_vga_common;
dc->props = vga_isa_properties;
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
}
static const TypeInfo vga_isa_info = {
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index 3e150ab..b3a45c8 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -198,6 +198,7 @@
k->class_id = PCI_CLASS_DISPLAY_VGA;
dc->vmsd = &vmstate_vga_pci;
dc->props = vga_pci_properties;
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
}
static const TypeInfo vga_info = {
diff --git a/hw/display/vga.c b/hw/display/vga.c
index 06f44a8..7b91d9c 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -318,7 +318,7 @@
int cur_line, cur_line_char, cur_char;
int64_t cur_tick;
- cur_tick = qemu_get_clock_ns(vm_clock);
+ cur_tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
cur_line = cur_char / r->htotal;
@@ -1304,7 +1304,7 @@
uint32_t *ch_attr_ptr;
vga_draw_glyph8_func *vga_draw_glyph8;
vga_draw_glyph9_func *vga_draw_glyph9;
- int64_t now = qemu_get_clock_ms(vm_clock);
+ int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
/* compute font data address (in plane 2) */
v = s->sr[VGA_SEQ_CHARACTER_MAP];
@@ -1907,7 +1907,7 @@
}
if (graphic_mode != s->graphic_mode) {
s->graphic_mode = graphic_mode;
- s->cursor_blink_time = qemu_get_clock_ms(vm_clock);
+ s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
full_update = 1;
}
switch(graphic_mode) {
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 3536cde..a6a8cdc 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -1306,6 +1306,7 @@
dc->reset = vmsvga_reset;
dc->vmsd = &vmstate_vmware_vga;
dc->props = vga_vmware_properties;
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
}
static const TypeInfo vmsvga_info = {
diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c
index 7937c3e..35b9015 100644
--- a/hw/dma/pl080.c
+++ b/hw/dma/pl080.c
@@ -35,8 +35,12 @@
uint32_t conf;
} pl080_channel;
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PL080 "pl080"
+#define PL080(obj) OBJECT_CHECK(PL080State, (obj), TYPE_PL080)
+
+typedef struct PL080State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint8_t tc_int;
uint8_t tc_mask;
@@ -51,7 +55,7 @@
/* Flag to avoid recursive DMA invocations. */
int running;
qemu_irq irq;
-} pl080_state;
+} PL080State;
static const VMStateDescription vmstate_pl080_channel = {
.name = "pl080_channel",
@@ -72,20 +76,20 @@
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
- VMSTATE_UINT8(tc_int, pl080_state),
- VMSTATE_UINT8(tc_mask, pl080_state),
- VMSTATE_UINT8(err_int, pl080_state),
- VMSTATE_UINT8(err_mask, pl080_state),
- VMSTATE_UINT32(conf, pl080_state),
- VMSTATE_UINT32(sync, pl080_state),
- VMSTATE_UINT32(req_single, pl080_state),
- VMSTATE_UINT32(req_burst, pl080_state),
- VMSTATE_UINT8(tc_int, pl080_state),
- VMSTATE_UINT8(tc_int, pl080_state),
- VMSTATE_UINT8(tc_int, pl080_state),
- VMSTATE_STRUCT_ARRAY(chan, pl080_state, PL080_MAX_CHANNELS,
+ VMSTATE_UINT8(tc_int, PL080State),
+ VMSTATE_UINT8(tc_mask, PL080State),
+ VMSTATE_UINT8(err_int, PL080State),
+ VMSTATE_UINT8(err_mask, PL080State),
+ VMSTATE_UINT32(conf, PL080State),
+ VMSTATE_UINT32(sync, PL080State),
+ VMSTATE_UINT32(req_single, PL080State),
+ VMSTATE_UINT32(req_burst, PL080State),
+ VMSTATE_UINT8(tc_int, PL080State),
+ VMSTATE_UINT8(tc_int, PL080State),
+ VMSTATE_UINT8(tc_int, PL080State),
+ VMSTATE_STRUCT_ARRAY(chan, PL080State, PL080_MAX_CHANNELS,
1, vmstate_pl080_channel, pl080_channel),
- VMSTATE_INT32(running, pl080_state),
+ VMSTATE_INT32(running, PL080State),
VMSTATE_END_OF_LIST()
}
};
@@ -96,7 +100,7 @@
static const unsigned char pl081_id[] =
{ 0x81, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
-static void pl080_update(pl080_state *s)
+static void pl080_update(PL080State *s)
{
if ((s->tc_int & s->tc_mask)
|| (s->err_int & s->err_mask))
@@ -105,7 +109,7 @@
qemu_irq_lower(s->irq);
}
-static void pl080_run(pl080_state *s)
+static void pl080_run(PL080State *s)
{
int c;
int flow;
@@ -221,7 +225,7 @@
static uint64_t pl080_read(void *opaque, hwaddr offset,
unsigned size)
{
- pl080_state *s = (pl080_state *)opaque;
+ PL080State *s = (PL080State *)opaque;
uint32_t i;
uint32_t mask;
@@ -290,7 +294,7 @@
static void pl080_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
- pl080_state *s = (pl080_state *)opaque;
+ PL080State *s = (PL080State *)opaque;
int i;
if (offset >= 0x100 && offset < 0x200) {
@@ -355,59 +359,44 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int pl08x_init(SysBusDevice *dev, int nchannels)
+static void pl080_init(Object *obj)
{
- pl080_state *s = FROM_SYSBUS(pl080_state, dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ PL080State *s = PL080(obj);
memory_region_init_io(&s->iomem, OBJECT(s), &pl080_ops, s, "pl080", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
- s->nchannels = nchannels;
- return 0;
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+ s->nchannels = 8;
}
-static int pl080_init(SysBusDevice *dev)
+static void pl081_init(Object *obj)
{
- return pl08x_init(dev, 8);
+ PL080State *s = PL080(obj);
+
+ s->nchannels = 2;
}
-static int pl081_init(SysBusDevice *dev)
+static void pl080_class_init(ObjectClass *oc, void *data)
{
- return pl08x_init(dev, 2);
-}
+ DeviceClass *dc = DEVICE_CLASS(oc);
-static void pl080_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = pl080_init;
dc->no_user = 1;
dc->vmsd = &vmstate_pl080;
}
static const TypeInfo pl080_info = {
- .name = "pl080",
+ .name = TYPE_PL080,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl080_state),
+ .instance_size = sizeof(PL080State),
+ .instance_init = pl080_init,
.class_init = pl080_class_init,
};
-static void pl081_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = pl081_init;
- dc->no_user = 1;
- dc->vmsd = &vmstate_pl080;
-}
-
static const TypeInfo pl081_info = {
.name = "pl081",
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl080_state),
- .class_init = pl081_class_init,
+ .parent = TYPE_PL080,
+ .instance_init = pl081_init,
};
/* The PL080 and PL081 are the same except for the number of channels
diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c
index ddcc413..401399d 100644
--- a/hw/dma/pl330.c
+++ b/hw/dma/pl330.c
@@ -1256,7 +1256,7 @@
if (s->periph_busy[irq] != level) {
s->periph_busy[irq] = level;
- qemu_mod_timer(s->timer, qemu_get_clock_ns(vm_clock));
+ timer_mod(s->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
}
}
@@ -1519,7 +1519,7 @@
s->periph_busy[i] = 0;
}
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
}
static void pl330_realize(DeviceState *dev, Error **errp)
@@ -1532,7 +1532,7 @@
"dma", PL330_IOMEM_SIZE);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
- s->timer = qemu_new_timer_ns(vm_clock, pl330_exec_cycle_timer, s);
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pl330_exec_cycle_timer, s);
s->cfg[0] = (s->mgr_ns_at_rst ? 0x4 : 0) |
(s->num_periph_req > 0 ? 1 : 0) |
diff --git a/hw/dma/puv3_dma.c b/hw/dma/puv3_dma.c
index 36004ae..101bd7f 100644
--- a/hw/dma/puv3_dma.c
+++ b/hw/dma/puv3_dma.c
@@ -18,8 +18,12 @@
#define PUV3_DMA_CH_MASK (0xff)
#define PUV3_DMA_CH(offset) ((offset) >> 8)
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PUV3_DMA "puv3_dma"
+#define PUV3_DMA(obj) OBJECT_CHECK(PUV3DMAState, (obj), TYPE_PUV3_DMA)
+
+typedef struct PUV3DMAState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t reg_CFG[PUV3_DMA_CH_NR];
} PUV3DMAState;
@@ -73,7 +77,7 @@
static int puv3_dma_init(SysBusDevice *dev)
{
- PUV3DMAState *s = FROM_SYSBUS(PUV3DMAState, dev);
+ PUV3DMAState *s = PUV3_DMA(dev);
int i;
for (i = 0; i < PUV3_DMA_CH_NR; i++) {
@@ -95,7 +99,7 @@
}
static const TypeInfo puv3_dma_info = {
- .name = "puv3_dma",
+ .name = TYPE_PUV3_DMA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PUV3DMAState),
.class_init = puv3_dma_class_init,
diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c
index bc7bf4c..c013abb 100644
--- a/hw/dma/pxa2xx_dma.c
+++ b/hw/dma/pxa2xx_dma.c
@@ -26,8 +26,12 @@
int request;
} PXA2xxDMAChannel;
+#define TYPE_PXA2XX_DMA "pxa2xx-dma"
+#define PXA2XX_DMA(obj) OBJECT_CHECK(PXA2xxDMAState, (obj), TYPE_PXA2XX_DMA)
+
typedef struct PXA2xxDMAState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq irq;
@@ -445,11 +449,11 @@
}
}
-static int pxa2xx_dma_init(SysBusDevice *dev)
+static int pxa2xx_dma_init(SysBusDevice *sbd)
{
+ DeviceState *dev = DEVICE(sbd);
+ PXA2xxDMAState *s = PXA2XX_DMA(dev);
int i;
- PXA2xxDMAState *s;
- s = FROM_SYSBUS(PXA2xxDMAState, dev);
if (s->channels <= 0) {
return -1;
@@ -463,12 +467,12 @@
memset(s->req, 0, sizeof(uint8_t) * PXA2XX_DMA_NUM_REQUESTS);
- qdev_init_gpio_in(&dev->qdev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS);
+ qdev_init_gpio_in(dev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS);
memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_dma_ops, s,
"pxa2xx.dma", 0x00010000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
return 0;
}
@@ -560,7 +564,7 @@
}
static const TypeInfo pxa2xx_dma_info = {
- .name = "pxa2xx-dma",
+ .name = TYPE_PXA2XX_DMA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PXA2xxDMAState),
.class_init = pxa2xx_dma_class_init,
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index 4ec433f..af26632 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -107,7 +107,7 @@
tm_hz = 1000 / (s->itr + 1);
- qemu_mod_timer(s->periodic_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(s->periodic_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
get_ticks_per_sec() / tm_hz);
}
@@ -806,7 +806,7 @@
*irqs = qemu_allocate_irqs(rc4030_irq_jazz_request, s, 16);
*dmas = rc4030_allocate_dmas(s, 4);
- s->periodic_timer = qemu_new_timer_ns(vm_clock, rc4030_periodic_timer, s);
+ s->periodic_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, rc4030_periodic_timer, s);
s->timer_irq = timer;
s->jazz_bus_irq = jazz_bus;
diff --git a/hw/dma/soc_dma.c b/hw/dma/soc_dma.c
index 5e3491d..c06aabb 100644
--- a/hw/dma/soc_dma.c
+++ b/hw/dma/soc_dma.c
@@ -84,10 +84,10 @@
static void soc_dma_ch_schedule(struct soc_dma_ch_s *ch, int delay_bytes)
{
- int64_t now = qemu_get_clock_ns(vm_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
struct dma_s *dma = (struct dma_s *) ch->dma;
- qemu_mod_timer(ch->timer, now + delay_bytes / dma->channel_freq);
+ timer_mod(ch->timer, now + delay_bytes / dma->channel_freq);
}
static void soc_dma_ch_run(void *opaque)
@@ -217,7 +217,7 @@
ch->enable = level;
if (!ch->enable)
- qemu_del_timer(ch->timer);
+ timer_del(ch->timer);
else if (!ch->running)
soc_dma_ch_run(ch);
else
@@ -246,7 +246,7 @@
for (i = 0; i < n; i ++) {
s->ch[i].dma = &s->soc;
s->ch[i].num = i;
- s->ch[i].timer = qemu_new_timer_ns(vm_clock, soc_dma_ch_run, &s->ch[i]);
+ s->ch[i].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, soc_dma_ch_run, &s->ch[i]);
}
soc_dma_reset(&s->soc);
diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
index be6275f..2a92ffb 100644
--- a/hw/dma/sparc32_dma.c
+++ b/hw/dma/sparc32_dma.c
@@ -60,10 +60,14 @@
/* XXX SCSI and ethernet should have different read-only bit masks */
#define DMA_CSR_RO_MASK 0xfe000007
+#define TYPE_SPARC32_DMA "sparc32_dma"
+#define SPARC32_DMA(obj) OBJECT_CHECK(DMAState, (obj), TYPE_SPARC32_DMA)
+
typedef struct DMAState DMAState;
struct DMAState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t dmaregs[DMA_REGS];
qemu_irq irq;
@@ -249,7 +253,7 @@
static void dma_reset(DeviceState *d)
{
- DMAState *s = container_of(d, DMAState, busdev.qdev);
+ DMAState *s = SPARC32_DMA(d);
memset(s->dmaregs, 0, DMA_SIZE);
s->dmaregs[0] = DMA_VER;
@@ -266,20 +270,21 @@
}
};
-static int sparc32_dma_init1(SysBusDevice *dev)
+static int sparc32_dma_init1(SysBusDevice *sbd)
{
- DMAState *s = FROM_SYSBUS(DMAState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ DMAState *s = SPARC32_DMA(dev);
int reg_size;
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE;
memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s,
"dma", reg_size);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
- qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1);
- qdev_init_gpio_out(&dev->qdev, s->gpio, 2);
+ qdev_init_gpio_in(dev, dma_set_irq, 1);
+ qdev_init_gpio_out(dev, s->gpio, 2);
return 0;
}
@@ -302,7 +307,7 @@
}
static const TypeInfo sparc32_dma_info = {
- .name = "sparc32_dma",
+ .name = TYPE_SPARC32_DMA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(DMAState),
.class_init = sparc32_dma_class_init,
diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c
index edb93f3..a04409a 100644
--- a/hw/dma/sun4m_iommu.c
+++ b/hw/dma/sun4m_iommu.c
@@ -126,8 +126,12 @@
#define IOMMU_PAGE_SIZE (1 << IOMMU_PAGE_SHIFT)
#define IOMMU_PAGE_MASK ~(IOMMU_PAGE_SIZE - 1)
+#define TYPE_SUN4M_IOMMU "iommu"
+#define SUN4M_IOMMU(obj) OBJECT_CHECK(IOMMUState, (obj), TYPE_SUN4M_IOMMU)
+
typedef struct IOMMUState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t regs[IOMMU_NREGS];
hwaddr iostart;
@@ -332,7 +336,7 @@
static void iommu_reset(DeviceState *d)
{
- IOMMUState *s = container_of(d, IOMMUState, busdev.qdev);
+ IOMMUState *s = SUN4M_IOMMU(d);
memset(s->regs, 0, IOMMU_NREGS * 4);
s->iostart = 0;
@@ -345,7 +349,7 @@
static int iommu_init1(SysBusDevice *dev)
{
- IOMMUState *s = FROM_SYSBUS(IOMMUState, dev);
+ IOMMUState *s = SUN4M_IOMMU(dev);
sysbus_init_irq(dev, &s->irq);
@@ -373,7 +377,7 @@
}
static const TypeInfo iommu_info = {
- .name = "iommu",
+ .name = TYPE_SUN4M_IOMMU,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IOMMUState),
.class_init = iommu_class_init,
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index a48e3ba..59e8e35 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -27,6 +27,7 @@
#include "hw/ptimer.h"
#include "qemu/log.h"
#include "qapi/qmp/qerror.h"
+#include "qemu/main-loop.h"
#include "hw/stream.h"
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
index 855afae..b8f572b 100644
--- a/hw/gpio/omap_gpio.c
+++ b/hw/gpio/omap_gpio.c
@@ -35,8 +35,13 @@
uint16_t pins;
};
+#define TYPE_OMAP1_GPIO "omap-gpio"
+#define OMAP1_GPIO(obj) \
+ OBJECT_CHECK(struct omap_gpif_s, (obj), TYPE_OMAP1_GPIO)
+
struct omap_gpif_s {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
int mpu_model;
void *clk;
@@ -203,8 +208,13 @@
uint8_t delay;
};
+#define TYPE_OMAP2_GPIO "omap2-gpio"
+#define OMAP2_GPIO(obj) \
+ OBJECT_CHECK(struct omap2_gpif_s, (obj), TYPE_OMAP2_GPIO)
+
struct omap2_gpif_s {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
int mpu_model;
void *iclk;
@@ -587,16 +597,16 @@
static void omap_gpif_reset(DeviceState *dev)
{
- struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s,
- SYS_BUS_DEVICE(dev));
+ struct omap_gpif_s *s = OMAP1_GPIO(dev);
+
omap_gpio_reset(&s->omap1);
}
static void omap2_gpif_reset(DeviceState *dev)
{
+ struct omap2_gpif_s *s = OMAP2_GPIO(dev);
int i;
- struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s,
- SYS_BUS_DEVICE(dev));
+
for (i = 0; i < s->modulecount; i++) {
omap2_gpio_module_reset(&s->modules[i]);
}
@@ -648,7 +658,7 @@
case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
if (value & (1 << 1)) /* SOFTRESET */
- omap2_gpif_reset(&s->busdev.qdev);
+ omap2_gpif_reset(DEVICE(s));
s->autoidle = value & 1;
break;
@@ -668,25 +678,29 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int omap_gpio_init(SysBusDevice *dev)
+static int omap_gpio_init(SysBusDevice *sbd)
{
- struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s, dev);
+ DeviceState *dev = DEVICE(sbd);
+ struct omap_gpif_s *s = OMAP1_GPIO(dev);
+
if (!s->clk) {
hw_error("omap-gpio: clk not connected\n");
}
- qdev_init_gpio_in(&dev->qdev, omap_gpio_set, 16);
- qdev_init_gpio_out(&dev->qdev, s->omap1.handler, 16);
- sysbus_init_irq(dev, &s->omap1.irq);
+ qdev_init_gpio_in(dev, omap_gpio_set, 16);
+ qdev_init_gpio_out(dev, s->omap1.handler, 16);
+ sysbus_init_irq(sbd, &s->omap1.irq);
memory_region_init_io(&s->iomem, OBJECT(s), &omap_gpio_ops, &s->omap1,
"omap.gpio", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
return 0;
}
-static int omap2_gpio_init(SysBusDevice *dev)
+static int omap2_gpio_init(SysBusDevice *sbd)
{
+ DeviceState *dev = DEVICE(sbd);
+ struct omap2_gpif_s *s = OMAP2_GPIO(dev);
int i;
- struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s, dev);
+
if (!s->iclk) {
hw_error("omap2-gpio: iclk not connected\n");
}
@@ -694,14 +708,14 @@
s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
memory_region_init_io(&s->iomem, OBJECT(s), &omap2_gpif_top_ops, s,
"omap2.gpio", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
} else {
s->modulecount = 6;
}
s->modules = g_malloc0(s->modulecount * sizeof(struct omap2_gpio_s));
s->handler = g_malloc0(s->modulecount * 32 * sizeof(qemu_irq));
- qdev_init_gpio_in(&dev->qdev, omap2_gpio_set, s->modulecount * 32);
- qdev_init_gpio_out(&dev->qdev, s->handler, s->modulecount * 32);
+ qdev_init_gpio_in(dev, omap2_gpio_set, s->modulecount * 32);
+ qdev_init_gpio_out(dev, s->handler, s->modulecount * 32);
for (i = 0; i < s->modulecount; i++) {
struct omap2_gpio_s *m = &s->modules[i];
if (!s->fclk[i]) {
@@ -709,12 +723,12 @@
}
m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
m->handler = &s->handler[i * 32];
- sysbus_init_irq(dev, &m->irq[0]); /* mpu irq */
- sysbus_init_irq(dev, &m->irq[1]); /* dsp irq */
- sysbus_init_irq(dev, &m->wkup);
+ sysbus_init_irq(sbd, &m->irq[0]); /* mpu irq */
+ sysbus_init_irq(sbd, &m->irq[1]); /* dsp irq */
+ sysbus_init_irq(sbd, &m->wkup);
memory_region_init_io(&m->iomem, OBJECT(s), &omap2_gpio_module_ops, m,
"omap.gpio-module", 0x1000);
- sysbus_init_mmio(dev, &m->iomem);
+ sysbus_init_mmio(sbd, &m->iomem);
}
return 0;
}
@@ -748,7 +762,7 @@
}
static const TypeInfo omap_gpio_info = {
- .name = "omap-gpio",
+ .name = TYPE_OMAP1_GPIO,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct omap_gpif_s),
.class_init = omap_gpio_class_init,
@@ -777,7 +791,7 @@
}
static const TypeInfo omap2_gpio_info = {
- .name = "omap2-gpio",
+ .name = TYPE_OMAP2_GPIO,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct omap2_gpif_s),
.class_init = omap2_gpio_class_init,
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
index a0bbf08..dd4ea29 100644
--- a/hw/gpio/pl061.c
+++ b/hw/gpio/pl061.c
@@ -28,8 +28,12 @@
static const uint8_t pl061_id_luminary[12] =
{ 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 };
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PL061 "pl061"
+#define PL061(obj) OBJECT_CHECK(PL061State, (obj), TYPE_PL061)
+
+typedef struct PL061State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t locked;
uint32_t data;
@@ -55,39 +59,39 @@
qemu_irq irq;
qemu_irq out[8];
const unsigned char *id;
-} pl061_state;
+} PL061State;
static const VMStateDescription vmstate_pl061 = {
.name = "pl061",
.version_id = 2,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(locked, pl061_state),
- VMSTATE_UINT32(data, pl061_state),
- VMSTATE_UINT32(old_data, pl061_state),
- VMSTATE_UINT32(dir, pl061_state),
- VMSTATE_UINT32(isense, pl061_state),
- VMSTATE_UINT32(ibe, pl061_state),
- VMSTATE_UINT32(iev, pl061_state),
- VMSTATE_UINT32(im, pl061_state),
- VMSTATE_UINT32(istate, pl061_state),
- VMSTATE_UINT32(afsel, pl061_state),
- VMSTATE_UINT32(dr2r, pl061_state),
- VMSTATE_UINT32(dr4r, pl061_state),
- VMSTATE_UINT32(dr8r, pl061_state),
- VMSTATE_UINT32(odr, pl061_state),
- VMSTATE_UINT32(pur, pl061_state),
- VMSTATE_UINT32(pdr, pl061_state),
- VMSTATE_UINT32(slr, pl061_state),
- VMSTATE_UINT32(den, pl061_state),
- VMSTATE_UINT32(cr, pl061_state),
- VMSTATE_UINT32(float_high, pl061_state),
- VMSTATE_UINT32_V(amsel, pl061_state, 2),
+ VMSTATE_UINT32(locked, PL061State),
+ VMSTATE_UINT32(data, PL061State),
+ VMSTATE_UINT32(old_data, PL061State),
+ VMSTATE_UINT32(dir, PL061State),
+ VMSTATE_UINT32(isense, PL061State),
+ VMSTATE_UINT32(ibe, PL061State),
+ VMSTATE_UINT32(iev, PL061State),
+ VMSTATE_UINT32(im, PL061State),
+ VMSTATE_UINT32(istate, PL061State),
+ VMSTATE_UINT32(afsel, PL061State),
+ VMSTATE_UINT32(dr2r, PL061State),
+ VMSTATE_UINT32(dr4r, PL061State),
+ VMSTATE_UINT32(dr8r, PL061State),
+ VMSTATE_UINT32(odr, PL061State),
+ VMSTATE_UINT32(pur, PL061State),
+ VMSTATE_UINT32(pdr, PL061State),
+ VMSTATE_UINT32(slr, PL061State),
+ VMSTATE_UINT32(den, PL061State),
+ VMSTATE_UINT32(cr, PL061State),
+ VMSTATE_UINT32(float_high, PL061State),
+ VMSTATE_UINT32_V(amsel, PL061State, 2),
VMSTATE_END_OF_LIST()
}
};
-static void pl061_update(pl061_state *s)
+static void pl061_update(PL061State *s)
{
uint8_t changed;
uint8_t mask;
@@ -116,7 +120,7 @@
static uint64_t pl061_read(void *opaque, hwaddr offset,
unsigned size)
{
- pl061_state *s = (pl061_state *)opaque;
+ PL061State *s = (PL061State *)opaque;
if (offset >= 0xfd0 && offset < 0x1000) {
return s->id[(offset - 0xfd0) >> 2];
@@ -173,7 +177,7 @@
static void pl061_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
- pl061_state *s = (pl061_state *)opaque;
+ PL061State *s = (PL061State *)opaque;
uint8_t mask;
if (offset < 0x400) {
@@ -246,7 +250,7 @@
pl061_update(s);
}
-static void pl061_reset(pl061_state *s)
+static void pl061_reset(PL061State *s)
{
s->locked = 1;
s->cr = 0xff;
@@ -254,7 +258,7 @@
static void pl061_set_irq(void * opaque, int irq, int level)
{
- pl061_state *s = (pl061_state *)opaque;
+ PL061State *s = (PL061State *)opaque;
uint8_t mask;
mask = 1 << irq;
@@ -272,27 +276,32 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int pl061_init(SysBusDevice *dev, const unsigned char *id)
+static int pl061_initfn(SysBusDevice *sbd)
{
- pl061_state *s = FROM_SYSBUS(pl061_state, dev);
- s->id = id;
+ DeviceState *dev = DEVICE(sbd);
+ PL061State *s = PL061(dev);
+
memory_region_init_io(&s->iomem, OBJECT(s), &pl061_ops, s, "pl061", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
- qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8);
- qdev_init_gpio_out(&dev->qdev, s->out, 8);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+ qdev_init_gpio_in(dev, pl061_set_irq, 8);
+ qdev_init_gpio_out(dev, s->out, 8);
pl061_reset(s);
return 0;
}
-static int pl061_init_luminary(SysBusDevice *dev)
+static void pl061_luminary_init(Object *obj)
{
- return pl061_init(dev, pl061_id_luminary);
+ PL061State *s = PL061(obj);
+
+ s->id = pl061_id_luminary;
}
-static int pl061_init_arm(SysBusDevice *dev)
+static void pl061_init(Object *obj)
{
- return pl061_init(dev, pl061_id);
+ PL061State *s = PL061(obj);
+
+ s->id = pl061_id;
}
static void pl061_class_init(ObjectClass *klass, void *data)
@@ -300,31 +309,22 @@
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = pl061_init_arm;
+ k->init = pl061_initfn;
dc->vmsd = &vmstate_pl061;
}
static const TypeInfo pl061_info = {
- .name = "pl061",
+ .name = TYPE_PL061,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl061_state),
+ .instance_size = sizeof(PL061State),
+ .instance_init = pl061_init,
.class_init = pl061_class_init,
};
-static void pl061_luminary_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = pl061_init_luminary;
- dc->vmsd = &vmstate_pl061;
-}
-
static const TypeInfo pl061_luminary_info = {
.name = "pl061_luminary",
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl061_state),
- .class_init = pl061_luminary_class_init,
+ .parent = TYPE_PL061,
+ .instance_init = pl061_luminary_init,
};
static void pl061_register_types(void)
diff --git a/hw/gpio/puv3_gpio.c b/hw/gpio/puv3_gpio.c
index 18671eb..39840aa 100644
--- a/hw/gpio/puv3_gpio.c
+++ b/hw/gpio/puv3_gpio.c
@@ -14,8 +14,12 @@
#undef DEBUG_PUV3
#include "hw/unicore32/puv3.h"
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PUV3_GPIO "puv3_gpio"
+#define PUV3_GPIO(obj) OBJECT_CHECK(PUV3GPIOState, (obj), TYPE_PUV3_GPIO)
+
+typedef struct PUV3GPIOState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq irq[9];
@@ -96,7 +100,7 @@
static int puv3_gpio_init(SysBusDevice *dev)
{
- PUV3GPIOState *s = FROM_SYSBUS(PUV3GPIOState, dev);
+ PUV3GPIOState *s = PUV3_GPIO(dev);
s->reg_GPLR = 0;
s->reg_GPDR = 0;
@@ -127,7 +131,7 @@
}
static const TypeInfo puv3_gpio_info = {
- .name = "puv3_gpio",
+ .name = TYPE_PUV3_GPIO,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PUV3GPIOState),
.class_init = puv3_gpio_class_init,
diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
index c235c3e..dc79a8b 100644
--- a/hw/gpio/zaurus.c
+++ b/hw/gpio/zaurus.c
@@ -24,9 +24,13 @@
/* SCOOP devices */
+#define TYPE_SCOOP "scoop"
+#define SCOOP(obj) OBJECT_CHECK(ScoopInfo, (obj), TYPE_SCOOP)
+
typedef struct ScoopInfo ScoopInfo;
struct ScoopInfo {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
qemu_irq handler[16];
MemoryRegion iomem;
uint16_t status;
@@ -162,16 +166,17 @@
s->gpio_level &= ~(1 << line);
}
-static int scoop_init(SysBusDevice *dev)
+static int scoop_init(SysBusDevice *sbd)
{
- ScoopInfo *s = FROM_SYSBUS(ScoopInfo, dev);
+ DeviceState *dev = DEVICE(sbd);
+ ScoopInfo *s = SCOOP(dev);
s->status = 0x02;
- qdev_init_gpio_out(&s->busdev.qdev, s->handler, 16);
- qdev_init_gpio_in(&s->busdev.qdev, scoop_gpio_set, 16);
+ qdev_init_gpio_out(dev, s->handler, 16);
+ qdev_init_gpio_in(dev, scoop_gpio_set, 16);
memory_region_init_io(&s->iomem, OBJECT(s), &scoop_ops, s, "scoop", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
return 0;
}
@@ -237,7 +242,7 @@
}
static const TypeInfo scoop_sysbus_info = {
- .name = "scoop",
+ .name = TYPE_SCOOP,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ScoopInfo),
.class_init = scoop_sysbus_class_init,
diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c
index 5f8b972..ca59456 100644
--- a/hw/i2c/bitbang_i2c.c
+++ b/hw/i2c/bitbang_i2c.c
@@ -185,8 +185,13 @@
}
/* GPIO interface. */
-typedef struct {
- SysBusDevice busdev;
+
+#define TYPE_GPIO_I2C "gpio_i2c"
+#define GPIO_I2C(obj) OBJECT_CHECK(GPIOI2CState, (obj), TYPE_GPIO_I2C)
+
+typedef struct GPIOI2CState {
+ SysBusDevice parent_obj;
+
MemoryRegion dummy_iomem;
bitbang_i2c_interface *bitbang;
int last_level;
@@ -204,19 +209,20 @@
}
}
-static int gpio_i2c_init(SysBusDevice *dev)
+static int gpio_i2c_init(SysBusDevice *sbd)
{
- GPIOI2CState *s = FROM_SYSBUS(GPIOI2CState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ GPIOI2CState *s = GPIO_I2C(dev);
i2c_bus *bus;
memory_region_init(&s->dummy_iomem, OBJECT(s), "gpio_i2c", 0);
- sysbus_init_mmio(dev, &s->dummy_iomem);
+ sysbus_init_mmio(sbd, &s->dummy_iomem);
- bus = i2c_init_bus(&dev->qdev, "i2c");
+ bus = i2c_init_bus(dev, "i2c");
s->bitbang = bitbang_i2c_init(bus);
- qdev_init_gpio_in(&dev->qdev, bitbang_i2c_gpio_set, 2);
- qdev_init_gpio_out(&dev->qdev, &s->out, 1);
+ qdev_init_gpio_in(dev, bitbang_i2c_gpio_set, 2);
+ qdev_init_gpio_out(dev, &s->out, 1);
return 0;
}
@@ -227,11 +233,12 @@
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = gpio_i2c_init;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->desc = "Virtual GPIO to I2C bridge";
}
static const TypeInfo gpio_i2c_info = {
- .name = "gpio_i2c",
+ .name = TYPE_GPIO_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(GPIOI2CState),
.class_init = gpio_i2c_class_init,
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index 22ef3b9..c97e7f7 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -224,6 +224,7 @@
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = i2c_slave_qdev_init;
+ set_bit(DEVICE_CATEGORY_MISC, k->categories);
k->bus_type = TYPE_I2C_BUS;
k->props = i2c_props;
}
diff --git a/hw/i2c/exynos4210_i2c.c b/hw/i2c/exynos4210_i2c.c
index 42f5e89..ce5f849 100644
--- a/hw/i2c/exynos4210_i2c.c
+++ b/hw/i2c/exynos4210_i2c.c
@@ -80,7 +80,8 @@
#endif
typedef struct Exynos4210I2CState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
i2c_bus *bus;
qemu_irq irq;
@@ -297,15 +298,16 @@
s->scl_free = true;
}
-static int exynos4210_i2c_realize(SysBusDevice *dev)
+static int exynos4210_i2c_realize(SysBusDevice *sbd)
{
+ DeviceState *dev = DEVICE(sbd);
Exynos4210I2CState *s = EXYNOS4_I2C(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_i2c_ops, s,
TYPE_EXYNOS4_I2C, EXYNOS4_I2C_MEM_SIZE);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
- s->bus = i2c_init_bus(&dev->qdev, "i2c");
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+ s->bus = i2c_init_bus(dev, "i2c");
return 0;
}
diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c
index f0eb448..f528b2b 100644
--- a/hw/i2c/omap_i2c.c
+++ b/hw/i2c/omap_i2c.c
@@ -21,9 +21,12 @@
#include "hw/arm/omap.h"
#include "hw/sysbus.h"
+#define TYPE_OMAP_I2C "omap_i2c"
+#define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C)
typedef struct OMAPI2CState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq irq;
qemu_irq drq[2];
@@ -130,8 +133,8 @@
static void omap_i2c_reset(DeviceState *dev)
{
- OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState,
- SYS_BUS_DEVICE(dev));
+ OMAPI2CState *s = OMAP_I2C(dev);
+
s->mask = 0;
s->stat = 0;
s->dma = 0;
@@ -316,15 +319,17 @@
return;
}
- if (value & 2)
- omap_i2c_reset(&s->busdev.qdev);
+ if (value & 2) {
+ omap_i2c_reset(DEVICE(s));
+ }
break;
case 0x24: /* I2C_CON */
s->control = value & 0xcf87;
if (~value & (1 << 15)) { /* I2C_EN */
- if (s->revision < OMAP2_INTR_REV)
- omap_i2c_reset(&s->busdev.qdev);
+ if (s->revision < OMAP2_INTR_REV) {
+ omap_i2c_reset(DEVICE(s));
+ }
break;
}
if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */
@@ -434,9 +439,10 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int omap_i2c_init(SysBusDevice *dev)
+static int omap_i2c_init(SysBusDevice *sbd)
{
- OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ OMAPI2CState *s = OMAP_I2C(dev);
if (!s->fclk) {
hw_error("omap_i2c: fclk not connected\n");
@@ -445,13 +451,13 @@
/* Note that OMAP1 doesn't have a separate interface clock */
hw_error("omap_i2c: iclk not connected\n");
}
- sysbus_init_irq(dev, &s->irq);
- sysbus_init_irq(dev, &s->drq[0]);
- sysbus_init_irq(dev, &s->drq[1]);
+ sysbus_init_irq(sbd, &s->irq);
+ sysbus_init_irq(sbd, &s->drq[0]);
+ sysbus_init_irq(sbd, &s->drq[1]);
memory_region_init_io(&s->iomem, OBJECT(s), &omap_i2c_ops, s, "omap.i2c",
(s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- s->bus = i2c_init_bus(&dev->qdev, NULL);
+ sysbus_init_mmio(sbd, &s->iomem);
+ s->bus = i2c_init_bus(dev, NULL);
return 0;
}
@@ -472,7 +478,7 @@
}
static const TypeInfo omap_i2c_info = {
- .name = "omap_i2c",
+ .name = TYPE_OMAP_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(OMAPI2CState),
.class_init = omap_i2c_class_init,
@@ -485,7 +491,7 @@
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
{
- OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, SYS_BUS_DEVICE(omap_i2c));
+ OMAPI2CState *s = OMAP_I2C(omap_i2c);
return s->bus;
}
diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c
index 204dd3d..02e9f17 100644
--- a/hw/i2c/versatile_i2c.c
+++ b/hw/i2c/versatile_i2c.c
@@ -24,8 +24,13 @@
#include "hw/sysbus.h"
#include "bitbang_i2c.h"
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_VERSATILE_I2C "versatile_i2c"
+#define VERSATILE_I2C(obj) \
+ OBJECT_CHECK(VersatileI2CState, (obj), TYPE_VERSATILE_I2C)
+
+typedef struct VersatileI2CState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
bitbang_i2c_interface *bitbang;
int out;
@@ -72,16 +77,17 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int versatile_i2c_init(SysBusDevice *dev)
+static int versatile_i2c_init(SysBusDevice *sbd)
{
- VersatileI2CState *s = FROM_SYSBUS(VersatileI2CState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ VersatileI2CState *s = VERSATILE_I2C(dev);
i2c_bus *bus;
- bus = i2c_init_bus(&dev->qdev, "i2c");
+ bus = i2c_init_bus(dev, "i2c");
s->bitbang = bitbang_i2c_init(bus);
memory_region_init_io(&s->iomem, OBJECT(s), &versatile_i2c_ops, s,
"versatile_i2c", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
return 0;
}
@@ -93,7 +99,7 @@
}
static const TypeInfo versatile_i2c_info = {
- .name = "versatile_i2c",
+ .name = TYPE_VERSATILE_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(VersatileI2CState),
.class_init = versatile_i2c_class_init,
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 205d22e..45e6165 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -1,6 +1,7 @@
obj-$(CONFIG_KVM) += kvm/
obj-y += multiboot.o smbios.o
obj-y += pc.o pc_piix.o pc_q35.o
+obj-y += pc_sysfw.o
obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
obj-y += kvmvapic.o
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index 179b806..5609063 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -79,7 +79,7 @@
v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
s->count_shift = (v + 1) & 7;
- s->initial_count_load_time = qemu_get_clock_ns(vm_clock);
+ s->initial_count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
apic_next_timer(s, s->initial_count_load_time);
}
diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c
index c1f4094..20b6457 100644
--- a/hw/i386/kvm/i8254.c
+++ b/hw/i386/kvm/i8254.c
@@ -65,12 +65,12 @@
/*
* Measure the delta between CLOCK_MONOTONIC, the base used for
- * kvm_pit_channel_state::count_load_time, and vm_clock. Take the
+ * kvm_pit_channel_state::count_load_time, and QEMU_CLOCK_VIRTUAL. Take the
* minimum of several samples to filter out scheduling noise.
*/
clock_offset = INT64_MAX;
for (i = 0; i < CALIBRATION_ROUNDS; i++) {
- offset = qemu_get_clock_ns(vm_clock);
+ offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
clock_gettime(CLOCK_MONOTONIC, &ts);
offset -= ts.tv_nsec;
offset -= (int64_t)ts.tv_sec * 1000000000;
@@ -194,7 +194,7 @@
case 5:
if (sc->gate < val) {
/* restart counting on rising edge */
- sc->count_load_time = qemu_get_clock_ns(vm_clock);
+ sc->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
break;
}
diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c
index 688cb5c..f11a540 100644
--- a/hw/i386/kvm/ioapic.c
+++ b/hw/i386/kvm/ioapic.c
@@ -112,7 +112,7 @@
static void kvm_ioapic_reset(DeviceState *dev)
{
- IOAPICCommonState *s = DO_UPCAST(IOAPICCommonState, busdev.qdev, dev);
+ IOAPICCommonState *s = IOAPIC_COMMON(dev);
ioapic_reset_common(dev);
kvm_ioapic_put(s);
@@ -131,7 +131,7 @@
{
memory_region_init_reservation(&s->io_memory, NULL, "kvm-ioapic", 0x1000);
- qdev_init_gpio_in(&s->busdev.qdev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS);
+ qdev_init_gpio_in(DEVICE(s), kvm_ioapic_set_irq, IOAPIC_NUM_PINS);
}
static Property kvm_ioapic_properties[] = {
diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
index 73941b2..011764f 100644
--- a/hw/i386/kvm/pci-assign.c
+++ b/hw/i386/kvm/pci-assign.c
@@ -1855,6 +1855,7 @@
dc->props = assigned_dev_properties;
dc->vmsd = &vmstate_assigned_device;
dc->reset = reset_assigned_device;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->desc = "KVM-based PCI passthrough";
}
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index a4506bc..15beb80 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -456,7 +456,7 @@
void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip,
TPRAccess access)
{
- VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
+ VAPICROMState *s = VAPIC(dev);
X86CPU *cpu = X86_CPU(cs);
CPUX86State *env = &cpu->env;
@@ -508,7 +508,7 @@
static void vapic_reset(DeviceState *dev)
{
- VAPICROMState *s = DO_UPCAST(VAPICROMState, busdev.qdev, dev);
+ VAPICROMState *s = VAPIC(dev);
if (s->state == VAPIC_ACTIVE) {
s->state = VAPIC_STANDBY;
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 2a87563..3a620a1 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -55,6 +55,7 @@
#include "hw/acpi/acpi.h"
#include "hw/cpu/icc_bus.h"
#include "hw/boards.h"
+#include "hw/pci/pci_host.h"
/* debug PC/ISA interrupts */
//#define DEBUG_IRQ
@@ -75,8 +76,6 @@
#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
-#define IO_APIC_DEFAULT_ADDRESS 0xfec00000
-
#define E820_NR_ENTRIES 16
struct e820_entry {
@@ -913,20 +912,19 @@
X86CPU *cpu;
Error *local_err = NULL;
- cpu = cpu_x86_create(cpu_model, icc_bridge, errp);
- if (!cpu) {
- return cpu;
+ cpu = cpu_x86_create(cpu_model, icc_bridge, &local_err);
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ return NULL;
}
object_property_set_int(OBJECT(cpu), apic_id, "apic-id", &local_err);
object_property_set_bool(OBJECT(cpu), true, "realized", &local_err);
if (local_err) {
- if (cpu != NULL) {
- object_unref(OBJECT(cpu));
- cpu = NULL;
- }
error_propagate(errp, local_err);
+ object_unref(OBJECT(cpu));
+ cpu = NULL;
}
return cpu;
}
@@ -980,7 +978,7 @@
cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
icc_bridge, &error);
if (error) {
- fprintf(stderr, "%s\n", error_get_pretty(error));
+ error_report("%s", error_get_pretty(error));
error_free(error);
exit(1);
}
@@ -1005,15 +1003,27 @@
static void pc_fw_cfg_guest_info(PcGuestInfo *guest_info)
{
PcRomPciInfo *info;
+ Object *pci_info;
+ bool ambiguous = false;
+
if (!guest_info->has_pci_info || !guest_info->fw_cfg) {
return;
}
+ pci_info = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous);
+ g_assert(!ambiguous);
+ if (!pci_info) {
+ return;
+ }
info = g_malloc(sizeof *info);
- info->w32_min = cpu_to_le64(guest_info->pci_info.w32.begin);
- info->w32_max = cpu_to_le64(guest_info->pci_info.w32.end);
- info->w64_min = cpu_to_le64(guest_info->pci_info.w64.begin);
- info->w64_max = cpu_to_le64(guest_info->pci_info.w64.end);
+ info->w32_min = cpu_to_le64(object_property_get_int(pci_info,
+ PCI_HOST_PROP_PCI_HOLE_START, NULL));
+ info->w32_max = cpu_to_le64(object_property_get_int(pci_info,
+ PCI_HOST_PROP_PCI_HOLE_END, NULL));
+ info->w64_min = cpu_to_le64(object_property_get_int(pci_info,
+ PCI_HOST_PROP_PCI_HOLE64_START, NULL));
+ info->w64_max = cpu_to_le64(object_property_get_int(pci_info,
+ PCI_HOST_PROP_PCI_HOLE64_END, NULL));
/* Pass PCI hole info to guest via a side channel.
* Required so guest PCI enumeration does the right thing. */
fw_cfg_add_file(guest_info->fw_cfg, "etc/pci-info", info, sizeof *info);
@@ -1039,29 +1049,28 @@
PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
PcGuestInfo *guest_info = &guest_info_state->info;
- guest_info->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS;
- if (sizeof(hwaddr) == 4) {
- guest_info->pci_info.w64.begin = 0;
- guest_info->pci_info.w64.end = 0;
- } else {
- /*
- * BIOS does not set MTRR entries for the 64 bit window, so no need to
- * align address to power of two. Align address at 1G, this makes sure
- * it can be exactly covered with a PAT entry even when using huge
- * pages.
- */
- guest_info->pci_info.w64.begin =
- ROUND_UP((0x1ULL << 32) + above_4g_mem_size, 0x1ULL << 30);
- guest_info->pci_info.w64.end = guest_info->pci_info.w64.begin +
- (0x1ULL << 62);
- assert(guest_info->pci_info.w64.begin <= guest_info->pci_info.w64.end);
- }
-
guest_info_state->machine_done.notify = pc_guest_info_machine_done;
qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
return guest_info;
}
+void pc_init_pci64_hole(PcPciInfo *pci_info, uint64_t pci_hole64_start,
+ uint64_t pci_hole64_size)
+{
+ if ((sizeof(hwaddr) == 4) || (!pci_hole64_size)) {
+ return;
+ }
+ /*
+ * BIOS does not set MTRR entries for the 64 bit window, so no need to
+ * align address to power of two. Align address at 1G, this makes sure
+ * it can be exactly covered with a PAT entry even when using huge
+ * pages.
+ */
+ pci_info->w64.begin = ROUND_UP(pci_hole64_start, 0x1ULL << 30);
+ pci_info->w64.end = pci_info->w64.begin + pci_hole64_size;
+ assert(pci_info->w64.begin <= pci_info->w64.end);
+}
+
void pc_acpi_init(const char *default_dsdt)
{
char *filename;
@@ -1087,8 +1096,8 @@
acpi_table_add(opts, &err);
if (err) {
- fprintf(stderr, "WARNING: failed to load %s: %s\n", filename,
- error_get_pretty(err));
+ error_report("WARNING: failed to load %s: %s", filename,
+ error_get_pretty(err));
error_free(err);
}
g_free(arg);
@@ -1136,7 +1145,7 @@
/* Initialize PC system firmware */
- pc_system_firmware_init(rom_memory);
+ pc_system_firmware_init(rom_memory, guest_info->isapc_ram_fw);
option_rom_mr = g_malloc(sizeof(*option_rom_mr));
memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index b58c255..3c36a2a 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -25,6 +25,7 @@
#include <glib.h>
#include "hw/hw.h"
+#include "hw/loader.h"
#include "hw/i386/pc.h"
#include "hw/i386/apic.h"
#include "hw/pci/pci.h"
@@ -56,21 +57,16 @@
static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
-static bool has_pvpanic = true;
+static bool has_pvpanic;
static bool has_pci_info = true;
/* PC hardware initialisation */
-static void pc_init1(MemoryRegion *system_memory,
- MemoryRegion *system_io,
- ram_addr_t ram_size,
- const char *boot_device,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
- const char *cpu_model,
+static void pc_init1(QEMUMachineInitArgs *args,
int pci_enabled,
int kvmclock_enabled)
{
+ MemoryRegion *system_memory = get_system_memory();
+ MemoryRegion *system_io = get_system_io();
int i;
ram_addr_t below_4g_mem_size, above_4g_mem_size;
PCIBus *pci_bus;
@@ -102,19 +98,18 @@
object_property_add_child(qdev_get_machine(), "icc-bridge",
OBJECT(icc_bridge), NULL);
- pc_cpus_init(cpu_model, icc_bridge);
- pc_acpi_init("acpi-dsdt.aml");
+ pc_cpus_init(args->cpu_model, icc_bridge);
if (kvm_enabled() && kvmclock_enabled) {
kvmclock_create();
}
- if (ram_size >= 0xe0000000 ) {
- above_4g_mem_size = ram_size - 0xe0000000;
+ if (args->ram_size >= 0xe0000000) {
+ above_4g_mem_size = args->ram_size - 0xe0000000;
below_4g_mem_size = 0xe0000000;
} else {
above_4g_mem_size = 0;
- below_4g_mem_size = ram_size;
+ below_4g_mem_size = args->ram_size;
}
if (pci_enabled) {
@@ -128,20 +123,13 @@
guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
guest_info->has_pci_info = has_pci_info;
-
- /* Set PCI window size the way seabios has always done it. */
- /* Power of 2 so bios can cover it with a single MTRR */
- if (ram_size <= 0x80000000)
- guest_info->pci_info.w32.begin = 0x80000000;
- else if (ram_size <= 0xc0000000)
- guest_info->pci_info.w32.begin = 0xc0000000;
- else
- guest_info->pci_info.w32.begin = 0xe0000000;
+ guest_info->isapc_ram_fw = !pci_enabled;
/* allocate ram and load rom/bios */
if (!xen_enabled()) {
fw_cfg = pc_memory_init(system_memory,
- kernel_filename, kernel_cmdline, initrd_filename,
+ args->kernel_filename, args->kernel_cmdline,
+ args->initrd_filename,
below_4g_mem_size, above_4g_mem_size,
rom_memory, &ram_memory, guest_info);
}
@@ -157,13 +145,10 @@
if (pci_enabled) {
pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
- system_memory, system_io, ram_size,
+ system_memory, system_io, args->ram_size,
below_4g_mem_size,
0x100000000ULL - below_4g_mem_size,
- 0x100000000ULL + above_4g_mem_size,
- (sizeof(hwaddr) == 4
- ? 0
- : ((uint64_t)1 << 62)),
+ above_4g_mem_size,
pci_memory, ram_memory);
} else {
pci_bus = NULL;
@@ -219,7 +204,7 @@
}
}
- pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
+ pc_cmos_init(below_4g_mem_size, above_4g_mem_size, args->boot_device,
floppy, idebus[0], idebus[1], rtc_state);
if (pci_enabled && usb_enabled(false)) {
@@ -248,90 +233,91 @@
static void pc_init_pci(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- pc_init1(get_system_memory(),
- get_system_io(),
- ram_size, boot_device,
- kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model, 1, 1);
+ pc_init1(args, 1, 1);
+}
+
+static void pc_compat_1_6(QEMUMachineInitArgs *args)
+{
+ has_pci_info = false;
+ rom_file_in_ram = false;
+}
+
+static void pc_compat_1_5(QEMUMachineInitArgs *args)
+{
+ pc_compat_1_6(args);
+ has_pvpanic = true;
+}
+
+static void pc_compat_1_4(QEMUMachineInitArgs *args)
+{
+ pc_compat_1_5(args);
+ has_pvpanic = false;
+ x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
+ x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
+}
+
+static void pc_compat_1_3(QEMUMachineInitArgs *args)
+{
+ pc_compat_1_4(args);
+ enable_compat_apic_id_mode();
+}
+
+/* PC compat function for pc-0.14 to pc-1.2 */
+static void pc_compat_1_2(QEMUMachineInitArgs *args)
+{
+ pc_compat_1_3(args);
+ disable_kvm_pv_eoi();
+}
+
+static void pc_init_pci_1_6(QEMUMachineInitArgs *args)
+{
+ pc_compat_1_6(args);
+ pc_init_pci(args);
}
static void pc_init_pci_1_5(QEMUMachineInitArgs *args)
{
- has_pci_info = false;
+ pc_compat_1_5(args);
pc_init_pci(args);
}
static void pc_init_pci_1_4(QEMUMachineInitArgs *args)
{
- has_pvpanic = false;
- x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
- pc_init_pci_1_5(args);
+ pc_compat_1_4(args);
+ pc_init_pci(args);
}
static void pc_init_pci_1_3(QEMUMachineInitArgs *args)
{
- enable_compat_apic_id_mode();
- pc_init_pci_1_4(args);
+ pc_compat_1_3(args);
+ pc_init_pci(args);
}
-/* PC machine init function for pc-1.1 to pc-1.2 */
+/* PC machine init function for pc-0.14 to pc-1.2 */
static void pc_init_pci_1_2(QEMUMachineInitArgs *args)
{
- disable_kvm_pv_eoi();
- pc_init_pci_1_3(args);
-}
-
-/* PC machine init function for pc-0.14 to pc-1.0 */
-static void pc_init_pci_1_0(QEMUMachineInitArgs *args)
-{
- pc_init_pci_1_2(args);
+ pc_compat_1_2(args);
+ pc_init_pci(args);
}
/* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */
static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- has_pvpanic = false;
has_pci_info = false;
disable_kvm_pv_eoi();
enable_compat_apic_id_mode();
- pc_init1(get_system_memory(),
- get_system_io(),
- ram_size, boot_device,
- kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model, 1, 0);
+ pc_init1(args, 1, 0);
}
static void pc_init_isa(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- has_pvpanic = false;
has_pci_info = false;
- if (cpu_model == NULL)
- cpu_model = "486";
+ if (!args->cpu_model) {
+ args->cpu_model = "486";
+ }
disable_kvm_pv_eoi();
enable_compat_apic_id_mode();
- pc_init1(get_system_memory(),
- get_system_io(),
- ram_size, boot_device,
- kernel_filename, kernel_cmdline,
- initrd_filename, cpu_model, 0, 1);
+ pc_init1(args, 0, 1);
}
#ifdef CONFIG_XEN
@@ -352,7 +338,7 @@
.name = "pc-i440fx-1.6",
.alias = "pc",
.desc = "Standard PC (i440FX + PIIX, 1996)",
- .init = pc_init_pci,
+ .init = pc_init_pci_1_6,
.hot_add_cpu = pc_hot_add_cpu,
.max_cpus = 255,
.is_default = 1,
@@ -503,10 +489,6 @@
#define PC_COMPAT_1_0 \
PC_COMPAT_1_1,\
{\
- .driver = "pc-sysfw",\
- .property = "rom_only",\
- .value = stringify(1),\
- }, {\
.driver = TYPE_ISA_FDC,\
.property = "check_media_rate",\
.value = "off",\
@@ -527,7 +509,7 @@
static QEMUMachine pc_machine_v1_0 = {
.name = "pc-1.0",
.desc = "Standard PC",
- .init = pc_init_pci_1_0,
+ .init = pc_init_pci_1_2,
.max_cpus = 255,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_0,
@@ -543,7 +525,7 @@
static QEMUMachine pc_machine_v0_15 = {
.name = "pc-0.15",
.desc = "Standard PC",
- .init = pc_init_pci_1_0,
+ .init = pc_init_pci_1_2,
.max_cpus = 255,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_0_15,
@@ -576,7 +558,7 @@
static QEMUMachine pc_machine_v0_14 = {
.name = "pc-0.14",
.desc = "Standard PC",
- .init = pc_init_pci_1_0,
+ .init = pc_init_pci_1_2,
.max_cpus = 255,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_0_14,
@@ -753,16 +735,6 @@
.init = pc_init_isa,
.max_cpus = 1,
.compat_props = (GlobalProperty[]) {
- {
- .driver = "pc-sysfw",
- .property = "rom_only",
- .value = stringify(1),
- },
- {
- .driver = "pc-sysfw",
- .property = "isapc_ram_fw",
- .value = stringify(1),
- },
{ /* end of list */ }
},
DEFAULT_MACHINE_OPTIONS,
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 0b1d2e3..198c785 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -28,6 +28,7 @@
* THE SOFTWARE.
*/
#include "hw/hw.h"
+#include "hw/loader.h"
#include "sysemu/arch_init.h"
#include "hw/i2c/smbus.h"
#include "hw/boards.h"
@@ -46,18 +47,12 @@
/* ICH9 AHCI has 6 ports */
#define MAX_SATA_PORTS 6
-static bool has_pvpanic = true;
+static bool has_pvpanic;
static bool has_pci_info = true;
/* PC hardware initialisation */
static void pc_q35_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
ram_addr_t below_4g_mem_size, above_4g_mem_size;
Q35PCIHost *q35_host;
PCIHostState *phb;
@@ -85,17 +80,17 @@
object_property_add_child(qdev_get_machine(), "icc-bridge",
OBJECT(icc_bridge), NULL);
- pc_cpus_init(cpu_model, icc_bridge);
+ pc_cpus_init(args->cpu_model, icc_bridge);
pc_acpi_init("q35-acpi-dsdt.aml");
kvmclock_create();
- if (ram_size >= 0xb0000000) {
- above_4g_mem_size = ram_size - 0xb0000000;
+ if (args->ram_size >= 0xb0000000) {
+ above_4g_mem_size = args->ram_size - 0xb0000000;
below_4g_mem_size = 0xb0000000;
} else {
above_4g_mem_size = 0;
- below_4g_mem_size = ram_size;
+ below_4g_mem_size = args->ram_size;
}
/* pci enabled */
@@ -110,11 +105,14 @@
guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
guest_info->has_pci_info = has_pci_info;
+ guest_info->isapc_ram_fw = false;
/* allocate ram and load rom/bios */
if (!xen_enabled()) {
- pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline,
- initrd_filename, below_4g_mem_size, above_4g_mem_size,
+ pc_memory_init(get_system_memory(),
+ args->kernel_filename, args->kernel_cmdline,
+ args->initrd_filename,
+ below_4g_mem_size, above_4g_mem_size,
rom_memory, &ram_memory, guest_info);
}
@@ -131,6 +129,7 @@
/* create pci host bus */
q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));
+ object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host), NULL);
q35_host->mch.ram_memory = ram_memory;
q35_host->mch.pci_address_space = pci_memory;
q35_host->mch.system_memory = get_system_memory();
@@ -201,7 +200,7 @@
0xb100),
8, NULL, 0);
- pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
+ pc_cmos_init(below_4g_mem_size, above_4g_mem_size, args->boot_device,
floppy, idebus[0], idebus[1], rtc_state);
/* the rest devices to which pci devfn is automatically assigned */
@@ -216,24 +215,49 @@
}
}
-static void pc_q35_init_1_5(QEMUMachineInitArgs *args)
+static void pc_compat_1_6(QEMUMachineInitArgs *args)
{
has_pci_info = false;
+ rom_file_in_ram = false;
+}
+
+static void pc_compat_1_5(QEMUMachineInitArgs *args)
+{
+ pc_compat_1_6(args);
+ has_pvpanic = true;
+}
+
+static void pc_compat_1_4(QEMUMachineInitArgs *args)
+{
+ pc_compat_1_5(args);
+ has_pvpanic = false;
+ x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
+ x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
+}
+
+static void pc_q35_init_1_6(QEMUMachineInitArgs *args)
+{
+ pc_compat_1_6(args);
+ pc_q35_init(args);
+}
+
+static void pc_q35_init_1_5(QEMUMachineInitArgs *args)
+{
+ pc_compat_1_5(args);
pc_q35_init(args);
}
static void pc_q35_init_1_4(QEMUMachineInitArgs *args)
{
- has_pvpanic = false;
- x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
- pc_q35_init_1_5(args);
+ pc_compat_1_4(args);
+ pc_q35_init(args);
}
static QEMUMachine pc_q35_machine_v1_6 = {
.name = "pc-q35-1.6",
.alias = "q35",
.desc = "Standard PC (Q35 + ICH9, 2009)",
- .init = pc_q35_init,
+ .init = pc_q35_init_1_6,
.hot_add_cpu = pc_hot_add_cpu,
.max_cpus = 255,
DEFAULT_MACHINE_OPTIONS,
diff --git a/hw/block/pc_sysfw.c b/hw/i386/pc_sysfw.c
similarity index 62%
rename from hw/block/pc_sysfw.c
rename to hw/i386/pc_sysfw.c
index 0669410..8246a1b 100644
--- a/hw/block/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -38,7 +38,6 @@
typedef struct PcSysFwDevice {
SysBusDevice busdev;
- uint8_t rom_only;
uint8_t isapc_ram_fw;
} PcSysFwDevice;
@@ -76,39 +75,6 @@
memory_region_set_readonly(isa_bios, true);
}
-static void pc_fw_add_pflash_drv(void)
-{
- QemuOpts *opts;
- QEMUMachine *machine;
- char *filename;
-
- if (bios_name == NULL) {
- bios_name = BIOS_FILENAME;
- }
- filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
- if (!filename) {
- error_report("Can't open BIOS image %s", bios_name);
- exit(1);
- }
-
- opts = drive_add(IF_PFLASH, -1, filename, "readonly=on");
-
- g_free(filename);
-
- if (opts == NULL) {
- return;
- }
-
- machine = find_default_machine();
- if (machine == NULL) {
- return;
- }
-
- if (!drive_init(opts, machine->block_default_type)) {
- qemu_opts_del(opts);
- }
-}
-
static void pc_system_flash_init(MemoryRegion *rom_memory,
DriveInfo *pflash_drv)
{
@@ -199,109 +165,24 @@
bios);
}
-/*
- * Bug-compatible flash vs. ROM selection enabled?
- * A few older machines enable this.
- */
-bool pc_sysfw_flash_vs_rom_bug_compatible;
-
-void pc_system_firmware_init(MemoryRegion *rom_memory)
+void pc_system_firmware_init(MemoryRegion *rom_memory, bool isapc_ram_fw)
{
DriveInfo *pflash_drv;
- PcSysFwDevice *sysfw_dev;
-
- /*
- * TODO This device exists only so that users can switch between
- * use of flash and ROM for the BIOS. The ability to switch was
- * created because flash doesn't work with KVM. Once it does, we
- * should drop this device.
- */
- sysfw_dev = (PcSysFwDevice*) qdev_create(NULL, "pc-sysfw");
-
- qdev_init_nofail(DEVICE(sysfw_dev));
pflash_drv = drive_get(IF_PFLASH, 0, 0);
- if (pc_sysfw_flash_vs_rom_bug_compatible) {
- /*
- * This is a Bad Idea, because it makes enabling/disabling KVM
- * guest-visible. Do it only in bug-compatibility mode.
- */
- if (kvm_enabled()) {
- if (pflash_drv != NULL) {
- fprintf(stderr, "qemu: pflash cannot be used with kvm enabled\n");
- exit(1);
- } else {
- /* In old pc_sysfw_flash_vs_rom_bug_compatible mode, we assume
- * that KVM cannot execute from device memory. In this case, we
- * use old rom based firmware initialization for KVM. But, since
- * this is different from non-kvm mode, this behavior is
- * undesirable */
- sysfw_dev->rom_only = 1;
- }
- }
- } else if (pflash_drv == NULL) {
+ if (isapc_ram_fw || pflash_drv == NULL) {
/* When a pflash drive is not found, use rom-mode */
- sysfw_dev->rom_only = 1;
- } else if (kvm_enabled() && !kvm_readonly_mem_enabled()) {
+ old_pc_system_rom_init(rom_memory, isapc_ram_fw);
+ return;
+ }
+
+ if (kvm_enabled() && !kvm_readonly_mem_enabled()) {
/* Older KVM cannot execute from device memory. So, flash memory
* cannot be used unless the readonly memory kvm capability is present. */
fprintf(stderr, "qemu: pflash with kvm requires KVM readonly memory support\n");
exit(1);
}
- /* If rom-mode is active, use the old pc system rom initialization. */
- if (sysfw_dev->rom_only) {
- old_pc_system_rom_init(rom_memory, sysfw_dev->isapc_ram_fw);
- return;
- }
-
- /* If a pflash drive is not found, then create one using
- the bios filename. */
- if (pflash_drv == NULL) {
- pc_fw_add_pflash_drv();
- pflash_drv = drive_get(IF_PFLASH, 0, 0);
- }
-
- if (pflash_drv != NULL) {
- pc_system_flash_init(rom_memory, pflash_drv);
- } else {
- fprintf(stderr, "qemu: PC system firmware (pflash) not available\n");
- exit(1);
- }
+ pc_system_flash_init(rom_memory, pflash_drv);
}
-
-static Property pcsysfw_properties[] = {
- DEFINE_PROP_UINT8("isapc_ram_fw", PcSysFwDevice, isapc_ram_fw, 0),
- DEFINE_PROP_UINT8("rom_only", PcSysFwDevice, rom_only, 0),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static int pcsysfw_init(DeviceState *dev)
-{
- return 0;
-}
-
-static void pcsysfw_class_init (ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS (klass);
-
- dc->desc = "PC System Firmware";
- dc->init = pcsysfw_init;
- dc->props = pcsysfw_properties;
-}
-
-static const TypeInfo pcsysfw_info = {
- .name = "pc-sysfw",
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof (PcSysFwDevice),
- .class_init = pcsysfw_class_init,
-};
-
-static void pcsysfw_register (void)
-{
- type_register_static (&pcsysfw_info);
-}
-
-type_init (pcsysfw_register);
-
diff --git a/hw/i386/xen_domainbuild.c b/hw/i386/xen_domainbuild.c
index 4e2cf95..c0ab753 100644
--- a/hw/i386/xen_domainbuild.c
+++ b/hw/i386/xen_domainbuild.c
@@ -148,7 +148,7 @@
goto quit;
}
- qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
+ timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
return;
quit:
@@ -290,8 +290,8 @@
goto err;
}
- xen_poll = qemu_new_timer_ms(rt_clock, xen_domain_poll, NULL);
- qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
+ xen_poll = timer_new_ms(QEMU_CLOCK_REALTIME, xen_domain_poll, NULL);
+ timer_mod(xen_poll, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
return 0;
err:
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 419adde..bba150f 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1338,6 +1338,7 @@
dc->vmsd = &vmstate_sysbus_ahci;
dc->props = sysbus_ahci_properties;
dc->reset = sysbus_ahci_reset;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo sysbus_ahci_info = {
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 33be386..d6ef799 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -127,7 +127,7 @@
unsigned size)
{
BMDMAState *bm = opaque;
- PCIIDEState *pci_dev = bm->pci_dev;
+ PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev);
uint32_t val;
if (size != 1) {
@@ -139,16 +139,16 @@
val = bm->cmd;
break;
case 1:
- val = pci_dev->dev.config[MRDMODE];
+ val = pci_dev->config[MRDMODE];
break;
case 2:
val = bm->status;
break;
case 3:
- if (bm == &pci_dev->bmdma[0]) {
- val = pci_dev->dev.config[UDIDETCR0];
+ if (bm == &bm->pci_dev->bmdma[0]) {
+ val = pci_dev->config[UDIDETCR0];
} else {
- val = pci_dev->dev.config[UDIDETCR1];
+ val = pci_dev->config[UDIDETCR1];
}
break;
default:
@@ -165,7 +165,7 @@
uint64_t val, unsigned size)
{
BMDMAState *bm = opaque;
- PCIIDEState *pci_dev = bm->pci_dev;
+ PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev);
if (size != 1) {
return;
@@ -179,18 +179,19 @@
bmdma_cmd_writeb(bm, val);
break;
case 1:
- pci_dev->dev.config[MRDMODE] =
- (pci_dev->dev.config[MRDMODE] & ~0x30) | (val & 0x30);
- cmd646_update_irq(pci_dev);
+ pci_dev->config[MRDMODE] =
+ (pci_dev->config[MRDMODE] & ~0x30) | (val & 0x30);
+ cmd646_update_irq(bm->pci_dev);
break;
case 2:
bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
break;
case 3:
- if (bm == &pci_dev->bmdma[0])
- pci_dev->dev.config[UDIDETCR0] = val;
- else
- pci_dev->dev.config[UDIDETCR1] = val;
+ if (bm == &bm->pci_dev->bmdma[0]) {
+ pci_dev->config[UDIDETCR0] = val;
+ } else {
+ pci_dev->config[UDIDETCR1] = val;
+ }
break;
}
}
@@ -222,25 +223,29 @@
registers */
static void cmd646_update_irq(PCIIDEState *d)
{
+ PCIDevice *pd = PCI_DEVICE(d);
int pci_level;
- pci_level = ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH0) &&
- !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH0)) ||
- ((d->dev.config[MRDMODE] & MRDMODE_INTR_CH1) &&
- !(d->dev.config[MRDMODE] & MRDMODE_BLK_CH1));
- qemu_set_irq(d->dev.irq[0], pci_level);
+
+ pci_level = ((pd->config[MRDMODE] & MRDMODE_INTR_CH0) &&
+ !(pd->config[MRDMODE] & MRDMODE_BLK_CH0)) ||
+ ((pd->config[MRDMODE] & MRDMODE_INTR_CH1) &&
+ !(pd->config[MRDMODE] & MRDMODE_BLK_CH1));
+ qemu_set_irq(pd->irq[0], pci_level);
}
/* the PCI irq level is the logical OR of the two channels */
static void cmd646_set_irq(void *opaque, int channel, int level)
{
PCIIDEState *d = opaque;
+ PCIDevice *pd = PCI_DEVICE(d);
int irq_mask;
irq_mask = MRDMODE_INTR_CH0 << channel;
- if (level)
- d->dev.config[MRDMODE] |= irq_mask;
- else
- d->dev.config[MRDMODE] &= ~irq_mask;
+ if (level) {
+ pd->config[MRDMODE] |= irq_mask;
+ } else {
+ pd->config[MRDMODE] &= ~irq_mask;
+ }
cmd646_update_irq(d);
}
@@ -257,8 +262,8 @@
/* CMD646 PCI IDE controller */
static int pci_cmd646_ide_initfn(PCIDevice *dev)
{
- PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
- uint8_t *pci_conf = d->dev.config;
+ PCIIDEState *d = PCI_IDE(dev);
+ uint8_t *pci_conf = dev->config;
qemu_irq *irq;
int i;
@@ -284,7 +289,7 @@
irq = qemu_allocate_irqs(cmd646_set_irq, d, 2);
for (i = 0; i < 2; i++) {
- ide_bus_new(&d->bus[i], &d->dev.qdev, i, 2);
+ ide_bus_new(&d->bus[i], DEVICE(dev), i, 2);
ide_init2(&d->bus[i], irq[i]);
bmdma_init(&d->bus[i], &d->bmdma[i], d);
@@ -293,14 +298,14 @@
&d->bmdma[i].dma);
}
- vmstate_register(&dev->qdev, 0, &vmstate_ide_pci, d);
+ vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
qemu_register_reset(cmd646_reset, d);
return 0;
}
static void pci_cmd646_ide_exitfn(PCIDevice *dev)
{
- PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
+ PCIIDEState *d = PCI_IDE(dev);
unsigned i;
for (i = 0; i < 2; ++i) {
@@ -347,8 +352,7 @@
static const TypeInfo cmd646_ide_info = {
.name = "cmd646-ide",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIIDEState),
+ .parent = TYPE_PCI_IDE,
.class_init = cmd646_ide_class_init,
};
diff --git a/hw/ide/core.c b/hw/ide/core.c
index a73af72..399b1ba 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -768,8 +768,8 @@
that at the expense of slower write performances. Use this
option _only_ to install Windows 2000. You must disable it
for normal use. */
- qemu_mod_timer(s->sector_write_timer,
- qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / 1000));
+ timer_mod(s->sector_write_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (get_ticks_per_sec() / 1000));
} else {
ide_set_irq(s->bus);
}
@@ -2163,7 +2163,7 @@
s->smart_selftest_data = qemu_blockalign(s->bs, 512);
memset(s->smart_selftest_data, 0, 512);
- s->sector_write_timer = qemu_new_timer_ns(vm_clock,
+ s->sector_write_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
ide_sector_write_timer_cb, s);
}
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 4eb5488..bff952b 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -160,6 +160,7 @@
k->class_id = PCI_CLASS_STORAGE_SATA;
dc->vmsd = &vmstate_ich9_ahci;
dc->reset = pci_ich9_reset;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo ich_ahci_info = {
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 7243c82..bbc8c6b 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -118,6 +118,7 @@
dc->fw_name = "ide";
dc->reset = isa_ide_reset;
dc->props = isa_ide_properties;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo isa_ide_info = {
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 38ad924..ef4ba2b 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -131,7 +131,7 @@
int sector_num = (s->lba << 2) + (s->io_buffer_index >> 9);
int nsector = io->len >> 9;
- MACIO_DPRINTF("precopying unaligned %d bytes to %#lx\n",
+ MACIO_DPRINTF("precopying unaligned %d bytes to %#" HWADDR_PRIx "\n",
unaligned, io->addr + io->len - unaligned);
bdrv_read(s->bs, sector_num + nsector, io->remainder, 1);
@@ -212,14 +212,15 @@
s->nsector -= n;
}
- MACIO_DPRINTF("remainder: %d io->len: %d nsector: %d sector_num: %ld\n",
+ MACIO_DPRINTF("remainder: %d io->len: %d nsector: %d "
+ "sector_num: %" PRId64 "\n",
io->remainder_len, io->len, s->nsector, sector_num);
if (io->remainder_len && io->len) {
/* guest wants the rest of its previous transfer */
int remainder_len = MIN(io->remainder_len, io->len);
uint8_t *p = &io->remainder[0x200 - remainder_len];
- MACIO_DPRINTF("copying remainder %d bytes at %#lx\n",
+ MACIO_DPRINTF("copying remainder %d bytes at %#" HWADDR_PRIx "\n",
remainder_len, io->addr);
switch (s->dma_cmd) {
@@ -261,7 +262,7 @@
if (unaligned) {
int nsector = io->len >> 9;
- MACIO_DPRINTF("precopying unaligned %d bytes to %#lx\n",
+ MACIO_DPRINTF("precopying unaligned %d bytes to %#" HWADDR_PRIx "\n",
unaligned, io->addr + io->len - unaligned);
switch (s->dma_cmd) {
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 635a364..91151fc 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -56,13 +56,14 @@
{
BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
IDEState *s = bmdma_active_if(bm);
+ PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev);
struct {
uint32_t addr;
uint32_t size;
} prd;
int l, len;
- pci_dma_sglist_init(&s->sg, &bm->pci_dev->dev,
+ pci_dma_sglist_init(&s->sg, pci_dev,
s->nsector / (BMDMA_PAGE_SIZE / 512) + 1);
s->io_buffer_size = 0;
for(;;) {
@@ -71,7 +72,7 @@
if (bm->cur_prd_last ||
(bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
return s->io_buffer_size != 0;
- pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, &prd, 8);
+ pci_dma_read(pci_dev, bm->cur_addr, &prd, 8);
bm->cur_addr += 8;
prd.addr = le32_to_cpu(prd.addr);
prd.size = le32_to_cpu(prd.size);
@@ -98,6 +99,7 @@
{
BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma);
IDEState *s = bmdma_active_if(bm);
+ PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev);
struct {
uint32_t addr;
uint32_t size;
@@ -113,7 +115,7 @@
if (bm->cur_prd_last ||
(bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE)
return 0;
- pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, &prd, 8);
+ pci_dma_read(pci_dev, bm->cur_addr, &prd, 8);
bm->cur_addr += 8;
prd.addr = le32_to_cpu(prd.addr);
prd.size = le32_to_cpu(prd.size);
@@ -128,10 +130,10 @@
l = bm->cur_prd_len;
if (l > 0) {
if (is_write) {
- pci_dma_write(&bm->pci_dev->dev, bm->cur_prd_addr,
+ pci_dma_write(pci_dev, bm->cur_prd_addr,
s->io_buffer + s->io_buffer_index, l);
} else {
- pci_dma_read(&bm->pci_dev->dev, bm->cur_prd_addr,
+ pci_dma_read(pci_dev, bm->cur_prd_addr,
s->io_buffer + s->io_buffer_index, l);
}
bm->cur_prd_addr += l;
@@ -480,7 +482,7 @@
.minimum_version_id_old = 0,
.post_load = ide_pci_post_load,
.fields = (VMStateField []) {
- VMSTATE_PCI_DEVICE(dev, PCIIDEState),
+ VMSTATE_PCI_DEVICE(parent_obj, PCIIDEState),
VMSTATE_STRUCT_ARRAY(bmdma, PCIIDEState, 2, 0,
vmstate_bmdma, BMDMAState),
VMSTATE_IDE_BUS_ARRAY(bus, PCIIDEState, 2),
@@ -492,7 +494,7 @@
void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table)
{
- PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
+ PCIIDEState *d = PCI_IDE(dev);
static const int bus[4] = { 0, 0, 1, 1 };
static const int unit[4] = { 0, 1, 0, 1 };
int i;
@@ -531,3 +533,17 @@
bus->irq = *irq;
bm->pci_dev = d;
}
+
+static const TypeInfo pci_ide_type_info = {
+ .name = TYPE_PCI_IDE,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIIDEState),
+ .abstract = true,
+};
+
+static void pci_ide_register_types(void)
+{
+ type_register_static(&pci_ide_type_info);
+}
+
+type_init(pci_ide_register_types)
diff --git a/hw/ide/pci.h b/hw/ide/pci.h
index a694e54..2428275 100644
--- a/hw/ide/pci.h
+++ b/hw/ide/pci.h
@@ -37,8 +37,14 @@
struct PCIIDEState *pci_dev;
} CMD646BAR;
+#define TYPE_PCI_IDE "pci-ide"
+#define PCI_IDE(obj) OBJECT_CHECK(PCIIDEState, (obj), TYPE_PCI_IDE)
+
typedef struct PCIIDEState {
- PCIDevice dev;
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+
IDEBus bus[2];
BMDMAState bmdma[2];
uint32_t secondary; /* used only for cmd646 */
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 58532fe..e6e6c0b 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -106,7 +106,8 @@
static void piix3_reset(void *opaque)
{
PCIIDEState *d = opaque;
- uint8_t *pci_conf = d->dev.config;
+ PCIDevice *pd = PCI_DEVICE(d);
+ uint8_t *pci_conf = pd->config;
int i;
for (i = 0; i < 2; i++) {
@@ -135,7 +136,7 @@
int i;
for (i = 0; i < 2; i++) {
- ide_bus_new(&d->bus[i], &d->dev.qdev, i, 2);
+ ide_bus_new(&d->bus[i], DEVICE(d), i, 2);
ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
port_info[i].iobase2);
ide_init2(&d->bus[i], isa_get_irq(NULL, port_info[i].isairq));
@@ -149,17 +150,17 @@
static int pci_piix_ide_initfn(PCIDevice *dev)
{
- PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
- uint8_t *pci_conf = d->dev.config;
+ PCIIDEState *d = PCI_IDE(dev);
+ uint8_t *pci_conf = dev->config;
pci_conf[PCI_CLASS_PROG] = 0x80; // legacy ATA mode
qemu_register_reset(piix3_reset, d);
bmdma_setup_bar(d);
- pci_register_bar(&d->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
+ pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
- vmstate_register(&d->dev.qdev, 0, &vmstate_ide_pci, d);
+ vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
pci_piix_init_ports(d);
@@ -168,13 +169,11 @@
static int pci_piix3_xen_ide_unplug(DeviceState *dev)
{
- PCIDevice *pci_dev;
PCIIDEState *pci_ide;
DriveInfo *di;
int i = 0;
- pci_dev = DO_UPCAST(PCIDevice, qdev, dev);
- pci_ide = DO_UPCAST(PCIIDEState, dev, pci_dev);
+ pci_ide = PCI_IDE(dev);
for (; i < 3; i++) {
di = drive_get_by_index(IF_IDE, i);
@@ -188,7 +187,7 @@
drive_put_ref(di);
}
}
- qdev_reset_all(&(pci_ide->dev.qdev));
+ qdev_reset_all(DEVICE(dev));
return 0;
}
@@ -203,7 +202,7 @@
static void pci_piix_ide_exitfn(PCIDevice *dev)
{
- PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
+ PCIIDEState *d = PCI_IDE(dev);
unsigned i;
for (i = 0; i < 2; ++i) {
@@ -248,13 +247,13 @@
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
k->class_id = PCI_CLASS_STORAGE_IDE;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->no_user = 1;
}
static const TypeInfo piix3_ide_info = {
.name = "piix3-ide",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIIDEState),
+ .parent = TYPE_PCI_IDE,
.class_init = piix3_ide_class_init,
};
@@ -267,14 +266,14 @@
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
k->class_id = PCI_CLASS_STORAGE_IDE;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->no_user = 1;
dc->unplug = pci_piix3_xen_ide_unplug;
}
static const TypeInfo piix3_ide_xen_info = {
.name = "piix3-ide-xen",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIIDEState),
+ .parent = TYPE_PCI_IDE,
.class_init = piix3_ide_xen_class_init,
};
@@ -289,13 +288,13 @@
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_82371AB;
k->class_id = PCI_CLASS_STORAGE_IDE;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->no_user = 1;
}
static const TypeInfo piix4_ide_info = {
.name = "piix4-ide",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIIDEState),
+ .parent = TYPE_PCI_IDE,
.class_init = piix4_ide_class_init,
};
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 6a272b0..1d84e15 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -282,6 +282,7 @@
{
DeviceClass *k = DEVICE_CLASS(klass);
k->init = ide_qdev_init;
+ set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
k->bus_type = TYPE_IDE_BUS;
k->props = ide_props;
}
diff --git a/hw/ide/via.c b/hw/ide/via.c
index 5a83191..e5fb297 100644
--- a/hw/ide/via.c
+++ b/hw/ide/via.c
@@ -108,7 +108,8 @@
static void via_reset(void *opaque)
{
PCIIDEState *d = opaque;
- uint8_t *pci_conf = d->dev.config;
+ PCIDevice *pd = PCI_DEVICE(d);
+ uint8_t *pci_conf = pd->config;
int i;
for (i = 0; i < 2; i++) {
@@ -158,7 +159,7 @@
int i;
for (i = 0; i < 2; i++) {
- ide_bus_new(&d->bus[i], &d->dev.qdev, i, 2);
+ ide_bus_new(&d->bus[i], DEVICE(d), i, 2);
ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
port_info[i].iobase2);
ide_init2(&d->bus[i], isa_get_irq(NULL, port_info[i].isairq));
@@ -173,17 +174,17 @@
/* via ide func */
static int vt82c686b_ide_initfn(PCIDevice *dev)
{
- PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
- uint8_t *pci_conf = d->dev.config;
+ PCIIDEState *d = PCI_IDE(dev);
+ uint8_t *pci_conf = dev->config;
pci_config_set_prog_interface(pci_conf, 0x8a); /* legacy ATA mode */
pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0);
qemu_register_reset(via_reset, d);
bmdma_setup_bar(d);
- pci_register_bar(&d->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
+ pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
- vmstate_register(&dev->qdev, 0, &vmstate_ide_pci, d);
+ vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
vt82c686b_init_ports(d);
@@ -192,7 +193,7 @@
static void vt82c686b_ide_exitfn(PCIDevice *dev)
{
- PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);
+ PCIIDEState *d = PCI_IDE(dev);
unsigned i;
for (i = 0; i < 2; ++i) {
@@ -223,13 +224,13 @@
k->device_id = PCI_DEVICE_ID_VIA_IDE;
k->revision = 0x06;
k->class_id = PCI_CLASS_STORAGE_IDE;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->no_user = 1;
}
static const TypeInfo via_ide_info = {
.name = "via-ide",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIIDEState),
+ .parent = TYPE_PCI_IDE,
.class_init = via_ide_class_init,
};
diff --git a/hw/input/hid.c b/hw/input/hid.c
index 14b3125..bb0fa6a 100644
--- a/hw/input/hid.c
+++ b/hw/input/hid.c
@@ -85,8 +85,8 @@
static void hid_del_idle_timer(HIDState *hs)
{
if (hs->idle_timer) {
- qemu_del_timer(hs->idle_timer);
- qemu_free_timer(hs->idle_timer);
+ timer_del(hs->idle_timer);
+ timer_free(hs->idle_timer);
hs->idle_timer = NULL;
}
}
@@ -94,12 +94,12 @@
void hid_set_next_idle(HIDState *hs)
{
if (hs->idle) {
- uint64_t expire_time = qemu_get_clock_ns(vm_clock) +
+ uint64_t expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
get_ticks_per_sec() * hs->idle * 4 / 1000;
if (!hs->idle_timer) {
- hs->idle_timer = qemu_new_timer_ns(vm_clock, hid_idle_timer, hs);
+ hs->idle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, hid_idle_timer, hs);
}
- qemu_mod_timer_ns(hs->idle_timer, expire_time);
+ timer_mod_ns(hs->idle_timer, expire_time);
} else {
hid_del_idle_timer(hs);
}
diff --git a/hw/input/lm832x.c b/hw/input/lm832x.c
index bacbeb2..f583cf0 100644
--- a/hw/input/lm832x.c
+++ b/hw/input/lm832x.c
@@ -365,7 +365,7 @@
break;
}
- qemu_del_timer(s->pwm.tm[(value & 3) - 1]);
+ timer_del(s->pwm.tm[(value & 3) - 1]);
break;
case LM832x_GENERAL_ERROR:
@@ -463,9 +463,9 @@
LM823KbdState *s = FROM_I2C_SLAVE(LM823KbdState, i2c);
s->model = 0x8323;
- s->pwm.tm[0] = qemu_new_timer_ns(vm_clock, lm_kbd_pwm0_tick, s);
- s->pwm.tm[1] = qemu_new_timer_ns(vm_clock, lm_kbd_pwm1_tick, s);
- s->pwm.tm[2] = qemu_new_timer_ns(vm_clock, lm_kbd_pwm2_tick, s);
+ s->pwm.tm[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, lm_kbd_pwm0_tick, s);
+ s->pwm.tm[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, lm_kbd_pwm1_tick, s);
+ s->pwm.tm[2] = timer_new_ns(QEMU_CLOCK_VIRTUAL, lm_kbd_pwm2_tick, s);
qdev_init_gpio_out(&i2c->qdev, &s->nirq, 1);
lm_kbd_reset(s);
diff --git a/hw/input/milkymist-softusb.c b/hw/input/milkymist-softusb.c
index 942cb79..ecde33c 100644
--- a/hw/input/milkymist-softusb.c
+++ b/hw/input/milkymist-softusb.c
@@ -44,8 +44,13 @@
#define COMLOC_KEVT_PRODUCE 0x1142
#define COMLOC_KEVT_BASE 0x1143
+#define TYPE_MILKYMIST_SOFTUSB "milkymist-softusb"
+#define MILKYMIST_SOFTUSB(obj) \
+ OBJECT_CHECK(MilkymistSoftUsbState, (obj), TYPE_MILKYMIST_SOFTUSB)
+
struct MilkymistSoftUsbState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
HIDState hid_kbd;
HIDState hid_mouse;
@@ -242,8 +247,7 @@
static void milkymist_softusb_reset(DeviceState *d)
{
- MilkymistSoftUsbState *s =
- container_of(d, MilkymistSoftUsbState, busdev.qdev);
+ MilkymistSoftUsbState *s = MILKYMIST_SOFTUSB(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -261,7 +265,7 @@
static int milkymist_softusb_init(SysBusDevice *dev)
{
- MilkymistSoftUsbState *s = FROM_SYSBUS(typeof(*s), dev);
+ MilkymistSoftUsbState *s = MILKYMIST_SOFTUSB(dev);
sysbus_init_irq(dev, &s->irq);
@@ -320,7 +324,7 @@
}
static const TypeInfo milkymist_softusb_info = {
- .name = "milkymist-softusb",
+ .name = TYPE_MILKYMIST_SOFTUSB,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistSoftUsbState),
.class_init = milkymist_softusb_class_init,
diff --git a/hw/input/pl050.c b/hw/input/pl050.c
index 2312ffc..c1b08d5 100644
--- a/hw/input/pl050.c
+++ b/hw/input/pl050.c
@@ -10,8 +10,12 @@
#include "hw/sysbus.h"
#include "hw/input/ps2.h"
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PL050 "pl050"
+#define PL050(obj) OBJECT_CHECK(PL050State, (obj), TYPE_PL050)
+
+typedef struct PL050State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
void *dev;
uint32_t cr;
@@ -19,18 +23,18 @@
uint32_t last;
int pending;
qemu_irq irq;
- int is_mouse;
-} pl050_state;
+ bool is_mouse;
+} PL050State;
static const VMStateDescription vmstate_pl050 = {
.name = "pl050",
.version_id = 2,
.minimum_version_id = 2,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(cr, pl050_state),
- VMSTATE_UINT32(clk, pl050_state),
- VMSTATE_UINT32(last, pl050_state),
- VMSTATE_INT32(pending, pl050_state),
+ VMSTATE_UINT32(cr, PL050State),
+ VMSTATE_UINT32(clk, PL050State),
+ VMSTATE_UINT32(last, PL050State),
+ VMSTATE_INT32(pending, PL050State),
VMSTATE_END_OF_LIST()
}
};
@@ -48,7 +52,7 @@
static void pl050_update(void *opaque, int level)
{
- pl050_state *s = (pl050_state *)opaque;
+ PL050State *s = (PL050State *)opaque;
int raise;
s->pending = level;
@@ -60,7 +64,7 @@
static uint64_t pl050_read(void *opaque, hwaddr offset,
unsigned size)
{
- pl050_state *s = (pl050_state *)opaque;
+ PL050State *s = (PL050State *)opaque;
if (offset >= 0xfe0 && offset < 0x1000)
return pl050_id[(offset - 0xfe0) >> 2];
@@ -103,7 +107,7 @@
static void pl050_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
- pl050_state *s = (pl050_state *)opaque;
+ PL050State *s = (PL050State *)opaque;
switch (offset >> 2) {
case 0: /* KMICR */
s->cr = value;
@@ -133,65 +137,67 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int pl050_init(SysBusDevice *dev, int is_mouse)
+static int pl050_initfn(SysBusDevice *dev)
{
- pl050_state *s = FROM_SYSBUS(pl050_state, dev);
+ PL050State *s = PL050(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &pl050_ops, s, "pl050", 0x1000);
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
- s->is_mouse = is_mouse;
- if (s->is_mouse)
+ if (s->is_mouse) {
s->dev = ps2_mouse_init(pl050_update, s);
- else
+ } else {
s->dev = ps2_kbd_init(pl050_update, s);
+ }
return 0;
}
-static int pl050_init_keyboard(SysBusDevice *dev)
+static void pl050_keyboard_init(Object *obj)
{
- return pl050_init(dev, 0);
+ PL050State *s = PL050(obj);
+
+ s->is_mouse = false;
}
-static int pl050_init_mouse(SysBusDevice *dev)
+static void pl050_mouse_init(Object *obj)
{
- return pl050_init(dev, 1);
-}
+ PL050State *s = PL050(obj);
-static void pl050_kbd_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = pl050_init_keyboard;
- dc->vmsd = &vmstate_pl050;
+ s->is_mouse = true;
}
static const TypeInfo pl050_kbd_info = {
.name = "pl050_keyboard",
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl050_state),
- .class_init = pl050_kbd_class_init,
+ .parent = TYPE_PL050,
+ .instance_init = pl050_keyboard_init,
};
-static void pl050_mouse_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
- k->init = pl050_init_mouse;
- dc->vmsd = &vmstate_pl050;
-}
-
static const TypeInfo pl050_mouse_info = {
.name = "pl050_mouse",
+ .parent = TYPE_PL050,
+ .instance_init = pl050_mouse_init,
+};
+
+static void pl050_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(oc);
+
+ sdc->init = pl050_initfn;
+ dc->vmsd = &vmstate_pl050;
+}
+
+static const TypeInfo pl050_type_info = {
+ .name = TYPE_PL050,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl050_state),
- .class_init = pl050_mouse_class_init,
+ .instance_size = sizeof(PL050State),
+ .abstract = true,
+ .class_init = pl050_class_init,
};
static void pl050_register_types(void)
{
+ type_register_static(&pl050_type_info);
type_register_static(&pl050_kbd_info);
type_register_static(&pl050_mouse_info);
}
diff --git a/hw/input/tsc2005.c b/hw/input/tsc2005.c
index a771cd5..21d4f4d 100644
--- a/hw/input/tsc2005.c
+++ b/hw/input/tsc2005.c
@@ -201,7 +201,7 @@
fprintf(stderr, "%s: touchscreen sense %sabled\n",
__FUNCTION__, s->enabled ? "en" : "dis");
if (s->busy && !s->enabled)
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
s->busy &= s->enabled;
}
s->nextprecision = (data >> 13) & 1;
@@ -290,8 +290,8 @@
s->precision = s->nextprecision;
s->function = s->nextfunction;
s->pdst = !s->pnd0; /* Synchronised on internal clock */
- expires = qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() >> 7);
- qemu_mod_timer(s->timer, expires);
+ expires = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (get_ticks_per_sec() >> 7);
+ timer_mod(s->timer, expires);
}
static void tsc2005_reset(TSC2005State *s)
@@ -337,7 +337,7 @@
fprintf(stderr, "%s: touchscreen sense %sabled\n",
__FUNCTION__, s->enabled ? "en" : "dis");
if (s->busy && !s->enabled)
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
s->busy &= s->enabled;
}
tsc2005_pin_update(s);
@@ -449,7 +449,7 @@
qemu_put_be16s(f, &s->dav);
qemu_put_be16s(f, &s->data);
- qemu_put_timer(f, s->timer);
+ timer_put(f, s->timer);
qemu_put_byte(f, s->enabled);
qemu_put_byte(f, s->host_mode);
qemu_put_byte(f, s->function);
@@ -490,7 +490,7 @@
qemu_get_be16s(f, &s->dav);
qemu_get_be16s(f, &s->data);
- qemu_get_timer(f, s->timer);
+ timer_get(f, s->timer);
s->enabled = qemu_get_byte(f);
s->host_mode = qemu_get_byte(f);
s->function = qemu_get_byte(f);
@@ -513,7 +513,7 @@
for (i = 0; i < 8; i ++)
s->tr[i] = qemu_get_be32(f);
- s->busy = qemu_timer_pending(s->timer);
+ s->busy = timer_pending(s->timer);
tsc2005_pin_update(s);
return 0;
@@ -529,7 +529,7 @@
s->y = 240;
s->pressure = 0;
s->precision = s->nextprecision = 0;
- s->timer = qemu_new_timer_ns(vm_clock, tsc2005_timer_tick, s);
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tsc2005_timer_tick, s);
s->pint = pintdav;
s->model = 0x2005;
diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c
index 9b854e7..485c9e5 100644
--- a/hw/input/tsc210x.c
+++ b/hw/input/tsc210x.c
@@ -503,9 +503,9 @@
l_ch = 1;
r_ch = 1;
if (s->softstep && !(s->dac_power & (1 << 10))) {
- l_ch = (qemu_get_clock_ns(vm_clock) >
+ l_ch = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >
s->volume_change + TSC_SOFTSTEP_DELAY);
- r_ch = (qemu_get_clock_ns(vm_clock) >
+ r_ch = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >
s->volume_change + TSC_SOFTSTEP_DELAY);
}
@@ -514,7 +514,7 @@
case 0x05: /* Stereo DAC Power Control */
return 0x2aa0 | s->dac_power |
(((s->dac_power & (1 << 10)) &&
- (qemu_get_clock_ns(vm_clock) >
+ (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >
s->powerdown + TSC_POWEROFF_DELAY)) << 6);
case 0x06: /* Audio Control 3 */
@@ -594,7 +594,7 @@
s->host_mode = value >> 15;
s->enabled = !(value & 0x4000);
if (s->busy && !s->enabled)
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
s->busy &= s->enabled;
s->nextfunction = (value >> 10) & 0xf;
s->nextprecision = (value >> 8) & 3;
@@ -629,7 +629,7 @@
case 0x04: /* Reset */
if (value == 0xbb00) {
if (s->busy)
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
tsc210x_reset(s);
#ifdef TSC_VERBOSE
} else {
@@ -695,7 +695,7 @@
case 0x02: /* DAC Volume Control */
s->volume = value;
- s->volume_change = qemu_get_clock_ns(vm_clock);
+ s->volume_change = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
return;
case 0x03:
@@ -717,7 +717,7 @@
case 0x05: /* Stereo DAC Power Control */
if ((value & ~s->dac_power) & (1 << 10))
- s->powerdown = qemu_get_clock_ns(vm_clock);
+ s->powerdown = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->dac_power = value & 0x9543;
#ifdef TSC_VERBOSE
@@ -864,8 +864,8 @@
s->busy = 1;
s->precision = s->nextprecision;
s->function = s->nextfunction;
- expires = qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() >> 10);
- qemu_mod_timer(s->timer, expires);
+ expires = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (get_ticks_per_sec() >> 10);
+ timer_mod(s->timer, expires);
}
static uint16_t tsc210x_read(TSC210xState *s)
@@ -1005,7 +1005,7 @@
static void tsc210x_save(QEMUFile *f, void *opaque)
{
TSC210xState *s = (TSC210xState *) opaque;
- int64_t now = qemu_get_clock_ns(vm_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
int i;
qemu_put_be16(f, s->x);
@@ -1020,7 +1020,7 @@
qemu_put_byte(f, s->irq);
qemu_put_be16s(f, &s->dav);
- qemu_put_timer(f, s->timer);
+ timer_put(f, s->timer);
qemu_put_byte(f, s->enabled);
qemu_put_byte(f, s->host_mode);
qemu_put_byte(f, s->function);
@@ -1051,7 +1051,7 @@
static int tsc210x_load(QEMUFile *f, void *opaque, int version_id)
{
TSC210xState *s = (TSC210xState *) opaque;
- int64_t now = qemu_get_clock_ns(vm_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
int i;
s->x = qemu_get_be16(f);
@@ -1066,7 +1066,7 @@
s->irq = qemu_get_byte(f);
qemu_get_be16s(f, &s->dav);
- qemu_get_timer(f, s->timer);
+ timer_get(f, s->timer);
s->enabled = qemu_get_byte(f);
s->host_mode = qemu_get_byte(f);
s->function = qemu_get_byte(f);
@@ -1093,7 +1093,7 @@
for (i = 0; i < 0x14; i ++)
qemu_get_be16s(f, &s->filter_data[i]);
- s->busy = qemu_timer_pending(s->timer);
+ s->busy = timer_pending(s->timer);
qemu_set_irq(s->pint, !s->irq);
qemu_set_irq(s->davint, !s->dav);
@@ -1111,7 +1111,7 @@
s->y = 160;
s->pressure = 0;
s->precision = s->nextprecision = 0;
- s->timer = qemu_new_timer_ns(vm_clock, tsc210x_timer_tick, s);
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tsc210x_timer_tick, s);
s->pint = pint;
s->model = 0x2102;
s->name = "tsc2102";
@@ -1160,7 +1160,7 @@
s->y = 240;
s->pressure = 0;
s->precision = s->nextprecision = 0;
- s->timer = qemu_new_timer_ns(vm_clock, tsc210x_timer_tick, s);
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tsc210x_timer_tick, s);
s->pint = penirq;
s->kbint = kbirq;
s->davint = dav;
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index 5e3b96e..a913186 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -606,7 +606,7 @@
{
int64_t d;
uint32_t val;
- d = (qemu_get_clock_ns(vm_clock) - s->initial_count_load_time) >>
+ d = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->initial_count_load_time) >>
s->count_shift;
if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
/* periodic */
@@ -623,9 +623,9 @@
static void apic_timer_update(APICCommonState *s, int64_t current_time)
{
if (apic_next_timer(s, current_time)) {
- qemu_mod_timer(s->timer, s->next_time);
+ timer_mod(s->timer, s->next_time);
} else {
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
}
}
@@ -822,7 +822,7 @@
int n = index - 0x32;
s->lvt[n] = val;
if (n == APIC_LVT_TIMER) {
- apic_timer_update(s, qemu_get_clock_ns(vm_clock));
+ apic_timer_update(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
} else if (n == APIC_LVT_LINT0 && apic_check_pic(s)) {
apic_update_irq(s);
}
@@ -830,7 +830,7 @@
break;
case 0x38:
s->initial_count = val;
- s->initial_count_load_time = qemu_get_clock_ns(vm_clock);
+ s->initial_count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
apic_timer_update(s, s->initial_count_load_time);
break;
case 0x39:
@@ -857,9 +857,9 @@
static void apic_post_load(APICCommonState *s)
{
if (s->timer_expiry != -1) {
- qemu_mod_timer(s->timer, s->timer_expiry);
+ timer_mod(s->timer, s->timer_expiry);
} else {
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
}
}
@@ -876,7 +876,7 @@
memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi",
APIC_SPACE_SIZE);
- s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s);
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, apic_timer, s);
local_apics[s->idx] = s;
msi_supported = true;
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index b03e904..a0beb10 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -198,7 +198,7 @@
s->wait_for_sipi = 1;
if (s->timer) {
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
}
s->timer_expiry = -1;
}
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 8e34004..d431b7a 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -639,6 +639,7 @@
void gic_init_irqs_and_distributor(GICState *s, int num_irq)
{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(s);
int i;
i = s->num_irq - GIC_INTERNAL;
@@ -652,9 +653,9 @@
if (s->revision != REV_NVIC) {
i += (GIC_INTERNAL * s->num_cpu);
}
- qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, i);
+ qdev_init_gpio_in(DEVICE(s), gic_set_irq, i);
for (i = 0; i < NUM_CPU(s); i++) {
- sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
+ sysbus_init_irq(sbd, &s->parent_irq[i]);
}
memory_region_init_io(&s->iomem, OBJECT(s), &gic_dist_ops, s,
"gic_dist", 0x1000);
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index 08560f2..709b5c2 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -110,7 +110,7 @@
static void arm_gic_common_reset(DeviceState *dev)
{
- GICState *s = FROM_SYSBUS(GICState, SYS_BUS_DEVICE(dev));
+ GICState *s = ARM_GIC_COMMON(dev);
int i;
memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
for (i = 0 ; i < s->num_cpu; i++) {
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 178344b..6066fa6 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -78,9 +78,9 @@
static void systick_reload(nvic_state *s, int reset)
{
if (reset)
- s->systick.tick = qemu_get_clock_ns(vm_clock);
+ s->systick.tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->systick.tick += (s->systick.reload + 1) * systick_scale(s);
- qemu_mod_timer(s->systick.timer, s->systick.tick);
+ timer_mod(s->systick.timer, s->systick.tick);
}
static void systick_timer_tick(void * opaque)
@@ -103,7 +103,7 @@
s->systick.control = 0;
s->systick.reload = 0;
s->systick.tick = 0;
- qemu_del_timer(s->systick.timer);
+ timer_del(s->systick.timer);
}
/* The external routines use the hardware vector numbering, ie. the first
@@ -158,7 +158,7 @@
int64_t t;
if ((s->systick.control & SYSTICK_ENABLE) == 0)
return 0;
- t = qemu_get_clock_ns(vm_clock);
+ t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (t >= s->systick.tick)
return 0;
val = ((s->systick.tick - (t + 1)) / systick_scale(s)) + 1;
@@ -290,16 +290,16 @@
s->systick.control &= 0xfffffff8;
s->systick.control |= value & 7;
if ((oldval ^ value) & SYSTICK_ENABLE) {
- int64_t now = qemu_get_clock_ns(vm_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (value & SYSTICK_ENABLE) {
if (s->systick.tick) {
s->systick.tick += now;
- qemu_mod_timer(s->systick.timer, s->systick.tick);
+ timer_mod(s->systick.timer, s->systick.tick);
} else {
systick_reload(s, 1);
}
} else {
- qemu_del_timer(s->systick.timer);
+ timer_del(s->systick.timer);
s->systick.tick -= now;
if (s->systick.tick < 0)
s->systick.tick = 0;
@@ -511,7 +511,7 @@
* by the v7M architecture.
*/
memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->container);
- s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
+ s->systick.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, systick_timer_tick, s);
}
static void armv7m_nvic_instance_init(Object *obj)
diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c
index ce3a3f6..e02da53 100644
--- a/hw/intc/etraxfs_pic.c
+++ b/hw/intc/etraxfs_pic.c
@@ -36,9 +36,14 @@
#define R_R_GURU 4
#define R_MAX 5
+#define TYPE_ETRAX_FS_PIC "etraxfs,pic"
+#define ETRAX_FS_PIC(obj) \
+ OBJECT_CHECK(struct etrax_pic, (obj), TYPE_ETRAX_FS_PIC)
+
struct etrax_pic
{
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion mmio;
void *interrupt_vector;
qemu_irq parent_irq;
@@ -138,17 +143,18 @@
pic_update(fs);
}
-static int etraxfs_pic_init(SysBusDevice *dev)
+static int etraxfs_pic_init(SysBusDevice *sbd)
{
- struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev);
+ DeviceState *dev = DEVICE(sbd);
+ struct etrax_pic *s = ETRAX_FS_PIC(dev);
- qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
- sysbus_init_irq(dev, &s->parent_irq);
- sysbus_init_irq(dev, &s->parent_nmi);
+ qdev_init_gpio_in(dev, irq_handler, 32);
+ sysbus_init_irq(sbd, &s->parent_irq);
+ sysbus_init_irq(sbd, &s->parent_nmi);
memory_region_init_io(&s->mmio, OBJECT(s), &pic_ops, s,
"etraxfs-pic", R_MAX * 4);
- sysbus_init_mmio(dev, &s->mmio);
+ sysbus_init_mmio(sbd, &s->mmio);
return 0;
}
@@ -167,7 +173,7 @@
}
static const TypeInfo etraxfs_pic_info = {
- .name = "etraxfs,pic",
+ .name = TYPE_ETRAX_FS_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct etrax_pic),
.class_init = etraxfs_pic_class_init,
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
index 3b40976..ef5e8eb 100644
--- a/hw/intc/exynos4210_combiner.c
+++ b/hw/intc/exynos4210_combiner.c
@@ -56,8 +56,13 @@
uint8_t src_pending; /* Pending source interrupts before masking */
} CombinerGroupState;
+#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
+#define EXYNOS4210_COMBINER(obj) \
+ OBJECT_CHECK(Exynos4210CombinerState, (obj), TYPE_EXYNOS4210_COMBINER)
+
typedef struct Exynos4210CombinerState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
struct CombinerGroupState group[IIC_NGRP];
@@ -402,24 +407,24 @@
/*
* Internal Combiner initialization.
*/
-static int exynos4210_combiner_init(SysBusDevice *dev)
+static int exynos4210_combiner_init(SysBusDevice *sbd)
{
+ DeviceState *dev = DEVICE(sbd);
+ Exynos4210CombinerState *s = EXYNOS4210_COMBINER(dev);
unsigned int i;
- struct Exynos4210CombinerState *s =
- FROM_SYSBUS(struct Exynos4210CombinerState, dev);
/* Allocate general purpose input signals and connect a handler to each of
* them */
- qdev_init_gpio_in(&s->busdev.qdev, exynos4210_combiner_handler, IIC_NIRQ);
+ qdev_init_gpio_in(dev, exynos4210_combiner_handler, IIC_NIRQ);
/* Connect SysBusDev irqs to device specific irqs */
for (i = 0; i < IIC_NIRQ; i++) {
- sysbus_init_irq(dev, &s->output_irq[i]);
+ sysbus_init_irq(sbd, &s->output_irq[i]);
}
memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_combiner_ops, s,
- "exynos4210-combiner", IIC_REGION_SIZE);
- sysbus_init_mmio(dev, &s->iomem);
+ "exynos4210-combiner", IIC_REGION_SIZE);
+ sysbus_init_mmio(sbd, &s->iomem);
return 0;
}
@@ -441,7 +446,7 @@
}
static const TypeInfo exynos4210_combiner_info = {
- .name = "exynos4210.combiner",
+ .name = TYPE_EXYNOS4210_COMBINER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210CombinerState),
.class_init = exynos4210_combiner_class_init,
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
index 6147f04..5b913f7 100644
--- a/hw/intc/exynos4210_gic.c
+++ b/hw/intc/exynos4210_gic.c
@@ -260,8 +260,13 @@
/********* GIC part *********/
+#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
+#define EXYNOS4210_GIC(obj) \
+ OBJECT_CHECK(Exynos4210GicState, (obj), TYPE_EXYNOS4210_GIC)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion cpu_container;
MemoryRegion dist_container;
MemoryRegion cpu_alias[EXYNOS4210_NCPUS];
@@ -276,9 +281,10 @@
qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
}
-static int exynos4210_gic_init(SysBusDevice *dev)
+static int exynos4210_gic_init(SysBusDevice *sbd)
{
- Exynos4210GicState *s = FROM_SYSBUS(Exynos4210GicState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ Exynos4210GicState *s = EXYNOS4210_GIC(dev);
uint32_t i;
const char cpu_prefix[] = "exynos4210-gic-alias_cpu";
const char dist_prefix[] = "exynos4210-gic-alias_dist";
@@ -293,10 +299,10 @@
busdev = SYS_BUS_DEVICE(s->gic);
/* Pass through outbound IRQ lines from the GIC */
- sysbus_pass_irq(dev, busdev);
+ sysbus_pass_irq(sbd, busdev);
/* Pass through inbound GPIO lines to the GIC */
- qdev_init_gpio_in(&s->busdev.qdev, exynos4210_gic_set_irq,
+ qdev_init_gpio_in(dev, exynos4210_gic_set_irq,
EXYNOS4210_GIC_NIRQ - 32);
memory_region_init(&s->cpu_container, OBJECT(s), "exynos4210-cpu-container",
@@ -326,8 +332,8 @@
EXYNOS4210_EXT_GIC_DIST_GET_OFFSET(i), &s->dist_alias[i]);
}
- sysbus_init_mmio(dev, &s->cpu_container);
- sysbus_init_mmio(dev, &s->dist_container);
+ sysbus_init_mmio(sbd, &s->cpu_container);
+ sysbus_init_mmio(sbd, &s->dist_container);
return 0;
}
@@ -347,7 +353,7 @@
}
static const TypeInfo exynos4210_gic_info = {
- .name = "exynos4210.gic",
+ .name = TYPE_EXYNOS4210_GIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210GicState),
.class_init = exynos4210_gic_class_init,
@@ -366,8 +372,13 @@
* output sysbus IRQ line. The output IRQ level is formed as OR between all
* gpio inputs.
*/
-typedef struct {
- SysBusDevice busdev;
+
+#define TYPE_EXYNOS4210_IRQ_GATE "exynos4210.irq_gate"
+#define EXYNOS4210_IRQ_GATE(obj) \
+ OBJECT_CHECK(Exynos4210IRQGateState, (obj), TYPE_EXYNOS4210_IRQ_GATE)
+
+typedef struct Exynos4210IRQGateState {
+ SysBusDevice parent_obj;
uint32_t n_in; /* inputs amount */
uint32_t *level; /* input levels */
@@ -412,8 +423,7 @@
static void exynos4210_irq_gate_reset(DeviceState *d)
{
- Exynos4210IRQGateState *s =
- DO_UPCAST(Exynos4210IRQGateState, busdev.qdev, d);
+ Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);
memset(s->level, 0, s->n_in * sizeof(*s->level));
}
@@ -421,17 +431,18 @@
/*
* IRQ Gate initialization.
*/
-static int exynos4210_irq_gate_init(SysBusDevice *dev)
+static int exynos4210_irq_gate_init(SysBusDevice *sbd)
{
- Exynos4210IRQGateState *s = FROM_SYSBUS(Exynos4210IRQGateState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev);
/* Allocate general purpose input signals and connect a handler to each of
* them */
- qdev_init_gpio_in(&s->busdev.qdev, exynos4210_irq_gate_handler, s->n_in);
+ qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in);
s->level = g_malloc0(s->n_in * sizeof(*s->level));
- sysbus_init_irq(dev, &s->out);
+ sysbus_init_irq(sbd, &s->out);
return 0;
}
@@ -448,7 +459,7 @@
}
static const TypeInfo exynos4210_irq_gate_info = {
- .name = "exynos4210.irq_gate",
+ .name = TYPE_EXYNOS4210_IRQ_GATE,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210IRQGateState),
.class_init = exynos4210_irq_gate_class_init,
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index 99a3bc3..1426437 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -70,7 +70,10 @@
} gic_irq_state;
typedef struct GICState {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
qemu_irq parent_irq[NCPU];
bool enabled;
bool cpu_enabled[NCPU];
diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c
index 181f614..42e00bc 100644
--- a/hw/intc/grlib_irqmp.c
+++ b/hw/intc/grlib_irqmp.c
@@ -45,10 +45,14 @@
#define FORCE_OFFSET 0x80
#define EXTENDED_OFFSET 0xC0
+#define TYPE_GRLIB_IRQMP "grlib,irqmp"
+#define GRLIB_IRQMP(obj) OBJECT_CHECK(IRQMP, (obj), TYPE_GRLIB_IRQMP)
+
typedef struct IRQMPState IRQMPState;
typedef struct IRQMP {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
void *set_pil_in;
@@ -102,19 +106,10 @@
void grlib_irqmp_ack(DeviceState *dev, int intno)
{
- SysBusDevice *sdev;
- IRQMP *irqmp;
+ IRQMP *irqmp = GRLIB_IRQMP(dev);
IRQMPState *state;
uint32_t mask;
- assert(dev != NULL);
-
- sdev = SYS_BUS_DEVICE(dev);
- assert(sdev != NULL);
-
- irqmp = FROM_SYSBUS(typeof(*irqmp), sdev);
- assert(irqmp != NULL);
-
state = irqmp->state;
assert(state != NULL);
@@ -132,15 +127,10 @@
void grlib_irqmp_set_irq(void *opaque, int irq, int level)
{
- IRQMP *irqmp;
+ IRQMP *irqmp = GRLIB_IRQMP(opaque);
IRQMPState *s;
int i = 0;
- assert(opaque != NULL);
-
- irqmp = FROM_SYSBUS(typeof(*irqmp), SYS_BUS_DEVICE(opaque));
- assert(irqmp != NULL);
-
s = irqmp->state;
assert(s != NULL);
assert(s->parent != NULL);
@@ -325,8 +315,7 @@
static void grlib_irqmp_reset(DeviceState *d)
{
- IRQMP *irqmp = container_of(d, IRQMP, busdev.qdev);
- assert(irqmp != NULL);
+ IRQMP *irqmp = GRLIB_IRQMP(d);
assert(irqmp->state != NULL);
memset(irqmp->state, 0, sizeof *irqmp->state);
@@ -335,9 +324,7 @@
static int grlib_irqmp_init(SysBusDevice *dev)
{
- IRQMP *irqmp = FROM_SYSBUS(typeof(*irqmp), dev);
-
- assert(irqmp != NULL);
+ IRQMP *irqmp = GRLIB_IRQMP(dev);
/* Check parameters */
if (irqmp->set_pil_in == NULL) {
@@ -371,7 +358,7 @@
}
static const TypeInfo grlib_irqmp_info = {
- .name = "grlib,irqmp",
+ .name = TYPE_GRLIB_IRQMP,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IRQMP),
.class_init = grlib_irqmp_class_init,
diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c
index 1415bda..c6f248b 100644
--- a/hw/intc/i8259.c
+++ b/hw/intc/i8259.c
@@ -150,7 +150,7 @@
#endif
#ifdef DEBUG_IRQ_LATENCY
if (level) {
- irq_time[irq_index] = qemu_get_clock_ns(vm_clock);
+ irq_time[irq_index] = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
#endif
@@ -228,7 +228,7 @@
#ifdef DEBUG_IRQ_LATENCY
printf("IRQ%d latency=%0.3fus\n",
irq,
- (double)(qemu_get_clock_ns(vm_clock) -
+ (double)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
irq_time[irq]) * 1000000.0 / get_ticks_per_sec());
#endif
DPRINTF("pic_interrupt: irq=%d\n", irq);
diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c
index 75c8ffd..fb00e91 100644
--- a/hw/intc/imx_avic.c
+++ b/hw/intc/imx_avic.c
@@ -55,8 +55,13 @@
#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4)
#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD)
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_IMX_AVIC "imx_avic"
+#define IMX_AVIC(obj) \
+ OBJECT_CHECK(IMXAVICState, (obj), TYPE_IMX_AVIC)
+
+typedef struct IMXAVICState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint64_t pending;
uint64_t enabled;
@@ -359,7 +364,8 @@
static void imx_avic_reset(DeviceState *dev)
{
- IMXAVICState *s = container_of(dev, IMXAVICState, busdev.qdev);
+ IMXAVICState *s = IMX_AVIC(dev);
+
s->pending = 0;
s->enabled = 0;
s->is_fiq = 0;
@@ -368,17 +374,18 @@
memset(s->prio, 0, sizeof s->prio);
}
-static int imx_avic_init(SysBusDevice *dev)
+static int imx_avic_init(SysBusDevice *sbd)
{
- IMXAVICState *s = FROM_SYSBUS(IMXAVICState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ IMXAVICState *s = IMX_AVIC(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &imx_avic_ops, s,
"imx_avic", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
- qdev_init_gpio_in(&dev->qdev, imx_avic_set_irq, IMX_AVIC_NUM_IRQS);
- sysbus_init_irq(dev, &s->irq);
- sysbus_init_irq(dev, &s->fiq);
+ qdev_init_gpio_in(dev, imx_avic_set_irq, IMX_AVIC_NUM_IRQS);
+ sysbus_init_irq(sbd, &s->irq);
+ sysbus_init_irq(sbd, &s->fiq);
return 0;
}
@@ -395,7 +402,7 @@
}
static const TypeInfo imx_avic_info = {
- .name = "imx_avic",
+ .name = TYPE_IMX_AVIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IMXAVICState),
.class_init = imx_avic_class_init,
diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
index 5d064fe..d866e00 100644
--- a/hw/intc/ioapic.c
+++ b/hw/intc/ioapic.c
@@ -230,7 +230,7 @@
memory_region_init_io(&s->io_memory, OBJECT(s), &ioapic_io_ops, s,
"ioapic", 0x1000);
- qdev_init_gpio_in(&s->busdev.qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
+ qdev_init_gpio_in(DEVICE(s), ioapic_set_irq, IOAPIC_NUM_PINS);
ioapics[instance_no] = s;
}
diff --git a/hw/intc/lm32_pic.c b/hw/intc/lm32_pic.c
index b4e80c8..32d009f 100644
--- a/hw/intc/lm32_pic.c
+++ b/hw/intc/lm32_pic.c
@@ -26,8 +26,12 @@
#include "trace.h"
#include "hw/lm32/lm32_pic.h"
+#define TYPE_LM32_PIC "lm32-pic"
+#define LM32_PIC(obj) OBJECT_CHECK(LM32PicState, (obj), TYPE_LM32_PIC)
+
struct LM32PicState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
qemu_irq parent_irq;
uint32_t im; /* interrupt mask */
uint32_t ip; /* interrupt pending */
@@ -99,7 +103,7 @@
void lm32_pic_set_im(DeviceState *d, uint32_t im)
{
- LM32PicState *s = container_of(d, LM32PicState, busdev.qdev);
+ LM32PicState *s = LM32_PIC(d);
trace_lm32_pic_set_im(im);
s->im = im;
@@ -109,7 +113,7 @@
void lm32_pic_set_ip(DeviceState *d, uint32_t ip)
{
- LM32PicState *s = container_of(d, LM32PicState, busdev.qdev);
+ LM32PicState *s = LM32_PIC(d);
trace_lm32_pic_set_ip(ip);
@@ -121,7 +125,7 @@
uint32_t lm32_pic_get_im(DeviceState *d)
{
- LM32PicState *s = container_of(d, LM32PicState, busdev.qdev);
+ LM32PicState *s = LM32_PIC(d);
trace_lm32_pic_get_im(s->im);
return s->im;
@@ -129,7 +133,7 @@
uint32_t lm32_pic_get_ip(DeviceState *d)
{
- LM32PicState *s = container_of(d, LM32PicState, busdev.qdev);
+ LM32PicState *s = LM32_PIC(d);
trace_lm32_pic_get_ip(s->ip);
return s->ip;
@@ -137,7 +141,7 @@
static void pic_reset(DeviceState *d)
{
- LM32PicState *s = container_of(d, LM32PicState, busdev.qdev);
+ LM32PicState *s = LM32_PIC(d);
int i;
s->im = 0;
@@ -148,12 +152,13 @@
}
}
-static int lm32_pic_init(SysBusDevice *dev)
+static int lm32_pic_init(SysBusDevice *sbd)
{
- LM32PicState *s = FROM_SYSBUS(typeof(*s), dev);
+ DeviceState *dev = DEVICE(sbd);
+ LM32PicState *s = LM32_PIC(dev);
- qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
- sysbus_init_irq(dev, &s->parent_irq);
+ qdev_init_gpio_in(dev, irq_handler, 32);
+ sysbus_init_irq(sbd, &s->parent_irq);
pic = s;
@@ -185,7 +190,7 @@
}
static const TypeInfo lm32_pic_info = {
- .name = "lm32-pic",
+ .name = TYPE_LM32_PIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LM32PicState),
.class_init = lm32_pic_class_init,
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
index bca8585..7dd63da 100644
--- a/hw/intc/omap_intc.c
+++ b/hw/intc/omap_intc.c
@@ -32,8 +32,13 @@
unsigned char priority[32];
};
+#define TYPE_OMAP_INTC "common-omap-intc"
+#define OMAP_INTC(obj) \
+ OBJECT_CHECK(struct omap_intr_handler_s, (obj), TYPE_OMAP_INTC)
+
struct omap_intr_handler_s {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
qemu_irq *pins;
qemu_irq parent_intr[2];
MemoryRegion mmio;
@@ -328,8 +333,7 @@
static void omap_inth_reset(DeviceState *dev)
{
- struct omap_intr_handler_s *s = FROM_SYSBUS(struct omap_intr_handler_s,
- SYS_BUS_DEVICE(dev));
+ struct omap_intr_handler_s *s = OMAP_INTC(dev);
int i;
for (i = 0; i < s->nbanks; ++i){
@@ -356,20 +360,21 @@
qemu_set_irq(s->parent_intr[1], 0);
}
-static int omap_intc_init(SysBusDevice *dev)
+static int omap_intc_init(SysBusDevice *sbd)
{
- struct omap_intr_handler_s *s;
- s = FROM_SYSBUS(struct omap_intr_handler_s, dev);
+ DeviceState *dev = DEVICE(sbd);
+ struct omap_intr_handler_s *s = OMAP_INTC(dev);
+
if (!s->iclk) {
hw_error("omap-intc: clk not connected\n");
}
s->nbanks = 1;
- sysbus_init_irq(dev, &s->parent_intr[0]);
- sysbus_init_irq(dev, &s->parent_intr[1]);
- qdev_init_gpio_in(&dev->qdev, omap_set_intr, s->nbanks * 32);
+ sysbus_init_irq(sbd, &s->parent_intr[0]);
+ sysbus_init_irq(sbd, &s->parent_intr[1]);
+ qdev_init_gpio_in(dev, omap_set_intr, s->nbanks * 32);
memory_region_init_io(&s->mmio, OBJECT(s), &omap_inth_mem_ops, s,
"omap-intc", s->size);
- sysbus_init_mmio(dev, &s->mmio);
+ sysbus_init_mmio(sbd, &s->mmio);
return 0;
}
@@ -391,8 +396,7 @@
static const TypeInfo omap_intc_info = {
.name = "omap-intc",
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(struct omap_intr_handler_s),
+ .parent = TYPE_OMAP_INTC,
.class_init = omap_intc_class_init,
};
@@ -500,8 +504,9 @@
case 0x10: /* INTC_SYSCONFIG */
s->autoidle &= 4;
s->autoidle |= (value & 1) << 2;
- if (value & 2) /* SOFTRESET */
- omap_inth_reset(&s->busdev.qdev);
+ if (value & 2) { /* SOFTRESET */
+ omap_inth_reset(DEVICE(s));
+ }
return;
case 0x48: /* INTC_CONTROL */
@@ -594,10 +599,11 @@
},
};
-static int omap2_intc_init(SysBusDevice *dev)
+static int omap2_intc_init(SysBusDevice *sbd)
{
- struct omap_intr_handler_s *s;
- s = FROM_SYSBUS(struct omap_intr_handler_s, dev);
+ DeviceState *dev = DEVICE(sbd);
+ struct omap_intr_handler_s *s = OMAP_INTC(dev);
+
if (!s->iclk) {
hw_error("omap2-intc: iclk not connected\n");
}
@@ -606,12 +612,12 @@
}
s->level_only = 1;
s->nbanks = 3;
- sysbus_init_irq(dev, &s->parent_intr[0]);
- sysbus_init_irq(dev, &s->parent_intr[1]);
- qdev_init_gpio_in(&dev->qdev, omap_set_intr_noedge, s->nbanks * 32);
+ sysbus_init_irq(sbd, &s->parent_intr[0]);
+ sysbus_init_irq(sbd, &s->parent_intr[1]);
+ qdev_init_gpio_in(dev, omap_set_intr_noedge, s->nbanks * 32);
memory_region_init_io(&s->mmio, OBJECT(s), &omap2_inth_mem_ops, s,
"omap2-intc", 0x1000);
- sysbus_init_mmio(dev, &s->mmio);
+ sysbus_init_mmio(sbd, &s->mmio);
return 0;
}
@@ -635,13 +641,20 @@
static const TypeInfo omap2_intc_info = {
.name = "omap2-intc",
+ .parent = TYPE_OMAP_INTC,
+ .class_init = omap2_intc_class_init,
+};
+
+static const TypeInfo omap_intc_type_info = {
+ .name = TYPE_OMAP_INTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct omap_intr_handler_s),
- .class_init = omap2_intc_class_init,
+ .abstract = true,
};
static void omap_intc_register_types(void)
{
+ type_register_static(&omap_intc_type_info);
type_register_static(&omap_intc_info);
type_register_static(&omap2_intc_info);
}
diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c
index fdb29d7..329680d 100644
--- a/hw/intc/pl190.c
+++ b/hw/intc/pl190.c
@@ -15,8 +15,12 @@
#define PL190_NUM_PRIO 17
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PL190 "pl190"
+#define PL190(obj) OBJECT_CHECK(PL190State, (obj), TYPE_PL190)
+
+typedef struct PL190State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t level;
uint32_t soft_level;
@@ -32,18 +36,18 @@
int prev_prio[PL190_NUM_PRIO];
qemu_irq irq;
qemu_irq fiq;
-} pl190_state;
+} PL190State;
static const unsigned char pl190_id[] =
{ 0x90, 0x11, 0x04, 0x00, 0x0D, 0xf0, 0x05, 0xb1 };
-static inline uint32_t pl190_irq_level(pl190_state *s)
+static inline uint32_t pl190_irq_level(PL190State *s)
{
return (s->level | s->soft_level) & s->irq_enable & ~s->fiq_select;
}
/* Update interrupts. */
-static void pl190_update(pl190_state *s)
+static void pl190_update(PL190State *s)
{
uint32_t level = pl190_irq_level(s);
int set;
@@ -56,7 +60,7 @@
static void pl190_set_irq(void *opaque, int irq, int level)
{
- pl190_state *s = (pl190_state *)opaque;
+ PL190State *s = (PL190State *)opaque;
if (level)
s->level |= 1u << irq;
@@ -65,7 +69,7 @@
pl190_update(s);
}
-static void pl190_update_vectors(pl190_state *s)
+static void pl190_update_vectors(PL190State *s)
{
uint32_t mask;
int i;
@@ -88,7 +92,7 @@
static uint64_t pl190_read(void *opaque, hwaddr offset,
unsigned size)
{
- pl190_state *s = (pl190_state *)opaque;
+ PL190State *s = (PL190State *)opaque;
int i;
if (offset >= 0xfe0 && offset < 0x1000) {
@@ -152,7 +156,7 @@
static void pl190_write(void *opaque, hwaddr offset,
uint64_t val, unsigned size)
{
- pl190_state *s = (pl190_state *)opaque;
+ PL190State *s = (PL190State *)opaque;
if (offset >= 0x100 && offset < 0x140) {
s->vect_addr[(offset - 0x100) >> 2] = val;
@@ -218,29 +222,29 @@
static void pl190_reset(DeviceState *d)
{
- pl190_state *s = DO_UPCAST(pl190_state, busdev.qdev, d);
- int i;
+ PL190State *s = PL190(d);
+ int i;
- for (i = 0; i < 16; i++)
- {
- s->vect_addr[i] = 0;
- s->vect_control[i] = 0;
+ for (i = 0; i < 16; i++) {
+ s->vect_addr[i] = 0;
+ s->vect_control[i] = 0;
}
- s->vect_addr[16] = 0;
- s->prio_mask[17] = 0xffffffff;
- s->priority = PL190_NUM_PRIO;
- pl190_update_vectors(s);
+ s->vect_addr[16] = 0;
+ s->prio_mask[17] = 0xffffffff;
+ s->priority = PL190_NUM_PRIO;
+ pl190_update_vectors(s);
}
-static int pl190_init(SysBusDevice *dev)
+static int pl190_init(SysBusDevice *sbd)
{
- pl190_state *s = FROM_SYSBUS(pl190_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ PL190State *s = PL190(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &pl190_ops, s, "pl190", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- qdev_init_gpio_in(&dev->qdev, pl190_set_irq, 32);
- sysbus_init_irq(dev, &s->irq);
- sysbus_init_irq(dev, &s->fiq);
+ sysbus_init_mmio(sbd, &s->iomem);
+ qdev_init_gpio_in(dev, pl190_set_irq, 32);
+ sysbus_init_irq(sbd, &s->irq);
+ sysbus_init_irq(sbd, &s->fiq);
return 0;
}
@@ -249,16 +253,16 @@
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(level, pl190_state),
- VMSTATE_UINT32(soft_level, pl190_state),
- VMSTATE_UINT32(irq_enable, pl190_state),
- VMSTATE_UINT32(fiq_select, pl190_state),
- VMSTATE_UINT8_ARRAY(vect_control, pl190_state, 16),
- VMSTATE_UINT32_ARRAY(vect_addr, pl190_state, PL190_NUM_PRIO),
- VMSTATE_UINT32_ARRAY(prio_mask, pl190_state, PL190_NUM_PRIO+1),
- VMSTATE_INT32(protected, pl190_state),
- VMSTATE_INT32(priority, pl190_state),
- VMSTATE_INT32_ARRAY(prev_prio, pl190_state, PL190_NUM_PRIO),
+ VMSTATE_UINT32(level, PL190State),
+ VMSTATE_UINT32(soft_level, PL190State),
+ VMSTATE_UINT32(irq_enable, PL190State),
+ VMSTATE_UINT32(fiq_select, PL190State),
+ VMSTATE_UINT8_ARRAY(vect_control, PL190State, 16),
+ VMSTATE_UINT32_ARRAY(vect_addr, PL190State, PL190_NUM_PRIO),
+ VMSTATE_UINT32_ARRAY(prio_mask, PL190State, PL190_NUM_PRIO+1),
+ VMSTATE_INT32(protected, PL190State),
+ VMSTATE_INT32(priority, PL190State),
+ VMSTATE_INT32_ARRAY(prev_prio, PL190State, PL190_NUM_PRIO),
VMSTATE_END_OF_LIST()
}
};
@@ -275,9 +279,9 @@
}
static const TypeInfo pl190_info = {
- .name = "pl190",
+ .name = TYPE_PL190,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl190_state),
+ .instance_size = sizeof(PL190State),
.class_init = pl190_class_init,
};
diff --git a/hw/intc/puv3_intc.c b/hw/intc/puv3_intc.c
index 44b6651..c2803d0 100644
--- a/hw/intc/puv3_intc.c
+++ b/hw/intc/puv3_intc.c
@@ -13,8 +13,12 @@
#undef DEBUG_PUV3
#include "hw/unicore32/puv3.h"
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PUV3_INTC "puv3_intc"
+#define PUV3_INTC(obj) OBJECT_CHECK(PUV3INTCState, (obj), TYPE_PUV3_INTC)
+
+typedef struct PUV3INTCState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq parent_irq;
@@ -96,19 +100,20 @@
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int puv3_intc_init(SysBusDevice *dev)
+static int puv3_intc_init(SysBusDevice *sbd)
{
- PUV3INTCState *s = FROM_SYSBUS(PUV3INTCState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ PUV3INTCState *s = PUV3_INTC(dev);
- qdev_init_gpio_in(&s->busdev.qdev, puv3_intc_handler, PUV3_IRQS_NR);
- sysbus_init_irq(&s->busdev, &s->parent_irq);
+ qdev_init_gpio_in(dev, puv3_intc_handler, PUV3_IRQS_NR);
+ sysbus_init_irq(sbd, &s->parent_irq);
s->reg_ICMR = 0;
s->reg_ICPR = 0;
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_intc_ops, s, "puv3_intc",
- PUV3_REGS_OFFSET);
- sysbus_init_mmio(dev, &s->iomem);
+ PUV3_REGS_OFFSET);
+ sysbus_init_mmio(sbd, &s->iomem);
return 0;
}
@@ -121,7 +126,7 @@
}
static const TypeInfo puv3_intc_info = {
- .name = "puv3_intc",
+ .name = TYPE_PUV3_INTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PUV3INTCState),
.class_init = puv3_intc_class_init,
diff --git a/hw/intc/realview_gic.c b/hw/intc/realview_gic.c
index e122c2c..ce80447 100644
--- a/hw/intc/realview_gic.c
+++ b/hw/intc/realview_gic.c
@@ -9,8 +9,13 @@
#include "hw/sysbus.h"
+#define TYPE_REALVIEW_GIC "realview_gic"
+#define REALVIEW_GIC(obj) \
+ OBJECT_CHECK(RealViewGICState, (obj), TYPE_REALVIEW_GIC)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
DeviceState *gic;
MemoryRegion container;
} RealViewGICState;
@@ -21,9 +26,10 @@
qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
}
-static int realview_gic_init(SysBusDevice *dev)
+static int realview_gic_init(SysBusDevice *sbd)
{
- RealViewGICState *s = FROM_SYSBUS(RealViewGICState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ RealViewGICState *s = REALVIEW_GIC(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
@@ -38,10 +44,10 @@
busdev = SYS_BUS_DEVICE(s->gic);
/* Pass through outbound IRQ lines from the GIC */
- sysbus_pass_irq(dev, busdev);
+ sysbus_pass_irq(sbd, busdev);
/* Pass through inbound GPIO lines to the GIC */
- qdev_init_gpio_in(&s->busdev.qdev, realview_gic_set_irq, numirq - 32);
+ qdev_init_gpio_in(dev, realview_gic_set_irq, numirq - 32);
memory_region_init(&s->container, OBJECT(s),
"realview-gic-container", 0x2000);
@@ -49,7 +55,7 @@
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);
+ sysbus_init_mmio(sbd, &s->container);
return 0;
}
@@ -61,7 +67,7 @@
}
static const TypeInfo realview_gic_info = {
- .name = "realview_gic",
+ .name = TYPE_REALVIEW_GIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(RealViewGICState),
.class_init = realview_gic_class_init,
diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c
index b47d0f0..41a1672 100644
--- a/hw/intc/slavio_intctl.c
+++ b/hw/intc/slavio_intctl.c
@@ -53,8 +53,13 @@
uint32_t irl_out;
} SLAVIO_CPUINTCTLState;
+#define TYPE_SLAVIO_INTCTL "slavio_intctl"
+#define SLAVIO_INTCTL(obj) \
+ OBJECT_CHECK(SLAVIO_INTCTLState, (obj), TYPE_SLAVIO_INTCTL)
+
typedef struct SLAVIO_INTCTLState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
#ifdef DEBUG_IRQ_COUNT
uint64_t irq_count[32];
@@ -206,12 +211,9 @@
void slavio_pic_info(Monitor *mon, DeviceState *dev)
{
- SysBusDevice *sd;
- SLAVIO_INTCTLState *s;
+ SLAVIO_INTCTLState *s = SLAVIO_INTCTL(dev);
int i;
- sd = SYS_BUS_DEVICE(dev);
- s = FROM_SYSBUS(SLAVIO_INTCTLState, sd);
for (i = 0; i < MAX_CPUS; i++) {
monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i,
s->slaves[i].intreg_pending);
@@ -225,13 +227,11 @@
#ifndef DEBUG_IRQ_COUNT
monitor_printf(mon, "irq statistic code not compiled.\n");
#else
- SysBusDevice *sd;
- SLAVIO_INTCTLState *s;
+ SLAVIO_INTCTLState *s = SLAVIO_INTCTL(dev);
int i;
int64_t count;
- sd = SYS_BUS_DEVICE(dev);
- s = FROM_SYSBUS(SLAVIO_INTCTLState, sd);
+ s = SLAVIO_INTCTL(dev);
monitor_printf(mon, "IRQ statistics:\n");
for (i = 0; i < 32; i++) {
count = s->irq_count[i];
@@ -406,7 +406,7 @@
static void slavio_intctl_reset(DeviceState *d)
{
- SLAVIO_INTCTLState *s = container_of(d, SLAVIO_INTCTLState, busdev.qdev);
+ SLAVIO_INTCTLState *s = SLAVIO_INTCTL(d);
int i;
for (i = 0; i < MAX_CPUS; i++) {
@@ -419,27 +419,28 @@
slavio_check_interrupts(s, 0);
}
-static int slavio_intctl_init1(SysBusDevice *dev)
+static int slavio_intctl_init1(SysBusDevice *sbd)
{
- SLAVIO_INTCTLState *s = FROM_SYSBUS(SLAVIO_INTCTLState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ SLAVIO_INTCTLState *s = SLAVIO_INTCTL(dev);
unsigned int i, j;
char slave_name[45];
- qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS);
+ qdev_init_gpio_in(dev, slavio_set_irq_all, 32 + MAX_CPUS);
memory_region_init_io(&s->iomem, OBJECT(s), &slavio_intctlm_mem_ops, s,
"master-interrupt-controller", INTCTLM_SIZE);
- sysbus_init_mmio(dev, &s->iomem);
+ sysbus_init_mmio(sbd, &s->iomem);
for (i = 0; i < MAX_CPUS; i++) {
snprintf(slave_name, sizeof(slave_name),
"slave-interrupt-controller-%i", i);
for (j = 0; j < MAX_PILS; j++) {
- sysbus_init_irq(dev, &s->cpu_irqs[i][j]);
+ sysbus_init_irq(sbd, &s->cpu_irqs[i][j]);
}
memory_region_init_io(&s->slaves[i].iomem, OBJECT(s),
&slavio_intctl_mem_ops,
&s->slaves[i], slave_name, INTCTL_SIZE);
- sysbus_init_mmio(dev, &s->slaves[i].iomem);
+ sysbus_init_mmio(sbd, &s->slaves[i].iomem);
s->slaves[i].cpu = i;
s->slaves[i].master = s;
}
@@ -458,7 +459,7 @@
}
static const TypeInfo slavio_intctl_info = {
- .name = "slavio_intctl",
+ .name = TYPE_SLAVIO_INTCTL,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SLAVIO_INTCTLState),
.class_init = slavio_intctl_class_init,
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 091912e..6b3c071 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -34,34 +34,19 @@
* ICP: Presentation layer
*/
-struct icp_server_state {
- uint32_t xirr;
- uint8_t pending_priority;
- uint8_t mfrr;
- qemu_irq output;
-};
-
#define XISR_MASK 0x00ffffff
#define CPPR_MASK 0xff000000
#define XISR(ss) (((ss)->xirr) & XISR_MASK)
#define CPPR(ss) (((ss)->xirr) >> 24)
-struct ics_state;
+static void ics_reject(ICSState *ics, int nr);
+static void ics_resend(ICSState *ics);
+static void ics_eoi(ICSState *ics, int nr);
-struct icp_state {
- long nr_servers;
- struct icp_server_state *ss;
- struct ics_state *ics;
-};
-
-static void ics_reject(struct ics_state *ics, int nr);
-static void ics_resend(struct ics_state *ics);
-static void ics_eoi(struct ics_state *ics, int nr);
-
-static void icp_check_ipi(struct icp_state *icp, int server)
+static void icp_check_ipi(XICSState *icp, int server)
{
- struct icp_server_state *ss = icp->ss + server;
+ ICPState *ss = icp->ss + server;
if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
return;
@@ -78,9 +63,9 @@
qemu_irq_raise(ss->output);
}
-static void icp_resend(struct icp_state *icp, int server)
+static void icp_resend(XICSState *icp, int server)
{
- struct icp_server_state *ss = icp->ss + server;
+ ICPState *ss = icp->ss + server;
if (ss->mfrr < CPPR(ss)) {
icp_check_ipi(icp, server);
@@ -88,9 +73,9 @@
ics_resend(icp->ics);
}
-static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr)
+static void icp_set_cppr(XICSState *icp, int server, uint8_t cppr)
{
- struct icp_server_state *ss = icp->ss + server;
+ ICPState *ss = icp->ss + server;
uint8_t old_cppr;
uint32_t old_xisr;
@@ -112,9 +97,9 @@
}
}
-static void icp_set_mfrr(struct icp_state *icp, int server, uint8_t mfrr)
+static void icp_set_mfrr(XICSState *icp, int server, uint8_t mfrr)
{
- struct icp_server_state *ss = icp->ss + server;
+ ICPState *ss = icp->ss + server;
ss->mfrr = mfrr;
if (mfrr < CPPR(ss)) {
@@ -122,7 +107,7 @@
}
}
-static uint32_t icp_accept(struct icp_server_state *ss)
+static uint32_t icp_accept(ICPState *ss)
{
uint32_t xirr = ss->xirr;
@@ -135,9 +120,9 @@
return xirr;
}
-static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
+static void icp_eoi(XICSState *icp, int server, uint32_t xirr)
{
- struct icp_server_state *ss = icp->ss + server;
+ ICPState *ss = icp->ss + server;
/* Send EOI -> ICS */
ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
@@ -148,9 +133,9 @@
}
}
-static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority)
+static void icp_irq(XICSState *icp, int server, int nr, uint8_t priority)
{
- struct icp_server_state *ss = icp->ss + server;
+ ICPState *ss = icp->ss + server;
trace_xics_icp_irq(server, nr, priority);
@@ -168,39 +153,59 @@
}
}
+static const VMStateDescription vmstate_icp_server = {
+ .name = "icp/server",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ /* Sanity check */
+ VMSTATE_UINT32(xirr, ICPState),
+ VMSTATE_UINT8(pending_priority, ICPState),
+ VMSTATE_UINT8(mfrr, ICPState),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void icp_reset(DeviceState *dev)
+{
+ ICPState *icp = ICP(dev);
+
+ icp->xirr = 0;
+ icp->pending_priority = 0xff;
+ icp->mfrr = 0xff;
+
+ /* Make all outputs are deasserted */
+ qemu_set_irq(icp->output, 0);
+}
+
+static void icp_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = icp_reset;
+ dc->vmsd = &vmstate_icp_server;
+}
+
+static TypeInfo icp_info = {
+ .name = TYPE_ICP,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(ICPState),
+ .class_init = icp_class_init,
+};
+
/*
* ICS: Source layer
*/
-
-struct ics_irq_state {
- int 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;
-};
-
-struct ics_state {
- int nr_irqs;
- int offset;
- qemu_irq *qirqs;
- bool *islsi;
- struct ics_irq_state *irqs;
- struct icp_state *icp;
-};
-
-static int ics_valid_irq(struct ics_state *ics, uint32_t nr)
+static int ics_valid_irq(ICSState *ics, uint32_t nr)
{
return (nr >= ics->offset)
&& (nr < (ics->offset + ics->nr_irqs));
}
-static void resend_msi(struct ics_state *ics, int srcno)
+static void resend_msi(ICSState *ics, int srcno)
{
- struct ics_irq_state *irq = ics->irqs + srcno;
+ ICSIRQState *irq = ics->irqs + srcno;
/* FIXME: filter by server#? */
if (irq->status & XICS_STATUS_REJECTED) {
@@ -212,9 +217,9 @@
}
}
-static void resend_lsi(struct ics_state *ics, int srcno)
+static void resend_lsi(ICSState *ics, int srcno)
{
- struct ics_irq_state *irq = ics->irqs + srcno;
+ ICSIRQState *irq = ics->irqs + srcno;
if ((irq->priority != 0xff)
&& (irq->status & XICS_STATUS_ASSERTED)
@@ -224,9 +229,9 @@
}
}
-static void set_irq_msi(struct ics_state *ics, int srcno, int val)
+static void set_irq_msi(ICSState *ics, int srcno, int val)
{
- struct ics_irq_state *irq = ics->irqs + srcno;
+ ICSIRQState *irq = ics->irqs + srcno;
trace_xics_set_irq_msi(srcno, srcno + ics->offset);
@@ -240,9 +245,9 @@
}
}
-static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
+static void set_irq_lsi(ICSState *ics, int srcno, int val)
{
- struct ics_irq_state *irq = ics->irqs + srcno;
+ ICSIRQState *irq = ics->irqs + srcno;
trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
if (val) {
@@ -255,7 +260,7 @@
static void ics_set_irq(void *opaque, int srcno, int val)
{
- struct ics_state *ics = (struct ics_state *)opaque;
+ ICSState *ics = (ICSState *)opaque;
if (ics->islsi[srcno]) {
set_irq_lsi(ics, srcno, val);
@@ -264,9 +269,9 @@
}
}
-static void write_xive_msi(struct ics_state *ics, int srcno)
+static void write_xive_msi(ICSState *ics, int srcno)
{
- struct ics_irq_state *irq = ics->irqs + srcno;
+ ICSIRQState *irq = ics->irqs + srcno;
if (!(irq->status & XICS_STATUS_MASKED_PENDING)
|| (irq->priority == 0xff)) {
@@ -277,16 +282,16 @@
icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
}
-static void write_xive_lsi(struct ics_state *ics, int srcno)
+static void write_xive_lsi(ICSState *ics, int srcno)
{
resend_lsi(ics, srcno);
}
-static void ics_write_xive(struct ics_state *ics, int nr, int server,
+static void ics_write_xive(ICSState *ics, int nr, int server,
uint8_t priority, uint8_t saved_priority)
{
int srcno = nr - ics->offset;
- struct ics_irq_state *irq = ics->irqs + srcno;
+ ICSIRQState *irq = ics->irqs + srcno;
irq->server = server;
irq->priority = priority;
@@ -301,16 +306,16 @@
}
}
-static void ics_reject(struct ics_state *ics, int nr)
+static void ics_reject(ICSState *ics, int nr)
{
- struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+ ICSIRQState *irq = ics->irqs + nr - ics->offset;
trace_xics_ics_reject(nr, nr - ics->offset);
irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
}
-static void ics_resend(struct ics_state *ics)
+static void ics_resend(ICSState *ics)
{
int i;
@@ -324,10 +329,10 @@
}
}
-static void ics_eoi(struct ics_state *ics, int nr)
+static void ics_eoi(ICSState *ics, int nr)
{
int srcno = nr - ics->offset;
- struct ics_irq_state *irq = ics->irqs + srcno;
+ ICSIRQState *irq = ics->irqs + srcno;
trace_xics_ics_eoi(nr);
@@ -336,11 +341,92 @@
}
}
+static void ics_reset(DeviceState *dev)
+{
+ ICSState *ics = ICS(dev);
+ int i;
+
+ memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs);
+ for (i = 0; i < ics->nr_irqs; i++) {
+ ics->irqs[i].priority = 0xff;
+ ics->irqs[i].saved_priority = 0xff;
+ }
+}
+
+static int ics_post_load(void *opaque, int version_id)
+{
+ int i;
+ ICSState *ics = opaque;
+
+ for (i = 0; i < ics->icp->nr_servers; i++) {
+ icp_resend(ics->icp, i);
+ }
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_ics_irq = {
+ .name = "ics/irq",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(server, ICSIRQState),
+ VMSTATE_UINT8(priority, ICSIRQState),
+ VMSTATE_UINT8(saved_priority, ICSIRQState),
+ VMSTATE_UINT8(status, ICSIRQState),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static const VMStateDescription vmstate_ics = {
+ .name = "ics",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .post_load = ics_post_load,
+ .fields = (VMStateField []) {
+ /* Sanity check */
+ VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
+
+ VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
+ vmstate_ics_irq, ICSIRQState),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static int ics_realize(DeviceState *dev)
+{
+ ICSState *ics = ICS(dev);
+
+ ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
+ ics->islsi = g_malloc0(ics->nr_irqs * sizeof(bool));
+ ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs);
+
+ return 0;
+}
+
+static void ics_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->init = ics_realize;
+ dc->vmsd = &vmstate_ics;
+ dc->reset = ics_reset;
+}
+
+static TypeInfo ics_info = {
+ .name = TYPE_ICS,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(ICSState),
+ .class_init = ics_class_init,
+};
+
/*
* Exported functions
*/
-qemu_irq xics_get_qirq(struct icp_state *icp, int irq)
+qemu_irq xics_get_qirq(XICSState *icp, int irq)
{
if (!ics_valid_irq(icp->ics, irq)) {
return NULL;
@@ -349,13 +435,17 @@
return icp->ics->qirqs[irq - icp->ics->offset];
}
-void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi)
+void xics_set_irq_type(XICSState *icp, int irq, bool lsi)
{
assert(ics_valid_irq(icp->ics, irq));
icp->ics->islsi[irq - icp->ics->offset] = lsi;
}
+/*
+ * Guest interfaces
+ */
+
static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
@@ -405,7 +495,7 @@
uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets)
{
- struct ics_state *ics = spapr->icp->ics;
+ ICSState *ics = spapr->icp->ics;
uint32_t nr, server, priority;
if ((nargs != 3) || (nret != 1)) {
@@ -433,7 +523,7 @@
uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets)
{
- struct ics_state *ics = spapr->icp->ics;
+ ICSState *ics = spapr->icp->ics;
uint32_t nr;
if ((nargs != 1) || (nret != 3)) {
@@ -458,7 +548,7 @@
uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets)
{
- struct ics_state *ics = spapr->icp->ics;
+ ICSState *ics = spapr->icp->ics;
uint32_t nr;
if ((nargs != 1) || (nret != 1)) {
@@ -484,7 +574,7 @@
uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets)
{
- struct ics_state *ics = spapr->icp->ics;
+ ICSState *ics = spapr->icp->ics;
uint32_t nr;
if ((nargs != 1) || (nret != 1)) {
@@ -506,32 +596,27 @@
rtas_st(rets, 0, 0); /* Success */
}
-static void xics_reset(void *opaque)
+/*
+ * XICS
+ */
+
+static void xics_reset(DeviceState *d)
{
- struct icp_state *icp = (struct icp_state *)opaque;
- struct ics_state *ics = icp->ics;
+ XICSState *icp = XICS(d);
int i;
for (i = 0; i < icp->nr_servers; i++) {
- icp->ss[i].xirr = 0;
- icp->ss[i].pending_priority = 0xff;
- icp->ss[i].mfrr = 0xff;
- /* Make all outputs are deasserted */
- qemu_set_irq(icp->ss[i].output, 0);
+ device_reset(DEVICE(&icp->ss[i]));
}
- memset(ics->irqs, 0, sizeof(struct ics_irq_state) * ics->nr_irqs);
- for (i = 0; i < ics->nr_irqs; i++) {
- ics->irqs[i].priority = 0xff;
- ics->irqs[i].saved_priority = 0xff;
- }
+ device_reset(DEVICE(icp->ics));
}
-void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu)
+void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
- struct icp_server_state *ss = &icp->ss[cs->cpu_index];
+ ICPState *ss = &icp->ss[cs->cpu_index];
assert(cs->cpu_index < icp->nr_servers);
@@ -551,37 +636,73 @@
}
}
-struct icp_state *xics_system_init(int nr_servers, int nr_irqs)
+static void xics_realize(DeviceState *dev, Error **errp)
{
- struct icp_state *icp;
- struct ics_state *ics;
+ XICSState *icp = XICS(dev);
+ ICSState *ics = icp->ics;
+ int i;
- icp = g_malloc0(sizeof(*icp));
- icp->nr_servers = nr_servers;
- icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state));
-
- ics = g_malloc0(sizeof(*ics));
- ics->nr_irqs = nr_irqs;
+ ics->nr_irqs = icp->nr_irqs;
ics->offset = XICS_IRQ_BASE;
- ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state));
- ics->islsi = g_malloc0(nr_irqs * sizeof(bool));
-
- icp->ics = ics;
ics->icp = icp;
+ qdev_init_nofail(DEVICE(ics));
- ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs);
+ icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
+ for (i = 0; i < icp->nr_servers; i++) {
+ char buffer[32];
+ object_initialize(&icp->ss[i], TYPE_ICP);
+ snprintf(buffer, sizeof(buffer), "icp[%d]", i);
+ object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]), NULL);
+ qdev_init_nofail(DEVICE(&icp->ss[i]));
+ }
+}
- spapr_register_hypercall(H_CPPR, h_cppr);
- spapr_register_hypercall(H_IPI, h_ipi);
- spapr_register_hypercall(H_XIRR, h_xirr);
- spapr_register_hypercall(H_EOI, h_eoi);
+static void xics_initfn(Object *obj)
+{
+ XICSState *xics = XICS(obj);
+
+ xics->ics = ICS(object_new(TYPE_ICS));
+ object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
+}
+
+static Property xics_properties[] = {
+ DEFINE_PROP_UINT32("nr_servers", XICSState, nr_servers, -1),
+ DEFINE_PROP_UINT32("nr_irqs", XICSState, nr_irqs, -1),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void xics_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = xics_realize;
+ dc->props = xics_properties;
+ dc->reset = xics_reset;
spapr_rtas_register("ibm,set-xive", rtas_set_xive);
spapr_rtas_register("ibm,get-xive", rtas_get_xive);
spapr_rtas_register("ibm,int-off", rtas_int_off);
spapr_rtas_register("ibm,int-on", rtas_int_on);
- qemu_register_reset(xics_reset, icp);
-
- return icp;
+ spapr_register_hypercall(H_CPPR, h_cppr);
+ spapr_register_hypercall(H_IPI, h_ipi);
+ spapr_register_hypercall(H_XIRR, h_xirr);
+ spapr_register_hypercall(H_EOI, h_eoi);
}
+
+static const TypeInfo xics_info = {
+ .name = TYPE_XICS,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(XICSState),
+ .class_init = xics_class_init,
+ .instance_init = xics_initfn,
+};
+
+static void xics_register_types(void)
+{
+ type_register_static(&xics_info);
+ type_register_static(&ics_info);
+ type_register_static(&icp_info);
+}
+
+type_init(xics_register_types)
diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
index 25d2057..4a10398 100644
--- a/hw/intc/xilinx_intc.c
+++ b/hw/intc/xilinx_intc.c
@@ -37,9 +37,13 @@
#define R_MER 7
#define R_MAX 8
+#define TYPE_XILINX_INTC "xlnx.xps-intc"
+#define XILINX_INTC(obj) OBJECT_CHECK(struct xlx_pic, (obj), TYPE_XILINX_INTC)
+
struct xlx_pic
{
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion mmio;
qemu_irq parent_irq;
@@ -153,16 +157,17 @@
update_irq(p);
}
-static int xilinx_intc_init(SysBusDevice *dev)
+static int xilinx_intc_init(SysBusDevice *sbd)
{
- struct xlx_pic *p = FROM_SYSBUS(typeof (*p), dev);
+ DeviceState *dev = DEVICE(sbd);
+ struct xlx_pic *p = XILINX_INTC(dev);
- qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
- sysbus_init_irq(dev, &p->parent_irq);
+ qdev_init_gpio_in(dev, irq_handler, 32);
+ sysbus_init_irq(sbd, &p->parent_irq);
memory_region_init_io(&p->mmio, OBJECT(p), &pic_ops, p, "xlnx.xps-intc",
R_MAX * 4);
- sysbus_init_mmio(dev, &p->mmio);
+ sysbus_init_mmio(sbd, &p->mmio);
return 0;
}
@@ -181,7 +186,7 @@
}
static const TypeInfo xilinx_intc_info = {
- .name = "xlnx.xps-intc",
+ .name = TYPE_XILINX_INTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct xlx_pic),
.class_init = xilinx_intc_class_init,
diff --git a/hw/isa/Makefile.objs b/hw/isa/Makefile.objs
index 193746a..9164556 100644
--- a/hw/isa/Makefile.objs
+++ b/hw/isa/Makefile.objs
@@ -1,7 +1,6 @@
common-obj-y += isa-bus.o
common-obj-$(CONFIG_APM) += apm.o
common-obj-$(CONFIG_I82378) += i82378.o
-common-obj-$(CONFIG_ISA_MMIO) += isa_mmio.o
common-obj-$(CONFIG_PC87312) += pc87312.o
common-obj-$(CONFIG_PIIX4) += piix4.o
common-obj-$(CONFIG_VT82C686) += vt82c686.o
diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c
index b25ed04..a7d9aa6 100644
--- a/hw/isa/i82378.c
+++ b/hw/isa/i82378.c
@@ -22,135 +22,28 @@
#include "hw/timer/i8254.h"
#include "hw/audio/pcspk.h"
-//#define DEBUG_I82378
-
-#ifdef DEBUG_I82378
-#define DPRINTF(fmt, ...) \
-do { fprintf(stderr, "i82378: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
-do {} while (0)
-#endif
-
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "i82378 ERROR: " fmt , ## __VA_ARGS__); } while (0)
+#define TYPE_I82378 "i82378"
+#define I82378(obj) \
+ OBJECT_CHECK(I82378State, (obj), TYPE_I82378)
typedef struct I82378State {
+ PCIDevice parent_obj;
+
qemu_irq out[2];
qemu_irq *i8259;
MemoryRegion io;
- MemoryRegion mem;
} I82378State;
-typedef struct PCIi82378State {
- PCIDevice pci_dev;
- uint32_t isa_io_base;
- uint32_t isa_mem_base;
- I82378State state;
-} PCIi82378State;
-
-static const VMStateDescription vmstate_pci_i82378 = {
+static const VMStateDescription vmstate_i82378 = {
.name = "pci-i82378",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
- VMSTATE_PCI_DEVICE(pci_dev, PCIi82378State),
+ VMSTATE_PCI_DEVICE(parent_obj, I82378State),
VMSTATE_END_OF_LIST()
},
};
-static void i82378_io_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned int size)
-{
- switch (size) {
- case 1:
- DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__,
- addr, value);
- cpu_outb(addr, value);
- break;
- case 2:
- DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__,
- addr, value);
- cpu_outw(addr, value);
- break;
- case 4:
- DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__,
- addr, value);
- cpu_outl(addr, value);
- break;
- default:
- abort();
- }
-}
-
-static uint64_t i82378_io_read(void *opaque, hwaddr addr,
- unsigned int size)
-{
- DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
- switch (size) {
- case 1:
- return cpu_inb(addr);
- case 2:
- return cpu_inw(addr);
- case 4:
- return cpu_inl(addr);
- default:
- abort();
- }
-}
-
-static const MemoryRegionOps i82378_io_ops = {
- .read = i82378_io_read,
- .write = i82378_io_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static void i82378_mem_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned int size)
-{
- switch (size) {
- case 1:
- DPRINTF("%s: " TARGET_FMT_plx "=%02" PRIx64 "\n", __func__,
- addr, value);
- cpu_outb(addr, value);
- break;
- case 2:
- DPRINTF("%s: " TARGET_FMT_plx "=%04" PRIx64 "\n", __func__,
- addr, value);
- cpu_outw(addr, value);
- break;
- case 4:
- DPRINTF("%s: " TARGET_FMT_plx "=%08" PRIx64 "\n", __func__,
- addr, value);
- cpu_outl(addr, value);
- break;
- default:
- abort();
- }
-}
-
-static uint64_t i82378_mem_read(void *opaque, hwaddr addr,
- unsigned int size)
-{
- DPRINTF("%s: " TARGET_FMT_plx "\n", __func__, addr);
- switch (size) {
- case 1:
- return cpu_inb(addr);
- case 2:
- return cpu_inw(addr);
- case 4:
- return cpu_inl(addr);
- default:
- abort();
- }
-}
-
-static const MemoryRegionOps i82378_mem_ops = {
- .read = i82378_mem_read,
- .write = i82378_mem_write,
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
static void i82378_request_out0_irq(void *opaque, int irq, int level)
{
I82378State *s = opaque;
@@ -160,19 +53,30 @@
static void i82378_request_pic_irq(void *opaque, int irq, int level)
{
DeviceState *dev = opaque;
- PCIDevice *pci = DO_UPCAST(PCIDevice, qdev, dev);
- PCIi82378State *s = DO_UPCAST(PCIi82378State, pci_dev, pci);
+ I82378State *s = I82378(dev);
- qemu_set_irq(s->state.i8259[irq], level);
+ qemu_set_irq(s->i8259[irq], level);
}
-static void i82378_init(DeviceState *dev, I82378State *s)
+static int i82378_initfn(PCIDevice *pci)
{
- ISABus *isabus = ISA_BUS(qdev_get_child_bus(dev, "isa.0"));
- ISADevice *pit;
+ DeviceState *dev = DEVICE(pci);
+ I82378State *s = I82378(dev);
+ uint8_t *pci_conf;
+ ISABus *isabus;
ISADevice *isa;
qemu_irq *out0_irq;
+ pci_conf = pci->config;
+ pci_set_word(pci_conf + PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_set_word(pci_conf + PCI_STATUS,
+ PCI_STATUS_DEVSEL_MEDIUM);
+
+ pci_config_set_interrupt_pin(pci_conf, 1); /* interrupt pin 0 */
+
+ isabus = isa_bus_new(dev, pci_address_space_io(pci));
+
/* This device has:
2 82C59 (irq)
1 82C54 (pit)
@@ -183,9 +87,6 @@
All devices accept byte access only, except timer
*/
- qdev_init_gpio_out(dev, s->out, 2);
- qdev_init_gpio_in(dev, i82378_request_pic_irq, 16);
-
/* Workaround the fact that i8259 is not qdev'ified... */
out0_irq = qemu_allocate_irqs(i82378_request_out0_irq, s, 1);
@@ -194,10 +95,10 @@
isa_bus_irqs(isabus, s->i8259);
/* 1 82C54 (pit) */
- pit = pit_init(isabus, 0x40, 0, NULL);
+ isa = pit_init(isabus, 0x40, 0, NULL);
/* speaker */
- pcspk_init(isabus, pit);
+ pcspk_init(isabus, isa);
/* 2 82C37 (dma) */
isa = isa_create_simple(isabus, "i82374");
@@ -205,75 +106,44 @@
/* timer */
isa_create_simple(isabus, "mc146818rtc");
-}
-
-static int pci_i82378_init(PCIDevice *dev)
-{
- PCIi82378State *pci = DO_UPCAST(PCIi82378State, pci_dev, dev);
- I82378State *s = &pci->state;
- uint8_t *pci_conf;
-
- pci_conf = dev->config;
- pci_set_word(pci_conf + PCI_COMMAND,
- PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
- pci_set_word(pci_conf + PCI_STATUS,
- PCI_STATUS_DEVSEL_MEDIUM);
-
- pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */
-
- memory_region_init_io(&s->io, OBJECT(pci), &i82378_io_ops, s,
- "i82378-io", 0x00010000);
- pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io);
-
- memory_region_init_io(&s->mem, OBJECT(pci), &i82378_mem_ops, s,
- "i82378-mem", 0x01000000);
- pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem);
-
- /* Make I/O address read only */
- pci_set_word(dev->wmask + PCI_COMMAND, PCI_COMMAND_SPECIAL);
- pci_set_long(dev->wmask + PCI_BASE_ADDRESS_0, 0);
- pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, pci->isa_io_base);
-
- isa_mem_base = pci->isa_mem_base;
- isa_bus_new(&dev->qdev, pci_address_space_io(dev));
-
- i82378_init(&dev->qdev, s);
return 0;
}
-static Property i82378_properties[] = {
- DEFINE_PROP_HEX32("iobase", PCIi82378State, isa_io_base, 0x80000000),
- DEFINE_PROP_HEX32("membase", PCIi82378State, isa_mem_base, 0xc0000000),
- DEFINE_PROP_END_OF_LIST()
-};
+static void i82378_init(Object *obj)
+{
+ DeviceState *dev = DEVICE(obj);
+ I82378State *s = I82378(obj);
-static void pci_i82378_class_init(ObjectClass *klass, void *data)
+ qdev_init_gpio_out(dev, s->out, 2);
+ qdev_init_gpio_in(dev, i82378_request_pic_irq, 16);
+}
+
+static void i82378_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
- k->init = pci_i82378_init;
+ k->init = i82378_initfn;
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_82378;
k->revision = 0x03;
k->class_id = PCI_CLASS_BRIDGE_ISA;
- k->subsystem_vendor_id = 0x0;
- k->subsystem_id = 0x0;
- dc->vmsd = &vmstate_pci_i82378;
- dc->props = i82378_properties;
+ dc->vmsd = &vmstate_i82378;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
-static const TypeInfo pci_i82378_info = {
- .name = "i82378",
+static const TypeInfo i82378_type_info = {
+ .name = TYPE_I82378,
.parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIi82378State),
- .class_init = pci_i82378_class_init,
+ .instance_size = sizeof(I82378State),
+ .instance_init = i82378_init,
+ .class_init = i82378_class_init,
};
static void i82378_register_types(void)
{
- type_register_static(&pci_i82378_info);
+ type_register_static(&i82378_type_info);
}
type_init(i82378_register_types)
diff --git a/hw/isa/isa_mmio.c b/hw/isa/isa_mmio.c
deleted file mode 100644
index 00ae8eb..0000000
--- a/hw/isa/isa_mmio.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Memory mapped access to ISA IO space.
- *
- * Copyright (c) 2006 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.
- */
-
-#include "hw/hw.h"
-#include "hw/isa/isa.h"
-#include "exec/address-spaces.h"
-
-static void isa_mmio_writeb (void *opaque, hwaddr addr,
- uint32_t val)
-{
- cpu_outb(addr & IOPORTS_MASK, val);
-}
-
-static void isa_mmio_writew(void *opaque, hwaddr addr,
- uint32_t val)
-{
- cpu_outw(addr & IOPORTS_MASK, val);
-}
-
-static void isa_mmio_writel(void *opaque, hwaddr addr,
- uint32_t val)
-{
- cpu_outl(addr & IOPORTS_MASK, val);
-}
-
-static uint32_t isa_mmio_readb (void *opaque, hwaddr addr)
-{
- return cpu_inb(addr & IOPORTS_MASK);
-}
-
-static uint32_t isa_mmio_readw(void *opaque, hwaddr addr)
-{
- return cpu_inw(addr & IOPORTS_MASK);
-}
-
-static uint32_t isa_mmio_readl(void *opaque, hwaddr addr)
-{
- return cpu_inl(addr & IOPORTS_MASK);
-}
-
-static const MemoryRegionOps isa_mmio_ops = {
- .old_mmio = {
- .write = { isa_mmio_writeb, isa_mmio_writew, isa_mmio_writel },
- .read = { isa_mmio_readb, isa_mmio_readw, isa_mmio_readl, },
- },
- .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-void isa_mmio_setup(MemoryRegion *mr, hwaddr size)
-{
- memory_region_init_io(mr, NULL, &isa_mmio_ops, NULL, "isa-mmio", size);
-}
-
-void isa_mmio_init(hwaddr base, hwaddr size)
-{
- MemoryRegion *mr = g_malloc(sizeof(*mr));
-
- isa_mmio_setup(mr, size);
- memory_region_add_subregion(get_system_memory(), base, mr);
-}
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index d1921aa..5633d08 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -600,6 +600,7 @@
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->reset = ich9_lpc_reset;
k->init = ich9_lpc_initfn;
dc->vmsd = &vmstate_ich9_lpc;
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index 2174eaa..8fe4fcb 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -281,6 +281,7 @@
k->device_id = PCI_DEVICE_ID_VIA_AC97;
k->revision = 0x50;
k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
dc->desc = "AC97";
}
@@ -322,6 +323,7 @@
k->device_id = PCI_DEVICE_ID_VIA_MC97;
k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
k->revision = 0x30;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
dc->desc = "MC97";
}
@@ -401,6 +403,7 @@
k->revision = 0x40;
dc->desc = "PM";
dc->vmsd = &vmstate_acpi;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->props = via_pm_properties;
}
diff --git a/hw/lm32/lm32.h b/hw/lm32/lm32.h
index 236686e..18aa6fd 100644
--- a/hw/lm32/lm32.h
+++ b/hw/lm32/lm32.h
@@ -1,8 +1,7 @@
#ifndef HW_LM32_H
#define HW_LM32_H 1
-
-#include "qemu-common.h"
+#include "hw/char/lm32_juart.h"
static inline DeviceState *lm32_pic_init(qemu_irq cpu_irq)
{
@@ -21,7 +20,7 @@
{
DeviceState *dev;
- dev = qdev_create(NULL, "lm32-juart");
+ dev = qdev_create(NULL, TYPE_LM32_JUART);
qdev_init_nofail(dev);
return dev;
diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
index e0266bf..c8b4b00 100644
--- a/hw/mips/cputimer.c
+++ b/hw/mips/cputimer.c
@@ -47,11 +47,11 @@
uint64_t now, next;
uint32_t wait;
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
wait = env->CP0_Compare - env->CP0_Count -
(uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
- qemu_mod_timer(env->timer, next);
+ timer_mod(env->timer, next);
}
/* Expire the timer. */
@@ -71,9 +71,9 @@
} else {
uint64_t now;
- now = qemu_get_clock_ns(vm_clock);
- if (qemu_timer_pending(env->timer)
- && qemu_timer_expired(env->timer, now)) {
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ if (timer_pending(env->timer)
+ && timer_expired(env->timer, now)) {
/* The timer has already expired. */
cpu_mips_timer_expire(env);
}
@@ -90,7 +90,7 @@
else {
/* Store new count register */
env->CP0_Count =
- count - (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
+ count - (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
TIMER_FREQ, get_ticks_per_sec());
/* Update timer timer */
cpu_mips_timer_update(env);
@@ -115,7 +115,7 @@
void cpu_mips_stop_count(CPUMIPSState *env)
{
/* Store the current value */
- env->CP0_Count += (uint32_t)muldiv64(qemu_get_clock_ns(vm_clock),
+ env->CP0_Count += (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
TIMER_FREQ, get_ticks_per_sec());
}
@@ -141,7 +141,7 @@
void cpu_mips_clock_init (CPUMIPSState *env)
{
- env->timer = qemu_new_timer_ns(vm_clock, &mips_timer_cb, env);
+ env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
env->CP0_Compare = 0;
cpu_mips_store_count(env, 1);
}
diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c
index 5843417..3da2e67 100644
--- a/hw/mips/gt64xxx_pci.c
+++ b/hw/mips/gt64xxx_pci.c
@@ -304,7 +304,8 @@
s->PCI0IO_length = ((s->regs[GT_PCI0IOHD] + 1) - (s->regs[GT_PCI0IOLD] & 0x7f)) << 21;
isa_mem_base = s->PCI0IO_start;
if (s->PCI0IO_length) {
- isa_mmio_setup(&s->PCI0IO_mem, s->PCI0IO_length);
+ memory_region_init_alias(&s->PCI0IO_mem, OBJECT(s), "isa_mmio",
+ get_system_io(), 0, s->PCI0IO_length);
memory_region_add_subregion(get_system_memory(), s->PCI0IO_start,
&s->PCI0IO_mem);
}
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
index 9e305d2..e8d5dd0 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -43,6 +43,8 @@
#include "hw/timer/i8254.h"
#include "sysemu/blockdev.h"
#include "exec/address-spaces.h"
+#include "sysemu/qtest.h"
+#include "qemu/error-report.h"
#define DEBUG_FULONG2E_INIT
@@ -126,7 +128,7 @@
if (loaderparams.initrd_filename) {
initrd_size = get_image_size (loaderparams.initrd_filename);
if (initrd_size > 0) {
- initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+ initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK;
if (initrd_offset + initrd_size > ram_size) {
fprintf(stderr,
"qemu: memory too small for initial ram disk '%s'\n",
@@ -332,8 +334,9 @@
bios_size = -1;
}
- if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
- fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", bios_name);
+ if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
+ !kernel_filename && !qtest_enabled()) {
+ error_report("Could not load MIPS bios '%s'", bios_name);
exit(1);
}
}
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 31e138b..d748ded 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -42,6 +42,8 @@
#include "sysemu/blockdev.h"
#include "hw/sysbus.h"
#include "exec/address-spaces.h"
+#include "sysemu/qtest.h"
+#include "qemu/error-report.h"
enum jazz_model_e
{
@@ -119,6 +121,7 @@
qemu_irq *rc4030, *i8259;
rc4030_dma *dmas;
void* rc4030_opaque;
+ MemoryRegion *isa = g_new(MemoryRegion, 1);
MemoryRegion *rtc = g_new(MemoryRegion, 1);
MemoryRegion *i8042 = g_new(MemoryRegion, 1);
MemoryRegion *dma_dummy = g_new(MemoryRegion, 1);
@@ -175,9 +178,8 @@
} else {
bios_size = -1;
}
- if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) {
- fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n",
- bios_name);
+ if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) && !qtest_enabled()) {
+ error_report("Could not load MIPS bios '%s'", bios_name);
exit(1);
}
@@ -201,7 +203,9 @@
pcspk_init(isa_bus, pit);
/* ISA IO space at 0x90000000 */
- isa_mmio_init(0x90000000, 0x01000000);
+ memory_region_init_alias(isa, NULL, "isa_mmio",
+ get_system_io(), 0, 0x01000000);
+ memory_region_add_subregion(address_space, 0x90000000, isa);
isa_mem_base = 0x11000000;
/* Video card */
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index de87241..f8d064c 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -47,6 +47,10 @@
#include "sysemu/blockdev.h"
#include "exec/address-spaces.h"
#include "hw/sysbus.h" /* SysBusDevice */
+#include "qemu/host-utils.h"
+#include "sysemu/qtest.h"
+#include "qemu/error-report.h"
+#include "hw/empty_slot.h"
//#define DEBUG_BOARD_INIT
@@ -79,8 +83,12 @@
SerialState *uart;
} MaltaFPGAState;
+#define TYPE_MIPS_MALTA "mips-malta"
+#define MIPS_MALTA(obj) OBJECT_CHECK(MaltaState, (obj), TYPE_MIPS_MALTA)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
qemu_irq *i8259;
} MaltaState;
@@ -144,12 +152,12 @@
typedef struct _eeprom24c0x_t eeprom24c0x_t;
-static eeprom24c0x_t eeprom = {
+static eeprom24c0x_t spd_eeprom = {
.contents = {
- /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
+ /* 00000000: */ 0x80,0x08,0xFF,0x0D,0x0A,0xFF,0x40,0x00,
/* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
- /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
- /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
+ /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x00,0x00,
+ /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0xFF,
/* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
/* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -165,69 +173,157 @@
},
};
-static uint8_t eeprom24c0x_read(void)
+static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
{
- logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
- eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
- return eeprom.sda;
+ enum { SDR = 0x4, DDR2 = 0x8 } type;
+ uint8_t *spd = spd_eeprom.contents;
+ uint8_t nbanks = 0;
+ uint16_t density = 0;
+ int i;
+
+ /* work in terms of MB */
+ ram_size >>= 20;
+
+ while ((ram_size >= 4) && (nbanks <= 2)) {
+ int sz_log2 = MIN(31 - clz32(ram_size), 14);
+ nbanks++;
+ density |= 1 << (sz_log2 - 2);
+ ram_size -= 1 << sz_log2;
+ }
+
+ /* split to 2 banks if possible */
+ if ((nbanks == 1) && (density > 1)) {
+ nbanks++;
+ density >>= 1;
+ }
+
+ if (density & 0xff00) {
+ density = (density & 0xe0) | ((density >> 8) & 0x1f);
+ type = DDR2;
+ } else if (!(density & 0x1f)) {
+ type = DDR2;
+ } else {
+ type = SDR;
+ }
+
+ if (ram_size) {
+ fprintf(stderr, "Warning: SPD cannot represent final %dMB"
+ " of SDRAM\n", (int)ram_size);
+ }
+
+ /* fill in SPD memory information */
+ spd[2] = type;
+ spd[5] = nbanks;
+ spd[31] = density;
+
+ /* checksum */
+ spd[63] = 0;
+ for (i = 0; i < 63; i++) {
+ spd[63] += spd[i];
+ }
+
+ /* copy for SMBUS */
+ memcpy(eeprom, spd, sizeof(spd_eeprom.contents));
}
-static void eeprom24c0x_write(int scl, int sda)
+static void generate_eeprom_serial(uint8_t *eeprom)
{
- if (eeprom.scl && scl && (eeprom.sda != sda)) {
+ int i, pos = 0;
+ uint8_t mac[6] = { 0x00 };
+ uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
+
+ /* version */
+ eeprom[pos++] = 0x01;
+
+ /* count */
+ eeprom[pos++] = 0x02;
+
+ /* MAC address */
+ eeprom[pos++] = 0x01; /* MAC */
+ eeprom[pos++] = 0x06; /* length */
+ memcpy(&eeprom[pos], mac, sizeof(mac));
+ pos += sizeof(mac);
+
+ /* serial number */
+ eeprom[pos++] = 0x02; /* serial */
+ eeprom[pos++] = 0x05; /* length */
+ memcpy(&eeprom[pos], sn, sizeof(sn));
+ pos += sizeof(sn);
+
+ /* checksum */
+ eeprom[pos] = 0;
+ for (i = 0; i < pos; i++) {
+ eeprom[pos] += eeprom[i];
+ }
+}
+
+static uint8_t eeprom24c0x_read(eeprom24c0x_t *eeprom)
+{
+ logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
+ eeprom->tick, eeprom->scl, eeprom->sda, eeprom->data);
+ return eeprom->sda;
+}
+
+static void eeprom24c0x_write(eeprom24c0x_t *eeprom, int scl, int sda)
+{
+ if (eeprom->scl && scl && (eeprom->sda != sda)) {
logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
- eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
+ eeprom->tick, eeprom->scl, scl, eeprom->sda, sda,
+ sda ? "stop" : "start");
if (!sda) {
- eeprom.tick = 1;
- eeprom.command = 0;
+ eeprom->tick = 1;
+ eeprom->command = 0;
}
- } else if (eeprom.tick == 0 && !eeprom.ack) {
+ } else if (eeprom->tick == 0 && !eeprom->ack) {
/* Waiting for start. */
logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
- eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
- } else if (!eeprom.scl && scl) {
+ eeprom->tick, eeprom->scl, scl, eeprom->sda, sda);
+ } else if (!eeprom->scl && scl) {
logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
- eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
- if (eeprom.ack) {
+ eeprom->tick, eeprom->scl, scl, eeprom->sda, sda);
+ if (eeprom->ack) {
logout("\ti2c ack bit = 0\n");
sda = 0;
- eeprom.ack = 0;
- } else if (eeprom.sda == sda) {
+ eeprom->ack = 0;
+ } else if (eeprom->sda == sda) {
uint8_t bit = (sda != 0);
logout("\ti2c bit = %d\n", bit);
- if (eeprom.tick < 9) {
- eeprom.command <<= 1;
- eeprom.command += bit;
- eeprom.tick++;
- if (eeprom.tick == 9) {
- logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
- eeprom.ack = 1;
+ if (eeprom->tick < 9) {
+ eeprom->command <<= 1;
+ eeprom->command += bit;
+ eeprom->tick++;
+ if (eeprom->tick == 9) {
+ logout("\tcommand 0x%04x, %s\n", eeprom->command,
+ bit ? "read" : "write");
+ eeprom->ack = 1;
}
- } else if (eeprom.tick < 17) {
- if (eeprom.command & 1) {
- sda = ((eeprom.data & 0x80) != 0);
+ } else if (eeprom->tick < 17) {
+ if (eeprom->command & 1) {
+ sda = ((eeprom->data & 0x80) != 0);
}
- eeprom.address <<= 1;
- eeprom.address += bit;
- eeprom.tick++;
- eeprom.data <<= 1;
- if (eeprom.tick == 17) {
- eeprom.data = eeprom.contents[eeprom.address];
- logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
- eeprom.ack = 1;
- eeprom.tick = 0;
+ eeprom->address <<= 1;
+ eeprom->address += bit;
+ eeprom->tick++;
+ eeprom->data <<= 1;
+ if (eeprom->tick == 17) {
+ eeprom->data = eeprom->contents[eeprom->address];
+ logout("\taddress 0x%04x, data 0x%02x\n",
+ eeprom->address, eeprom->data);
+ eeprom->ack = 1;
+ eeprom->tick = 0;
}
- } else if (eeprom.tick >= 17) {
+ } else if (eeprom->tick >= 17) {
sda = 0;
}
} else {
logout("\tsda changed with raising scl\n");
}
} else {
- logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
+ logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom->tick, eeprom->scl,
+ scl, eeprom->sda, sda);
}
- eeprom.scl = scl;
- eeprom.sda = sda;
+ eeprom->scl = scl;
+ eeprom->sda = sda;
}
static uint64_t malta_fpga_read(void *opaque, hwaddr addr,
@@ -290,7 +386,7 @@
/* I2CINP Register */
case 0x00b00:
- val = ((s->i2cin & ~1) | eeprom24c0x_read());
+ val = ((s->i2cin & ~1) | eeprom24c0x_read(&spd_eeprom));
break;
/* I2COE Register */
@@ -386,7 +482,7 @@
/* I2COUT Register */
case 0x00b10:
- eeprom24c0x_write(val & 0x02, val & 0x01);
+ eeprom24c0x_write(&spd_eeprom, val & 0x02, val & 0x01);
s->i2cout = val;
break;
@@ -699,7 +795,7 @@
if (loaderparams.initrd_filename) {
initrd_size = get_image_size (loaderparams.initrd_filename);
if (initrd_size > 0) {
- initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+ initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK;
if (initrd_offset + initrd_size > ram_size) {
fprintf(stderr,
"qemu: memory too small for initial ram disk '%s'\n",
@@ -789,8 +885,10 @@
pflash_t *fl;
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
- MemoryRegion *bios, *bios_alias = g_new(MemoryRegion, 1);
+ MemoryRegion *bios, *bios_copy = g_new(MemoryRegion, 1);
target_long bios_size = FLASH_SIZE;
+ const size_t smbus_eeprom_size = 8 * 256;
+ uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size);
int64_t kernel_entry;
PCIBus *pci_bus;
ISABus *isa_bus;
@@ -808,8 +906,13 @@
int fl_sectors = bios_size >> 16;
int be;
- DeviceState *dev = qdev_create(NULL, "mips-malta");
- MaltaState *s = DO_UPCAST(MaltaState, busdev.qdev, dev);
+ DeviceState *dev = qdev_create(NULL, TYPE_MIPS_MALTA);
+ MaltaState *s = MIPS_MALTA(dev);
+
+ /* The whole address space decoded by the GT-64120A doesn't generate
+ exception when accessing invalid memory. Create an empty slot to
+ emulate this feature. */
+ empty_slot_init(0, 0x20000000);
qdev_init_nofail(dev);
@@ -858,6 +961,10 @@
vmstate_register_ram_global(ram);
memory_region_add_subregion(system_memory, 0, ram);
+ /* generate SPD EEPROM data */
+ generate_eeprom_spd(&smbus_eeprom_buf[0 * 256], ram_size);
+ generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
+
#ifdef TARGET_WORDS_BIGENDIAN
be = 1;
#else
@@ -906,10 +1013,10 @@
} else {
bios_size = -1;
}
- if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
- fprintf(stderr,
- "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
- bios_name);
+ if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
+ !kernel_filename && !qtest_enabled()) {
+ error_report("Could not load MIPS bios '%s', and no "
+ "-kernel argument was specified", bios_name);
exit(1);
}
}
@@ -917,8 +1024,11 @@
a neat trick which allows bi-endian firmware. */
#ifndef TARGET_WORDS_BIGENDIAN
{
- uint32_t *addr = memory_region_get_ram_ptr(bios);
- uint32_t *end = addr + bios_size;
+ uint32_t *end, *addr = rom_ptr(FLASH_ADDRESS);
+ if (!addr) {
+ addr = memory_region_get_ram_ptr(bios);
+ }
+ end = (void *)addr + MIN(bios_size, 0x3e0000);
while (addr < end) {
bswap32s(addr);
addr++;
@@ -927,14 +1037,23 @@
#endif
}
- /* Map the BIOS at a 2nd physical location, as on the real board. */
- memory_region_init_alias(bios_alias, NULL, "bios.1fc", bios, 0, BIOS_SIZE);
- memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias);
+ /*
+ * Map the BIOS at a 2nd physical location, as on the real board.
+ * Copy it so that we can patch in the MIPS revision, which cannot be
+ * handled by an overlapping region as the resulting ROM code subpage
+ * regions are not executable.
+ */
+ memory_region_init_ram(bios_copy, NULL, "bios.1fc", BIOS_SIZE);
+ if (!rom_copy(memory_region_get_ram_ptr(bios_copy),
+ FLASH_ADDRESS, BIOS_SIZE)) {
+ memcpy(memory_region_get_ram_ptr(bios_copy),
+ memory_region_get_ram_ptr(bios), BIOS_SIZE);
+ }
+ memory_region_set_readonly(bios_copy, true);
+ memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_copy);
- /* Board ID = 0x420 (Malta Board with CoreLV)
- XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
- map to the board ID. */
- stl_p(memory_region_get_ram_ptr(bios) + 0x10, 0x00000420);
+ /* Board ID = 0x420 (Malta Board with CoreLV) */
+ stl_p(memory_region_get_ram_ptr(bios_copy) + 0x10, 0x00000420);
/* Init internal devices */
cpu_mips_irq_init_cpu(env);
@@ -966,8 +1085,8 @@
pci_create_simple(pci_bus, piix4_devfn + 2, "piix4-usb-uhci");
smbus = piix4_pm_init(pci_bus, piix4_devfn + 3, 0x1100,
isa_get_irq(NULL, 9), NULL, 0, NULL);
- /* TODO: Populate SPD eeprom data. */
- smbus_eeprom_init(smbus, 8, NULL, 0);
+ smbus_eeprom_init(smbus, 8, smbus_eeprom_buf, smbus_eeprom_size);
+ g_free(smbus_eeprom_buf);
pit = pit_init(isa_bus, 0x40, 0, NULL);
cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
DMA_init(0, cpu_exit_irq);
@@ -1005,7 +1124,7 @@
}
static const TypeInfo mips_malta_device = {
- .name = "mips-malta",
+ .name = TYPE_MIPS_MALTA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MaltaState),
.class_init = mips_malta_class_init,
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c
index a10cf13..297f01e 100644
--- a/hw/mips/mips_mipssim.c
+++ b/hw/mips/mips_mipssim.c
@@ -37,6 +37,7 @@
#include "elf.h"
#include "hw/sysbus.h"
#include "exec/address-spaces.h"
+#include "qemu/error-report.h"
static struct _loaderparams {
int ram_size;
@@ -83,7 +84,7 @@
if (loaderparams.initrd_filename) {
initrd_size = get_image_size (loaderparams.initrd_filename);
if (initrd_size > 0) {
- initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+ initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK;
if (initrd_offset + initrd_size > loaderparams.ram_size) {
fprintf(stderr,
"qemu: memory too small for initial ram disk '%s'\n",
@@ -140,6 +141,7 @@
const char *initrd_filename = args->initrd_filename;
char *filename;
MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *isa = g_new(MemoryRegion, 1);
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *bios = g_new(MemoryRegion, 1);
MIPSCPU *cpu;
@@ -190,9 +192,8 @@
}
if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) {
/* Bail out if we have neither a kernel image nor boot vector code. */
- fprintf(stderr,
- "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
- filename);
+ error_report("Could not load MIPS bios '%s', and no "
+ "-kernel argument was specified", filename);
exit(1);
} else {
/* We have a boot vector start address. */
@@ -212,7 +213,9 @@
cpu_mips_clock_init(env);
/* Register 64 KB of ISA IO space at 0x1fd00000. */
- isa_mmio_init(0x1fd00000, 0x00010000);
+ memory_region_init_alias(isa, NULL, "isa_mmio",
+ get_system_io(), 0, 0x00010000);
+ memory_region_add_subregion(get_system_memory(), 0x1fd00000, isa);
/* A single 16450 sits at offset 0x3f8. It is attached to
MIPS CPU INT2, which is interrupt 4. */
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
index 22beb0a..044f232 100644
--- a/hw/mips/mips_r4k.c
+++ b/hw/mips/mips_r4k.c
@@ -26,6 +26,7 @@
#include "hw/timer/i8254.h"
#include "sysemu/blockdev.h"
#include "exec/address-spaces.h"
+#include "sysemu/qtest.h"
#define MAX_IDE_BUS 2
@@ -102,7 +103,7 @@
if (loaderparams.initrd_filename) {
initrd_size = get_image_size (loaderparams.initrd_filename);
if (initrd_size > 0) {
- initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK;
+ initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) & INITRD_PAGE_MASK;
if (initrd_offset + initrd_size > ram_size) {
fprintf(stderr,
"qemu: memory too small for initial ram disk '%s'\n",
@@ -164,6 +165,7 @@
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *bios;
MemoryRegion *iomem = g_new(MemoryRegion, 1);
+ MemoryRegion *isa = g_new(MemoryRegion, 1);
int bios_size;
MIPSCPU *cpu;
CPUMIPSState *env;
@@ -243,8 +245,7 @@
4, 0, 0, 0, 0, be)) {
fprintf(stderr, "qemu: Error registering flash memory.\n");
}
- }
- else {
+ } else if (!qtest_enabled()) {
/* not fatal */
fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
bios_name);
@@ -273,7 +274,10 @@
rtc_init(isa_bus, 2000, NULL);
/* Register 64 KB of ISA IO space at 0x14000000 */
- isa_mmio_init(0x14000000, 0x00010000);
+ memory_region_init_alias(isa, NULL, "isa_mmio",
+ get_system_io(), 0, 0x00010000);
+ memory_region_add_subregion(get_system_memory(), 0x14000000, isa);
+
isa_mem_base = 0x10000000;
pit = pit_init(isa_bus, 0x40, 0, NULL);
diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
index bfafa51..1e8d183 100644
--- a/hw/misc/applesmc.c
+++ b/hw/misc/applesmc.c
@@ -263,6 +263,7 @@
dc->realize = applesmc_isa_realize;
dc->reset = qdev_applesmc_isa_reset;
dc->props = applesmc_isa_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo applesmc_isa_info = {
diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c
index 3d6acee..8e192cd 100644
--- a/hw/misc/arm_l2x0.c
+++ b/hw/misc/arm_l2x0.c
@@ -23,8 +23,12 @@
/* L2C-310 r3p2 */
#define CACHE_ID 0x410000c8
-typedef struct l2x0_state {
- SysBusDevice busdev;
+#define TYPE_ARM_L2X0 "l2x0"
+#define ARM_L2X0(obj) OBJECT_CHECK(L2x0State, (obj), TYPE_ARM_L2X0)
+
+typedef struct L2x0State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t cache_type;
uint32_t ctrl;
@@ -33,19 +37,19 @@
uint32_t tag_ctrl;
uint32_t filter_start;
uint32_t filter_end;
-} l2x0_state;
+} L2x0State;
static const VMStateDescription vmstate_l2x0 = {
.name = "l2x0",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(ctrl, l2x0_state),
- VMSTATE_UINT32(aux_ctrl, l2x0_state),
- VMSTATE_UINT32(data_ctrl, l2x0_state),
- VMSTATE_UINT32(tag_ctrl, l2x0_state),
- VMSTATE_UINT32(filter_start, l2x0_state),
- VMSTATE_UINT32(filter_end, l2x0_state),
+ VMSTATE_UINT32(ctrl, L2x0State),
+ VMSTATE_UINT32(aux_ctrl, L2x0State),
+ VMSTATE_UINT32(data_ctrl, L2x0State),
+ VMSTATE_UINT32(tag_ctrl, L2x0State),
+ VMSTATE_UINT32(filter_start, L2x0State),
+ VMSTATE_UINT32(filter_end, L2x0State),
VMSTATE_END_OF_LIST()
}
};
@@ -55,7 +59,7 @@
unsigned size)
{
uint32_t cache_data;
- l2x0_state *s = (l2x0_state *)opaque;
+ L2x0State *s = (L2x0State *)opaque;
offset &= 0xfff;
if (offset >= 0x730 && offset < 0x800) {
return 0; /* cache ops complete */
@@ -97,7 +101,7 @@
static void l2x0_priv_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
- l2x0_state *s = (l2x0_state *)opaque;
+ L2x0State *s = (L2x0State *)opaque;
offset &= 0xfff;
if (offset >= 0x730 && offset < 0x800) {
/* ignore */
@@ -137,7 +141,7 @@
static void l2x0_priv_reset(DeviceState *dev)
{
- l2x0_state *s = DO_UPCAST(l2x0_state, busdev.qdev, dev);
+ L2x0State *s = ARM_L2X0(dev);
s->ctrl = 0;
s->aux_ctrl = 0x02020000;
@@ -155,7 +159,7 @@
static int l2x0_priv_init(SysBusDevice *dev)
{
- l2x0_state *s = FROM_SYSBUS(l2x0_state, dev);
+ L2x0State *s = ARM_L2X0(dev);
memory_region_init_io(&s->iomem, OBJECT(dev), &l2x0_mem_ops, s,
"l2x0_cc", 0x1000);
@@ -164,7 +168,7 @@
}
static Property l2x0_properties[] = {
- DEFINE_PROP_UINT32("cache-type", l2x0_state, cache_type, 0x1c100100),
+ DEFINE_PROP_UINT32("cache-type", L2x0State, cache_type, 0x1c100100),
DEFINE_PROP_END_OF_LIST(),
};
@@ -181,9 +185,9 @@
}
static const TypeInfo l2x0_info = {
- .name = "l2x0",
+ .name = TYPE_ARM_L2X0,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(l2x0_state),
+ .instance_size = sizeof(L2x0State),
.class_init = l2x0_class_init,
};
diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c
index 5906ae5..0fc26d2 100644
--- a/hw/misc/arm_sysctl.c
+++ b/hw/misc/arm_sysctl.c
@@ -16,8 +16,13 @@
#define LOCK_VALUE 0xa05f
+#define TYPE_ARM_SYSCTL "realview_sysctl"
+#define ARM_SYSCTL(obj) \
+ OBJECT_CHECK(arm_sysctl_state, (obj), TYPE_ARM_SYSCTL)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq pl110_mux_ctrl;
@@ -85,7 +90,7 @@
static void arm_sysctl_reset(DeviceState *d)
{
- arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, SYS_BUS_DEVICE(d));
+ arm_sysctl_state *s = ARM_SYSCTL(d);
int i;
s->leds = 0;
@@ -165,7 +170,7 @@
case 0x58: /* BOOTCS */
return 0;
case 0x5c: /* 24MHz */
- return muldiv64(qemu_get_clock_ns(vm_clock), 24000000, get_ticks_per_sec());
+ return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24000000, get_ticks_per_sec());
case 0x60: /* MISC */
return 0;
case 0x84: /* PROCID0 */
@@ -587,7 +592,7 @@
{
DeviceState *dev = DEVICE(obj);
SysBusDevice *sd = SYS_BUS_DEVICE(obj);
- arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sd);
+ arm_sysctl_state *s = ARM_SYSCTL(obj);
memory_region_init_io(&s->iomem, OBJECT(dev), &arm_sysctl_ops, s,
"arm-sysctl", 0x1000);
@@ -598,14 +603,15 @@
static void arm_sysctl_realize(DeviceState *d, Error **errp)
{
- arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, SYS_BUS_DEVICE(d));
+ arm_sysctl_state *s = ARM_SYSCTL(d);
+
s->db_clock = g_new0(uint32_t, s->db_num_clocks);
}
static void arm_sysctl_finalize(Object *obj)
{
- SysBusDevice *dev = SYS_BUS_DEVICE(obj);
- arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev);
+ arm_sysctl_state *s = ARM_SYSCTL(obj);
+
g_free(s->db_voltage);
g_free(s->db_clock);
g_free(s->db_clock_reset);
@@ -634,7 +640,7 @@
}
static const TypeInfo arm_sysctl_info = {
- .name = "realview_sysctl",
+ .name = TYPE_ARM_SYSCTL,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(arm_sysctl_state),
.instance_init = arm_sysctl_init,
diff --git a/hw/misc/debugexit.c b/hw/misc/debugexit.c
index d754cf1..9db5680 100644
--- a/hw/misc/debugexit.c
+++ b/hw/misc/debugexit.c
@@ -58,6 +58,7 @@
dc->realize = debug_exit_realizefn;
dc->props = debug_exit_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo debug_exit_info = {
diff --git a/hw/misc/eccmemctl.c b/hw/misc/eccmemctl.c
index 3de9675..96a69d4 100644
--- a/hw/misc/eccmemctl.c
+++ b/hw/misc/eccmemctl.c
@@ -120,8 +120,12 @@
#define ECC_DIAG_SIZE 4
#define ECC_DIAG_MASK (ECC_DIAG_SIZE - 1)
+#define TYPE_ECC_MEMCTL "eccmemctl"
+#define ECC_MEMCTL(obj) OBJECT_CHECK(ECCState, (obj), TYPE_ECC_MEMCTL)
+
typedef struct ECCState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem, iomem_diag;
qemu_irq irq;
uint32_t regs[ECC_NREGS];
@@ -273,13 +277,14 @@
static void ecc_reset(DeviceState *d)
{
- ECCState *s = container_of(d, ECCState, busdev.qdev);
+ ECCState *s = ECC_MEMCTL(d);
- if (s->version == ECC_MCC)
+ if (s->version == ECC_MCC) {
s->regs[ECC_MER] &= ECC_MER_REU;
- else
+ } else {
s->regs[ECC_MER] &= (ECC_MER_VER | ECC_MER_IMPL | ECC_MER_MRR |
ECC_MER_DCI);
+ }
s->regs[ECC_MDR] = 0x20;
s->regs[ECC_MFSR] = 0;
s->regs[ECC_VCR] = 0;
@@ -292,7 +297,7 @@
static int ecc_init1(SysBusDevice *dev)
{
- ECCState *s = FROM_SYSBUS(ECCState, dev);
+ ECCState *s = ECC_MEMCTL(dev);
sysbus_init_irq(dev, &s->irq);
s->regs[0] = s->version;
@@ -325,7 +330,7 @@
}
static const TypeInfo ecc_info = {
- .name = "eccmemctl",
+ .name = TYPE_ECC_MEMCTL,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ECCState),
.class_init = ecc_class_init,
diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c
index 28395ba..cbf0795 100644
--- a/hw/misc/exynos4210_pmu.c
+++ b/hw/misc/exynos4210_pmu.c
@@ -386,8 +386,13 @@
#define PMU_NUM_OF_REGISTERS \
(sizeof(exynos4210_pmu_regs) / sizeof(Exynos4210PmuReg))
+#define TYPE_EXYNOS4210_PMU "exynos4210.pmu"
+#define EXYNOS4210_PMU(obj) \
+ OBJECT_CHECK(Exynos4210PmuState, (obj), TYPE_EXYNOS4210_PMU)
+
typedef struct Exynos4210PmuState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t reg[PMU_NUM_OF_REGISTERS];
} Exynos4210PmuState;
@@ -443,8 +448,7 @@
static void exynos4210_pmu_reset(DeviceState *dev)
{
- Exynos4210PmuState *s =
- container_of(dev, Exynos4210PmuState, busdev.qdev);
+ Exynos4210PmuState *s = EXYNOS4210_PMU(dev);
unsigned i;
/* Set default values for registers */
@@ -455,7 +459,7 @@
static int exynos4210_pmu_init(SysBusDevice *dev)
{
- Exynos4210PmuState *s = FROM_SYSBUS(Exynos4210PmuState, dev);
+ Exynos4210PmuState *s = EXYNOS4210_PMU(dev);
/* memory mapping */
memory_region_init_io(&s->iomem, OBJECT(dev), &exynos4210_pmu_ops, s,
@@ -485,7 +489,7 @@
}
static const TypeInfo exynos4210_pmu_info = {
- .name = "exynos4210.pmu",
+ .name = TYPE_EXYNOS4210_PMU,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210PmuState),
.class_init = exynos4210_pmu_class_init,
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
index 816d5e8..63e33a4 100644
--- a/hw/misc/imx_ccm.c
+++ b/hw/misc/imx_ccm.c
@@ -29,8 +29,12 @@
static int imx_ccm_post_load(void *opaque, int version_id);
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_IMX_CCM "imx_ccm"
+#define IMX_CCM(obj) OBJECT_CHECK(IMXCCMState, (obj), TYPE_IMX_CCM)
+
+typedef struct IMXCCMState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t ccmr;
@@ -108,7 +112,7 @@
uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock)
{
- IMXCCMState *s = container_of(dev, IMXCCMState, busdev.qdev);
+ IMXCCMState *s = IMX_CCM(dev);
switch (clock) {
case NOCLK:
@@ -178,7 +182,7 @@
static void imx_ccm_reset(DeviceState *dev)
{
- IMXCCMState *s = container_of(dev, IMXCCMState, busdev.qdev);
+ IMXCCMState *s = IMX_CCM(dev);
s->ccmr = 0x074b0b7b;
s->pdr0 = 0xff870b48;
@@ -279,7 +283,7 @@
static int imx_ccm_init(SysBusDevice *dev)
{
- IMXCCMState *s = FROM_SYSBUS(typeof(*s), dev);
+ IMXCCMState *s = IMX_CCM(dev);
memory_region_init_io(&s->iomem, OBJECT(dev), &imx_ccm_ops, s,
"imx_ccm", 0x1000);
@@ -308,7 +312,7 @@
}
static const TypeInfo imx_ccm_info = {
- .name = "imx_ccm",
+ .name = TYPE_IMX_CCM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IMXCCMState),
.class_init = imx_ccm_class_init,
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 4a74856..2838866 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -821,6 +821,7 @@
k->class_id = PCI_CLASS_MEMORY_RAM;
dc->reset = ivshmem_reset;
dc->props = ivshmem_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo ivshmem_info = {
diff --git a/hw/misc/lm32_sys.c b/hw/misc/lm32_sys.c
index 060a5bf..9bdb781 100644
--- a/hw/misc/lm32_sys.c
+++ b/hw/misc/lm32_sys.c
@@ -44,8 +44,12 @@
#define MAX_TESTNAME_LEN 16
+#define TYPE_LM32_SYS "lm32-sys"
+#define LM32_SYS(obj) OBJECT_CHECK(LM32SysState, (obj), TYPE_LM32_SYS)
+
struct LM32SysState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t base;
uint32_t regs[R_MAX];
@@ -104,7 +108,7 @@
static void sys_reset(DeviceState *d)
{
- LM32SysState *s = container_of(d, LM32SysState, busdev.qdev);
+ LM32SysState *s = LM32_SYS(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -115,7 +119,7 @@
static int lm32_sys_init(SysBusDevice *dev)
{
- LM32SysState *s = FROM_SYSBUS(typeof(*s), dev);
+ LM32SysState *s = LM32_SYS(dev);
memory_region_init_io(&s->iomem, OBJECT(dev), &sys_ops , s,
"sys", R_MAX * 4);
@@ -158,7 +162,7 @@
}
static const TypeInfo lm32_sys_info = {
- .name = "lm32-sys",
+ .name = TYPE_LM32_SYS,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LM32SysState),
.class_init = lm32_sys_class_init,
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index c0fd7da..c811b95 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -128,7 +128,7 @@
int64_t d;
unsigned int counter;
- d = muldiv64(qemu_get_clock_ns(vm_clock) - s->load_time,
+ d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->load_time,
CUDA_TIMER_FREQ, get_ticks_per_sec());
if (s->index == 0) {
/* the timer goes down from latch to -1 (period of latch + 2) */
@@ -147,7 +147,7 @@
static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
{
CUDA_DPRINTF("T%d.counter=%d\n", 1 + (ti->timer == NULL), val);
- ti->load_time = qemu_get_clock_ns(vm_clock);
+ ti->load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ti->counter_value = val;
cuda_timer_update(s, ti, ti->load_time);
}
@@ -191,10 +191,10 @@
if (!ti->timer)
return;
if ((s->acr & T1MODE) != T1MODE_CONT) {
- qemu_del_timer(ti->timer);
+ timer_del(ti->timer);
} else {
ti->next_irq_time = get_next_irq_time(ti, current_time);
- qemu_mod_timer(ti->timer, ti->next_irq_time);
+ timer_mod(ti->timer, ti->next_irq_time);
}
}
@@ -304,7 +304,7 @@
break;
case 4:
s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
+ cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
break;
case 5:
s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
@@ -313,12 +313,12 @@
break;
case 6:
s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
+ cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
break;
case 7:
s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
s->ifr &= ~T1_INT;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
+ cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
break;
case 8:
s->timers[1].latch = val;
@@ -332,7 +332,7 @@
break;
case 11:
s->acr = val;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
+ cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
cuda_update(s);
break;
case 12:
@@ -463,8 +463,8 @@
obuf[1] = 0x40; /* polled data */
cuda_send_packet_to_host(s, obuf, olen + 2);
}
- qemu_mod_timer(s->adb_poll_timer,
- qemu_get_clock_ns(vm_clock) +
+ timer_mod(s->adb_poll_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
(get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
}
@@ -481,11 +481,11 @@
if (autopoll != s->autopoll) {
s->autopoll = autopoll;
if (autopoll) {
- qemu_mod_timer(s->adb_poll_timer,
- qemu_get_clock_ns(vm_clock) +
+ timer_mod(s->adb_poll_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
(get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
} else {
- qemu_del_timer(s->adb_poll_timer);
+ timer_del(s->adb_poll_timer);
}
}
obuf[0] = CUDA_PACKET;
@@ -494,14 +494,14 @@
break;
case CUDA_SET_TIME:
ti = (((uint32_t)data[1]) << 24) + (((uint32_t)data[2]) << 16) + (((uint32_t)data[3]) << 8) + data[4];
- s->tick_offset = ti - (qemu_get_clock_ns(vm_clock) / get_ticks_per_sec());
+ s->tick_offset = ti - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / get_ticks_per_sec());
obuf[0] = CUDA_PACKET;
obuf[1] = 0;
obuf[2] = 0;
cuda_send_packet_to_host(s, obuf, 3);
break;
case CUDA_GET_TIME:
- ti = s->tick_offset + (qemu_get_clock_ns(vm_clock) / get_ticks_per_sec());
+ ti = s->tick_offset + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / get_ticks_per_sec());
obuf[0] = CUDA_PACKET;
obuf[1] = 0;
obuf[2] = 0;
@@ -689,12 +689,12 @@
CUDAState *s = CUDA(dev);
struct tm tm;
- s->timers[0].timer = qemu_new_timer_ns(vm_clock, cuda_timer1, s);
+ s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer1, s);
qemu_get_timedate(&tm, 0);
s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
- s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s);
+ s->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_adb_poll, s);
}
static void cuda_initfn(Object *obj)
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index c0d0bf7..9cc33d8 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -245,10 +245,10 @@
switch (addr) {
case 0x38:
- value = qemu_get_clock_ns(vm_clock);
+ value = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
break;
case 0x3c:
- value = qemu_get_clock_ns(vm_clock) >> 32;
+ value = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 32;
break;
}
diff --git a/hw/misc/milkymist-hpdmc.c b/hw/misc/milkymist-hpdmc.c
index a498881..aef135e 100644
--- a/hw/misc/milkymist-hpdmc.c
+++ b/hw/misc/milkymist-hpdmc.c
@@ -40,8 +40,13 @@
IODELAY_PLL2_LOCKED = (1<<7),
};
+#define TYPE_MILKYMIST_HPDMC "milkymist-hpdmc"
+#define MILKYMIST_HPDMC(obj) \
+ OBJECT_CHECK(MilkymistHpdmcState, (obj), TYPE_MILKYMIST_HPDMC)
+
struct MilkymistHpdmcState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion regs_region;
uint32_t regs[R_MAX];
@@ -111,7 +116,7 @@
static void milkymist_hpdmc_reset(DeviceState *d)
{
- MilkymistHpdmcState *s = container_of(d, MilkymistHpdmcState, busdev.qdev);
+ MilkymistHpdmcState *s = MILKYMIST_HPDMC(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -125,7 +130,7 @@
static int milkymist_hpdmc_init(SysBusDevice *dev)
{
- MilkymistHpdmcState *s = FROM_SYSBUS(typeof(*s), dev);
+ MilkymistHpdmcState *s = MILKYMIST_HPDMC(dev);
memory_region_init_io(&s->regs_region, OBJECT(dev), &hpdmc_mmio_ops, s,
"milkymist-hpdmc", R_MAX * 4);
@@ -156,7 +161,7 @@
}
static const TypeInfo milkymist_hpdmc_info = {
- .name = "milkymist-hpdmc",
+ .name = TYPE_MILKYMIST_HPDMC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistHpdmcState),
.class_init = milkymist_hpdmc_class_init,
diff --git a/hw/misc/milkymist-pfpu.c b/hw/misc/milkymist-pfpu.c
index 2b64ee7..b3b2143 100644
--- a/hw/misc/milkymist-pfpu.c
+++ b/hw/misc/milkymist-pfpu.c
@@ -116,8 +116,13 @@
};
#endif
+#define TYPE_MILKYMIST_PFPU "milkymist-pfpu"
+#define MILKYMIST_PFPU(obj) \
+ OBJECT_CHECK(MilkymistPFPUState, (obj), TYPE_MILKYMIST_PFPU)
+
struct MilkymistPFPUState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion regs_region;
CharDriverState *chr;
qemu_irq irq;
@@ -473,7 +478,7 @@
static void milkymist_pfpu_reset(DeviceState *d)
{
- MilkymistPFPUState *s = container_of(d, MilkymistPFPUState, busdev.qdev);
+ MilkymistPFPUState *s = MILKYMIST_PFPU(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -493,7 +498,7 @@
static int milkymist_pfpu_init(SysBusDevice *dev)
{
- MilkymistPFPUState *s = FROM_SYSBUS(typeof(*s), dev);
+ MilkymistPFPUState *s = MILKYMIST_PFPU(dev);
sysbus_init_irq(dev, &s->irq);
@@ -530,7 +535,7 @@
}
static const TypeInfo milkymist_pfpu_info = {
- .name = "milkymist-pfpu",
+ .name = TYPE_MILKYMIST_PFPU,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistPFPUState),
.class_init = milkymist_pfpu_class_init,
diff --git a/hw/misc/mst_fpga.c b/hw/misc/mst_fpga.c
index 604be5e..c96810f 100644
--- a/hw/misc/mst_fpga.c
+++ b/hw/misc/mst_fpga.c
@@ -35,25 +35,30 @@
#define MST_PCMCIA_CD0_IRQ 9
#define MST_PCMCIA_CD1_IRQ 13
+#define TYPE_MAINSTONE_FPGA "mainstone-fpga"
+#define MAINSTONE_FPGA(obj) \
+ OBJECT_CHECK(mst_irq_state, (obj), TYPE_MAINSTONE_FPGA)
+
typedef struct mst_irq_state{
- SysBusDevice busdev;
- MemoryRegion iomem;
+ SysBusDevice parent_obj;
- qemu_irq parent;
+ MemoryRegion iomem;
- uint32_t prev_level;
- uint32_t leddat1;
- uint32_t leddat2;
- uint32_t ledctrl;
- uint32_t gpswr;
- uint32_t mscwr1;
- uint32_t mscwr2;
- uint32_t mscwr3;
- uint32_t mscrd;
- uint32_t intmskena;
- uint32_t intsetclr;
- uint32_t pcmcia0;
- uint32_t pcmcia1;
+ qemu_irq parent;
+
+ uint32_t prev_level;
+ uint32_t leddat1;
+ uint32_t leddat2;
+ uint32_t ledctrl;
+ uint32_t gpswr;
+ uint32_t mscwr1;
+ uint32_t mscwr2;
+ uint32_t mscwr3;
+ uint32_t mscrd;
+ uint32_t intmskena;
+ uint32_t intsetclr;
+ uint32_t pcmcia0;
+ uint32_t pcmcia1;
}mst_irq_state;
static void
@@ -194,24 +199,23 @@
return 0;
}
-static int mst_fpga_init(SysBusDevice *dev)
+static int mst_fpga_init(SysBusDevice *sbd)
{
- mst_irq_state *s;
+ DeviceState *dev = DEVICE(sbd);
+ mst_irq_state *s = MAINSTONE_FPGA(dev);
- s = FROM_SYSBUS(mst_irq_state, dev);
+ s->pcmcia0 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
+ s->pcmcia1 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
- s->pcmcia0 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
- s->pcmcia1 = MST_PCMCIAx_READY | MST_PCMCIAx_nCD;
+ sysbus_init_irq(sbd, &s->parent);
- sysbus_init_irq(dev, &s->parent);
+ /* alloc the external 16 irqs */
+ qdev_init_gpio_in(dev, mst_fpga_set_irq, MST_NUM_IRQS);
- /* alloc the external 16 irqs */
- qdev_init_gpio_in(&dev->qdev, mst_fpga_set_irq, MST_NUM_IRQS);
-
- memory_region_init_io(&s->iomem, OBJECT(s), &mst_fpga_ops, s,
- "fpga", 0x00100000);
- sysbus_init_mmio(dev, &s->iomem);
- return 0;
+ memory_region_init_io(&s->iomem, OBJECT(s), &mst_fpga_ops, s,
+ "fpga", 0x00100000);
+ sysbus_init_mmio(sbd, &s->iomem);
+ return 0;
}
static VMStateDescription vmstate_mst_fpga_regs = {
@@ -249,7 +253,7 @@
}
static const TypeInfo mst_fpga_info = {
- .name = "mainstone-fpga",
+ .name = TYPE_MAINSTONE_FPGA,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(mst_irq_state),
.class_init = mst_fpga_class_init,
diff --git a/hw/misc/pc-testdev.c b/hw/misc/pc-testdev.c
index 699a16f..18e94e0 100644
--- a/hw/misc/pc-testdev.c
+++ b/hw/misc/pc-testdev.c
@@ -49,6 +49,7 @@
ISADevice parent_obj;
MemoryRegion ioport;
+ MemoryRegion ioport_byte;
MemoryRegion flush;
MemoryRegion irq;
MemoryRegion iomem;
@@ -80,13 +81,20 @@
unsigned len)
{
PCTestdev *dev = opaque;
- dev->ioport_data = data;
+ int bits = len * 8;
+ int start_bit = (addr & 3) * 8;
+ uint32_t mask = ((uint32_t)-1 >> (32 - bits)) << start_bit;
+ dev->ioport_data &= ~mask;
+ dev->ioport_data |= data << start_bit;
}
static uint64_t test_ioport_read(void *opaque, hwaddr addr, unsigned len)
{
PCTestdev *dev = opaque;
- return dev->ioport_data;
+ int bits = len * 8;
+ int start_bit = (addr & 3) * 8;
+ uint32_t mask = ((uint32_t)-1 >> (32 - bits)) << start_bit;
+ return (dev->ioport_data & mask) >> start_bit;
}
static const MemoryRegionOps test_ioport_ops = {
@@ -95,6 +103,16 @@
.endianness = DEVICE_LITTLE_ENDIAN,
};
+static const MemoryRegionOps test_ioport_byte_ops = {
+ .read = test_ioport_read,
+ .write = test_ioport_write,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 1,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
static void test_flush_page(void *opaque, hwaddr addr, uint64_t data,
unsigned len)
{
@@ -122,7 +140,6 @@
PCTestdev *dev = opaque;
uint64_t ret = 0;
memcpy(&ret, &dev->iomem_buf[addr], len);
- ret = le64_to_cpu(ret);
return ret;
}
@@ -131,7 +148,6 @@
unsigned len)
{
PCTestdev *dev = opaque;
- val = cpu_to_le64(val);
memcpy(&dev->iomem_buf[addr], &val, len);
dev->iomem_buf[addr] = val;
}
@@ -151,6 +167,9 @@
memory_region_init_io(&dev->ioport, OBJECT(dev), &test_ioport_ops, dev,
"pc-testdev-ioport", 4);
+ memory_region_init_io(&dev->ioport_byte, OBJECT(dev),
+ &test_ioport_byte_ops, dev,
+ "pc-testdev-ioport-byte", 4);
memory_region_init_io(&dev->flush, OBJECT(dev), &test_flush_ops, dev,
"pc-testdev-flush-page", 4);
memory_region_init_io(&dev->irq, OBJECT(dev), &test_irq_ops, dev,
@@ -160,6 +179,7 @@
memory_region_add_subregion(io, 0xe0, &dev->ioport);
memory_region_add_subregion(io, 0xe4, &dev->flush);
+ memory_region_add_subregion(io, 0xe8, &dev->ioport_byte);
memory_region_add_subregion(io, 0x2000, &dev->irq);
memory_region_add_subregion(mem, 0xff000000, &dev->iomem);
}
@@ -168,6 +188,7 @@
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->realize = testdev_realizefn;
}
diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c
index d69ff33..ca53b3f 100644
--- a/hw/misc/pci-testdev.c
+++ b/hw/misc/pci-testdev.c
@@ -315,6 +315,7 @@
k->revision = 0x00;
k->class_id = PCI_CLASS_OTHERS;
dc->desc = "PCI Test Device";
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->reset = qdev_pci_testdev_reset;
}
diff --git a/hw/misc/puv3_pm.c b/hw/misc/puv3_pm.c
index 5592560..37f2369 100644
--- a/hw/misc/puv3_pm.c
+++ b/hw/misc/puv3_pm.c
@@ -14,8 +14,12 @@
#undef DEBUG_PUV3
#include "hw/unicore32/puv3.h"
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PUV3_PM "puv3_pm"
+#define PUV3_PM(obj) OBJECT_CHECK(PUV3PMState, (obj), TYPE_PUV3_PM)
+
+typedef struct PUV3PMState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t reg_PMCR;
@@ -116,7 +120,7 @@
static int puv3_pm_init(SysBusDevice *dev)
{
- PUV3PMState *s = FROM_SYSBUS(PUV3PMState, dev);
+ PUV3PMState *s = PUV3_PM(dev);
s->reg_PCGR = 0x0;
@@ -135,7 +139,7 @@
}
static const TypeInfo puv3_pm_info = {
- .name = "puv3_pm",
+ .name = TYPE_PUV3_PM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PUV3PMState),
.class_init = puv3_pm_class_init,
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
index 7bb49a5..b64e3bb 100644
--- a/hw/misc/pvpanic.c
+++ b/hw/misc/pvpanic.c
@@ -97,29 +97,24 @@
{
ISADevice *d = ISA_DEVICE(dev);
PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
+ FWCfgState *fw_cfg = fw_cfg_find();
+ uint16_t *pvpanic_port;
+
+ if (!fw_cfg) {
+ return;
+ }
+
+ pvpanic_port = g_malloc(sizeof(*pvpanic_port));
+ *pvpanic_port = cpu_to_le16(s->ioport);
+ fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
+ sizeof(*pvpanic_port));
isa_register_ioport(d, &s->io, s->ioport);
}
-static void pvpanic_fw_cfg(ISADevice *dev, FWCfgState *fw_cfg)
-{
- PVPanicState *s = ISA_PVPANIC_DEVICE(dev);
- uint16_t *pvpanic_port = g_malloc(sizeof(*pvpanic_port));
- *pvpanic_port = cpu_to_le16(s->ioport);
-
- fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port,
- sizeof(*pvpanic_port));
-}
-
void pvpanic_init(ISABus *bus)
{
- ISADevice *dev;
- FWCfgState *fw_cfg = fw_cfg_find();
- if (!fw_cfg) {
- return;
- }
- dev = isa_create_simple (bus, TYPE_ISA_PVPANIC_DEVICE);
- pvpanic_fw_cfg(dev, fw_cfg);
+ isa_create_simple(bus, TYPE_ISA_PVPANIC_DEVICE);
}
static Property pvpanic_isa_properties[] = {
@@ -132,8 +127,8 @@
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = pvpanic_isa_realizefn;
- dc->no_user = 1;
dc->props = pvpanic_isa_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static TypeInfo pvpanic_isa_info = {
diff --git a/hw/misc/sga.c b/hw/misc/sga.c
index 08803e7..83d2fd9 100644
--- a/hw/misc/sga.c
+++ b/hw/misc/sga.c
@@ -47,6 +47,7 @@
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
dc->realize = sga_realizefn;
dc->desc = "Serial Graphics Adapter";
}
diff --git a/hw/misc/slavio_misc.c b/hw/misc/slavio_misc.c
index 00d9542..767544e 100644
--- a/hw/misc/slavio_misc.c
+++ b/hw/misc/slavio_misc.c
@@ -34,8 +34,12 @@
* This also includes the PMC CPU idle controller.
*/
+#define TYPE_SLAVIO_MISC "slavio_misc"
+#define SLAVIO_MISC(obj) OBJECT_CHECK(MiscState, (obj), TYPE_SLAVIO_MISC)
+
typedef struct MiscState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion cfg_iomem;
MemoryRegion diag_iomem;
MemoryRegion mdm_iomem;
@@ -53,8 +57,12 @@
uint16_t leds;
} MiscState;
+#define TYPE_APC "apc"
+#define APC(obj) OBJECT_CHECK(APCState, (obj), TYPE_APC)
+
typedef struct APCState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq cpu_halt;
} APCState;
@@ -88,7 +96,7 @@
static void slavio_misc_reset(DeviceState *d)
{
- MiscState *s = container_of(d, MiscState, busdev.qdev);
+ MiscState *s = SLAVIO_MISC(d);
// Diagnostic and system control registers not cleared in reset
s->config = s->aux1 = s->aux2 = s->mctrl = 0;
@@ -407,7 +415,7 @@
static int apc_init1(SysBusDevice *dev)
{
- APCState *s = FROM_SYSBUS(APCState, dev);
+ APCState *s = APC(dev);
sysbus_init_irq(dev, &s->cpu_halt);
@@ -418,52 +426,53 @@
return 0;
}
-static int slavio_misc_init1(SysBusDevice *dev)
+static int slavio_misc_init1(SysBusDevice *sbd)
{
- MiscState *s = FROM_SYSBUS(MiscState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ MiscState *s = SLAVIO_MISC(dev);
- sysbus_init_irq(dev, &s->irq);
- sysbus_init_irq(dev, &s->fdc_tc);
+ sysbus_init_irq(sbd, &s->irq);
+ sysbus_init_irq(sbd, &s->fdc_tc);
/* 8 bit registers */
/* Slavio control */
memory_region_init_io(&s->cfg_iomem, OBJECT(s), &slavio_cfg_mem_ops, s,
"configuration", MISC_SIZE);
- sysbus_init_mmio(dev, &s->cfg_iomem);
+ sysbus_init_mmio(sbd, &s->cfg_iomem);
/* Diagnostics */
memory_region_init_io(&s->diag_iomem, OBJECT(s), &slavio_diag_mem_ops, s,
"diagnostic", MISC_SIZE);
- sysbus_init_mmio(dev, &s->diag_iomem);
+ sysbus_init_mmio(sbd, &s->diag_iomem);
/* Modem control */
memory_region_init_io(&s->mdm_iomem, OBJECT(s), &slavio_mdm_mem_ops, s,
"modem", MISC_SIZE);
- sysbus_init_mmio(dev, &s->mdm_iomem);
+ sysbus_init_mmio(sbd, &s->mdm_iomem);
/* 16 bit registers */
/* ss600mp diag LEDs */
memory_region_init_io(&s->led_iomem, OBJECT(s), &slavio_led_mem_ops, s,
"leds", MISC_SIZE);
- sysbus_init_mmio(dev, &s->led_iomem);
+ sysbus_init_mmio(sbd, &s->led_iomem);
/* 32 bit registers */
/* System control */
memory_region_init_io(&s->sysctrl_iomem, OBJECT(s), &slavio_sysctrl_mem_ops, s,
"system-control", MISC_SIZE);
- sysbus_init_mmio(dev, &s->sysctrl_iomem);
+ sysbus_init_mmio(sbd, &s->sysctrl_iomem);
/* AUX 1 (Misc System Functions) */
memory_region_init_io(&s->aux1_iomem, OBJECT(s), &slavio_aux1_mem_ops, s,
"misc-system-functions", MISC_SIZE);
- sysbus_init_mmio(dev, &s->aux1_iomem);
+ sysbus_init_mmio(sbd, &s->aux1_iomem);
/* AUX 2 (Software Powerdown Control) */
memory_region_init_io(&s->aux2_iomem, OBJECT(s), &slavio_aux2_mem_ops, s,
"software-powerdown-control", MISC_SIZE);
- sysbus_init_mmio(dev, &s->aux2_iomem);
+ sysbus_init_mmio(sbd, &s->aux2_iomem);
- qdev_init_gpio_in(&dev->qdev, slavio_set_power_fail, 1);
+ qdev_init_gpio_in(dev, slavio_set_power_fail, 1);
return 0;
}
@@ -479,7 +488,7 @@
}
static const TypeInfo slavio_misc_info = {
- .name = "slavio_misc",
+ .name = TYPE_SLAVIO_MISC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MiscState),
.class_init = slavio_misc_class_init,
@@ -493,7 +502,7 @@
}
static const TypeInfo apc_info = {
- .name = "apc",
+ .name = TYPE_APC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MiscState),
.class_init = apc_class_init,
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index 54af34a..a1c08fb 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -276,8 +276,8 @@
VFIODevice *vdev = opaque;
if (vdev->intx.pending) {
- qemu_mod_timer(vdev->intx.mmap_timer,
- qemu_get_clock_ms(vm_clock) + vdev->intx.mmap_timeout);
+ timer_mod(vdev->intx.mmap_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + vdev->intx.mmap_timeout);
return;
}
@@ -300,8 +300,8 @@
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 1);
vfio_mmap_set_enabled(vdev, false);
if (vdev->intx.mmap_timeout) {
- qemu_mod_timer(vdev->intx.mmap_timer,
- qemu_get_clock_ms(vm_clock) + vdev->intx.mmap_timeout);
+ timer_mod(vdev->intx.mmap_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + vdev->intx.mmap_timeout);
}
}
@@ -543,7 +543,7 @@
{
int fd;
- qemu_del_timer(vdev->intx.mmap_timer);
+ timer_del(vdev->intx.mmap_timer);
vfio_disable_intx_kvm(vdev);
vfio_disable_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
vdev->intx.pending = false;
@@ -3176,7 +3176,7 @@
}
if (vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1)) {
- vdev->intx.mmap_timer = qemu_new_timer_ms(vm_clock,
+ vdev->intx.mmap_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
vfio_intx_mmap_enable, vdev);
pci_device_set_intx_routing_notifier(&vdev->pdev, vfio_update_irq);
ret = vfio_enable_intx(vdev);
@@ -3210,7 +3210,7 @@
pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
vfio_disable_interrupts(vdev);
if (vdev->intx.mmap_timer) {
- qemu_free_timer(vdev->intx.mmap_timer);
+ timer_free(vdev->intx.mmap_timer);
}
vfio_teardown_msi(vdev);
vfio_unmap_bars(vdev);
@@ -3299,6 +3299,7 @@
dc->props = vfio_pci_dev_properties;
dc->vmsd = &vfio_pci_vmstate;
dc->desc = "VFIO-based PCI device assignment";
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
pdc->init = vfio_initfn;
pdc->exit = vfio_exitfn;
pdc->config_read = vfio_pci_read_config;
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index fc7a85f..e42a5b0 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -114,8 +114,12 @@
RESET_MAX
} ResetValues;
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr"
+#define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR)
+
+typedef struct ZynqSLCRState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
union {
@@ -158,9 +162,8 @@
static void zynq_slcr_reset(DeviceState *d)
{
+ ZynqSLCRState *s = ZYNQ_SLCR(d);
int i;
- ZynqSLCRState *s =
- FROM_SYSBUS(ZynqSLCRState, SYS_BUS_DEVICE(d));
DB_PRINT("RESET\n");
@@ -492,7 +495,7 @@
static int zynq_slcr_init(SysBusDevice *dev)
{
- ZynqSLCRState *s = FROM_SYSBUS(ZynqSLCRState, dev);
+ ZynqSLCRState *s = ZYNQ_SLCR(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &slcr_ops, s, "slcr", 0x1000);
sysbus_init_mmio(dev, &s->iomem);
@@ -523,7 +526,7 @@
static const TypeInfo zynq_slcr_info = {
.class_init = zynq_slcr_class_init,
- .name = "xilinx,zynq_slcr",
+ .name = TYPE_ZYNQ_SLCR,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ZynqSLCRState),
};
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index ac929cb..4a355bb 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -315,8 +315,12 @@
desc[1] |= len;
}
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_CADENCE_GEM "cadence_gem"
+#define GEM(obj) OBJECT_CHECK(GemState, (obj), TYPE_CADENCE_GEM)
+
+typedef struct GemState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
NICState *nic;
NICConf conf;
@@ -945,7 +949,7 @@
static void gem_reset(DeviceState *d)
{
- GemState *s = FROM_SYSBUS(GemState, SYS_BUS_DEVICE(d));
+ GemState *s = GEM(d);
DB_PRINT("\n");
@@ -1155,22 +1159,22 @@
.link_status_changed = gem_set_link,
};
-static int gem_init(SysBusDevice *dev)
+static int gem_init(SysBusDevice *sbd)
{
- GemState *s;
+ DeviceState *dev = DEVICE(sbd);
+ GemState *s = GEM(dev);
DB_PRINT("\n");
- s = FROM_SYSBUS(GemState, dev);
gem_init_register_masks(s);
memory_region_init_io(&s->iomem, OBJECT(s), &gem_ops, s,
"enet", sizeof(s->regs));
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_gem_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->id, s);
return 0;
}
@@ -1206,10 +1210,10 @@
}
static const TypeInfo gem_info = {
- .class_init = gem_class_init,
- .name = "cadence_gem",
+ .name = TYPE_CADENCE_GEM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(GemState),
+ .class_init = gem_class_init,
};
static void gem_register_types(void)
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 049aa70..789d385 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -274,7 +274,7 @@
static void do_software_reset(dp8393xState *s)
{
- qemu_del_timer(s->watchdog);
+ timer_del(s->watchdog);
s->regs[SONIC_CR] &= ~(SONIC_CR_LCAM | SONIC_CR_RRRA | SONIC_CR_TXP | SONIC_CR_HTX);
s->regs[SONIC_CR] |= SONIC_CR_RST | SONIC_CR_RXDIS;
@@ -286,14 +286,14 @@
int64_t delay;
if (s->regs[SONIC_CR] & SONIC_CR_STP) {
- qemu_del_timer(s->watchdog);
+ timer_del(s->watchdog);
return;
}
ticks = s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0];
- s->wt_last_update = qemu_get_clock_ns(vm_clock);
+ s->wt_last_update = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
delay = get_ticks_per_sec() * ticks / 5000000;
- qemu_mod_timer(s->watchdog, s->wt_last_update + delay);
+ timer_mod(s->watchdog, s->wt_last_update + delay);
}
static void update_wt_regs(dp8393xState *s)
@@ -302,11 +302,11 @@
uint32_t val;
if (s->regs[SONIC_CR] & SONIC_CR_STP) {
- qemu_del_timer(s->watchdog);
+ timer_del(s->watchdog);
return;
}
- elapsed = s->wt_last_update - qemu_get_clock_ns(vm_clock);
+ elapsed = s->wt_last_update - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
val = s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0];
val -= elapsed / 5000000;
s->regs[SONIC_WT1] = (val >> 16) & 0xffff;
@@ -838,7 +838,7 @@
static void nic_reset(void *opaque)
{
dp8393xState *s = opaque;
- qemu_del_timer(s->watchdog);
+ timer_del(s->watchdog);
s->regs[SONIC_CR] = SONIC_CR_RST | SONIC_CR_STP | SONIC_CR_RXDIS;
s->regs[SONIC_DCR] &= ~(SONIC_DCR_EXBUS | SONIC_DCR_LBR);
@@ -866,8 +866,8 @@
memory_region_del_subregion(s->address_space, &s->mmio);
memory_region_destroy(&s->mmio);
- qemu_del_timer(s->watchdog);
- qemu_free_timer(s->watchdog);
+ timer_del(s->watchdog);
+ timer_free(s->watchdog);
g_free(s);
}
@@ -896,7 +896,7 @@
s->memory_rw = memory_rw;
s->it_shift = it_shift;
s->irq = irq;
- s->watchdog = qemu_new_timer_ns(vm_clock, dp8393x_watchdog, s);
+ s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s);
s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */
s->conf.macaddr = nd->macaddr;
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index b952d8d..f5ebed4 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -190,7 +190,7 @@
e1000_link_down(s);
s->phy_reg[PHY_STATUS] &= ~MII_SR_AUTONEG_COMPLETE;
DBGOUT(PHY, "Start link auto negotiation\n");
- qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500);
+ timer_mod(s->autoneg_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
}
}
@@ -306,7 +306,7 @@
uint8_t *macaddr = d->conf.macaddr.a;
int i;
- qemu_del_timer(d->autoneg_timer);
+ timer_del(d->autoneg_timer);
memset(d->phy_reg, 0, sizeof d->phy_reg);
memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
memset(d->mac_reg, 0, sizeof d->mac_reg);
@@ -1184,7 +1184,7 @@
s->phy_reg[PHY_CTRL] & MII_CR_RESTART_AUTO_NEG &&
!(s->phy_reg[PHY_STATUS] & MII_SR_AUTONEG_COMPLETE)) {
nc->link_down = false;
- qemu_mod_timer(s->autoneg_timer, qemu_get_clock_ms(vm_clock) + 500);
+ timer_mod(s->autoneg_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 500);
}
return 0;
@@ -1314,8 +1314,8 @@
{
E1000State *d = E1000(dev);
- qemu_del_timer(d->autoneg_timer);
- qemu_free_timer(d->autoneg_timer);
+ timer_del(d->autoneg_timer);
+ timer_free(d->autoneg_timer);
memory_region_destroy(&d->mmio);
memory_region_destroy(&d->io);
qemu_del_nic(d->nic);
@@ -1370,7 +1370,7 @@
add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0");
- d->autoneg_timer = qemu_new_timer_ms(vm_clock, e1000_autoneg_timer, d);
+ d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d);
return 0;
}
@@ -1400,6 +1400,7 @@
k->device_id = E1000_DEVID;
k->revision = 0x03;
k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
dc->desc = "Intel Gigabit Ethernet";
dc->reset = qdev_e1000_reset;
dc->vmsd = &vmstate_e1000;
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index e0befb2..ffa60d5 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -47,6 +47,7 @@
#include "hw/nvram/eeprom93xx.h"
#include "sysemu/sysemu.h"
#include "sysemu/dma.h"
+#include "qemu/bitops.h"
/* QEMU sends frames smaller than 60 bytes to ethernet nics.
* Such frames are rejected by real nics and their emulations.
@@ -105,7 +106,6 @@
#define PCI_IO_SIZE 64
#define PCI_FLASH_SIZE (128 * KiB)
-#define BIT(n) (1 << (n))
#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
/* The SCB accepts the following controls for the Tx and Rx units: */
@@ -2083,6 +2083,7 @@
info = eepro100_get_class_by_name(object_class_get_name(klass));
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
dc->props = e100_properties;
dc->desc = info->desc;
k->vendor_id = PCI_VENDOR_ID_INTEL;
diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
index ab9a215..78ebbbc 100644
--- a/hw/net/etraxfs_eth.c
+++ b/hw/net/etraxfs_eth.c
@@ -322,9 +322,14 @@
#define R_STAT 0x0b
#define FS_ETH_MAX_REGS 0x17
-struct fs_eth
+#define TYPE_ETRAX_FS_ETH "etraxfs-eth"
+#define ETRAX_FS_ETH(obj) \
+ OBJECT_CHECK(ETRAXFSEthState, (obj), TYPE_ETRAX_FS_ETH)
+
+typedef struct ETRAXFSEthState
{
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion mmio;
NICState *nic;
NICConf conf;
@@ -349,9 +354,9 @@
/* PHY. */
struct qemu_phy phy;
-};
+} ETRAXFSEthState;
-static void eth_validate_duplex(struct fs_eth *eth)
+static void eth_validate_duplex(ETRAXFSEthState *eth)
{
struct qemu_phy *phy;
unsigned int phy_duplex;
@@ -382,7 +387,7 @@
static uint64_t
eth_read(void *opaque, hwaddr addr, unsigned int size)
{
- struct fs_eth *eth = opaque;
+ ETRAXFSEthState *eth = opaque;
uint32_t r = 0;
addr >>= 2;
@@ -399,7 +404,7 @@
return r;
}
-static void eth_update_ma(struct fs_eth *eth, int ma)
+static void eth_update_ma(ETRAXFSEthState *eth, int ma)
{
int reg;
int i = 0;
@@ -428,7 +433,7 @@
eth_write(void *opaque, hwaddr addr,
uint64_t val64, unsigned int size)
{
- struct fs_eth *eth = opaque;
+ ETRAXFSEthState *eth = opaque;
uint32_t value = val64;
addr >>= 2;
@@ -472,7 +477,7 @@
/* The ETRAX FS has a groupt address table (GAT) which works like a k=1 bloom
filter dropping group addresses we have not joined. The filter has 64
bits (m). The has function is a simple nible xor of the group addr. */
-static int eth_match_groupaddr(struct fs_eth *eth, const unsigned char *sa)
+static int eth_match_groupaddr(ETRAXFSEthState *eth, const unsigned char *sa)
{
unsigned int hsh;
int m_individual = eth->regs[RW_REC_CTRL] & 4;
@@ -523,7 +528,7 @@
static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
{
unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- struct fs_eth *eth = qemu_get_nic_opaque(nc);
+ ETRAXFSEthState *eth = qemu_get_nic_opaque(nc);
int use_ma0 = eth->regs[RW_REC_CTRL] & 1;
int use_ma1 = eth->regs[RW_REC_CTRL] & 2;
int r_bcast = eth->regs[RW_REC_CTRL] & 8;
@@ -547,12 +552,12 @@
/* FIXME: Find another way to pass on the fake csum. */
etraxfs_dmac_input(eth->dma_in, (void *)buf, size + 4, 1);
- return size;
+ return size;
}
static int eth_tx_push(void *opaque, unsigned char *buf, int len, bool eop)
{
- struct fs_eth *eth = opaque;
+ ETRAXFSEthState *eth = opaque;
D(printf("%s buf=%p len=%d\n", __func__, buf, len));
qemu_send_packet(qemu_get_queue(eth->nic), buf, len);
@@ -561,7 +566,7 @@
static void eth_set_link(NetClientState *nc)
{
- struct fs_eth *eth = qemu_get_nic_opaque(nc);
+ ETRAXFSEthState *eth = qemu_get_nic_opaque(nc);
D(printf("%s %d\n", __func__, nc->link_down));
eth->phy.link = !nc->link_down;
}
@@ -578,7 +583,7 @@
static void eth_cleanup(NetClientState *nc)
{
- struct fs_eth *eth = qemu_get_nic_opaque(nc);
+ ETRAXFSEthState *eth = qemu_get_nic_opaque(nc);
/* Disconnect the client. */
eth->dma_out->client.push = NULL;
@@ -597,9 +602,10 @@
.link_status_changed = eth_set_link,
};
-static int fs_eth_init(SysBusDevice *dev)
+static int fs_eth_init(SysBusDevice *sbd)
{
- struct fs_eth *s = FROM_SYSBUS(typeof(*s), dev);
+ DeviceState *dev = DEVICE(sbd);
+ ETRAXFSEthState *s = ETRAX_FS_ETH(dev);
if (!s->dma_out || !s->dma_in) {
hw_error("Unconnected ETRAX-FS Ethernet MAC.\n");
@@ -612,11 +618,11 @@
memory_region_init_io(&s->mmio, OBJECT(dev), ð_ops, s,
"etraxfs-eth", 0x5c);
- sysbus_init_mmio(dev, &s->mmio);
+ sysbus_init_mmio(sbd, &s->mmio);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf,
- object_get_typename(OBJECT(s)), dev->qdev.id, s);
+ object_get_typename(OBJECT(s)), dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
@@ -626,10 +632,10 @@
}
static Property etraxfs_eth_properties[] = {
- DEFINE_PROP_UINT32("phyaddr", struct fs_eth, phyaddr, 1),
- DEFINE_PROP_PTR("dma_out", struct fs_eth, vdma_out),
- DEFINE_PROP_PTR("dma_in", struct fs_eth, vdma_in),
- DEFINE_NIC_PROPERTIES(struct fs_eth, conf),
+ DEFINE_PROP_UINT32("phyaddr", ETRAXFSEthState, phyaddr, 1),
+ DEFINE_PROP_PTR("dma_out", ETRAXFSEthState, vdma_out),
+ DEFINE_PROP_PTR("dma_in", ETRAXFSEthState, vdma_in),
+ DEFINE_NIC_PROPERTIES(ETRAXFSEthState, conf),
DEFINE_PROP_END_OF_LIST(),
};
@@ -643,9 +649,9 @@
}
static const TypeInfo etraxfs_eth_info = {
- .name = "etraxfs-eth",
+ .name = TYPE_ETRAX_FS_ETH,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(struct fs_eth),
+ .instance_size = sizeof(ETRAXFSEthState),
.class_init = etraxfs_eth_class_init,
};
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 3323f48..2315f99 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -170,8 +170,12 @@
}
};
+#define TYPE_LAN9118 "lan9118"
+#define LAN9118(obj) OBJECT_CHECK(lan9118_state, (obj), TYPE_LAN9118)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
NICState *nic;
NICConf conf;
qemu_irq irq;
@@ -401,7 +405,8 @@
static void lan9118_reset(DeviceState *d)
{
- lan9118_state *s = FROM_SYSBUS(lan9118_state, SYS_BUS_DEVICE(d));
+ lan9118_state *s = LAN9118(d);
+
s->irq_cfg &= (IRQ_TYPE | IRQ_POL);
s->int_sts = 0;
s->int_en = 0;
@@ -434,7 +439,7 @@
s->afc_cfg = 0;
s->e2p_cmd = 0;
s->e2p_data = 0;
- s->free_timer_start = qemu_get_clock_ns(vm_clock) / 40;
+ s->free_timer_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 40;
ptimer_stop(s->timer);
ptimer_set_count(s->timer, 0xffff);
@@ -1053,7 +1058,7 @@
case CSR_HW_CFG:
if (val & 1) {
/* SRST */
- lan9118_reset(&s->busdev.qdev);
+ lan9118_reset(DEVICE(s));
} else {
s->hw_cfg = (val & 0x003f300) | (s->hw_cfg & 0x4);
}
@@ -1231,7 +1236,7 @@
case CSR_WORD_SWAP:
return s->word_swap;
case CSR_FREE_RUN:
- return (qemu_get_clock_ns(vm_clock) / 40) - s->free_timer_start;
+ return (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 40) - s->free_timer_start;
case CSR_RX_DROP:
/* TODO: Implement dropped frames counter. */
return 0;
@@ -1320,9 +1325,10 @@
.link_status_changed = lan9118_set_link,
};
-static int lan9118_init1(SysBusDevice *dev)
+static int lan9118_init1(SysBusDevice *sbd)
{
- lan9118_state *s = FROM_SYSBUS(lan9118_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ lan9118_state *s = LAN9118(dev);
QEMUBH *bh;
int i;
const MemoryRegionOps *mem_ops =
@@ -1330,12 +1336,12 @@
memory_region_init_io(&s->mmio, OBJECT(dev), mem_ops, s,
"lan9118-mmio", 0x100);
- sysbus_init_mmio(dev, &s->mmio);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_mmio(sbd, &s->mmio);
+ sysbus_init_irq(sbd, &s->irq);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_lan9118_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
s->eeprom[0] = 0xa5;
for (i = 0; i < 6; i++) {
@@ -1370,7 +1376,7 @@
}
static const TypeInfo lan9118_info = {
- .name = "lan9118",
+ .name = TYPE_LAN9118,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(lan9118_state),
.class_init = lan9118_class_init,
@@ -1389,7 +1395,7 @@
SysBusDevice *s;
qemu_check_nic_model(nd, "lan9118");
- dev = qdev_create(NULL, "lan9118");
+ dev = qdev_create(NULL, TYPE_LAN9118);
qdev_set_nic_properties(dev, nd);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
diff --git a/hw/net/lance.c b/hw/net/lance.c
index 98bcdfc..e339f02 100644
--- a/hw/net/lance.c
+++ b/hw/net/lance.c
@@ -43,8 +43,13 @@
#include "pcnet.h"
#include "trace.h"
+#define TYPE_LANCE "lance"
+#define SYSBUS_PCNET(obj) \
+ OBJECT_CHECK(SysBusPCNetState, (obj), TYPE_LANCE)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
PCNetState state;
} SysBusPCNetState;
@@ -112,28 +117,29 @@
}
};
-static int lance_init(SysBusDevice *dev)
+static int lance_init(SysBusDevice *sbd)
{
- SysBusPCNetState *d = FROM_SYSBUS(SysBusPCNetState, dev);
+ DeviceState *dev = DEVICE(sbd);
+ SysBusPCNetState *d = SYSBUS_PCNET(dev);
PCNetState *s = &d->state;
memory_region_init_io(&s->mmio, OBJECT(d), &lance_mem_ops, d,
"lance-mmio", 4);
- qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1);
+ qdev_init_gpio_in(dev, parent_lance_reset, 1);
- sysbus_init_mmio(dev, &s->mmio);
+ sysbus_init_mmio(sbd, &s->mmio);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
s->phys_mem_read = ledma_memory_read;
s->phys_mem_write = ledma_memory_write;
- return pcnet_common_init(&dev->qdev, s, &net_lance_info);
+ return pcnet_common_init(dev, s, &net_lance_info);
}
static void lance_reset(DeviceState *dev)
{
- SysBusPCNetState *d = DO_UPCAST(SysBusPCNetState, busdev.qdev, dev);
+ SysBusPCNetState *d = SYSBUS_PCNET(dev);
pcnet_h_reset(&d->state);
}
@@ -150,6 +156,7 @@
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = lance_init;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
dc->fw_name = "ethernet";
dc->reset = lance_reset;
dc->vmsd = &vmstate_lance;
@@ -157,7 +164,7 @@
}
static const TypeInfo lance_info = {
- .name = "lance",
+ .name = TYPE_LANCE,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SysBusPCNetState),
.class_init = lance_class_init,
diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c
index becd26c..1e92379 100644
--- a/hw/net/milkymist-minimac2.c
+++ b/hw/net/milkymist-minimac2.c
@@ -90,8 +90,13 @@
};
typedef struct MilkymistMinimac2MdioState MilkymistMinimac2MdioState;
+#define TYPE_MILKYMIST_MINIMAC2 "milkymist-minimac2"
+#define MILKYMIST_MINIMAC2(obj) \
+ OBJECT_CHECK(MilkymistMinimac2State, (obj), TYPE_MILKYMIST_MINIMAC2)
+
struct MilkymistMinimac2State {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
NICState *nic;
NICConf conf;
char *phy_model;
@@ -429,8 +434,7 @@
static void milkymist_minimac2_reset(DeviceState *d)
{
- MilkymistMinimac2State *s =
- container_of(d, MilkymistMinimac2State, busdev.qdev);
+ MilkymistMinimac2State *s = MILKYMIST_MINIMAC2(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -453,17 +457,18 @@
.cleanup = minimac2_cleanup,
};
-static int milkymist_minimac2_init(SysBusDevice *dev)
+static int milkymist_minimac2_init(SysBusDevice *sbd)
{
- MilkymistMinimac2State *s = FROM_SYSBUS(typeof(*s), dev);
+ DeviceState *dev = DEVICE(sbd);
+ MilkymistMinimac2State *s = MILKYMIST_MINIMAC2(dev);
size_t buffers_size = TARGET_PAGE_ALIGN(3 * MINIMAC2_BUFFER_SIZE);
- sysbus_init_irq(dev, &s->rx_irq);
- sysbus_init_irq(dev, &s->tx_irq);
+ sysbus_init_irq(sbd, &s->rx_irq);
+ sysbus_init_irq(sbd, &s->tx_irq);
memory_region_init_io(&s->regs_region, OBJECT(dev), &minimac2_ops, s,
"milkymist-minimac2", R_MAX * 4);
- sysbus_init_mmio(dev, &s->regs_region);
+ sysbus_init_mmio(sbd, &s->regs_region);
/* register buffers memory */
memory_region_init_ram(&s->buffers, OBJECT(dev), "milkymist-minimac2.buffers",
@@ -473,11 +478,11 @@
s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE;
s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE;
- sysbus_init_mmio(dev, &s->buffers);
+ sysbus_init_mmio(sbd, &s->buffers);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
return 0;
@@ -532,7 +537,7 @@
}
static const TypeInfo milkymist_minimac2_info = {
- .name = "milkymist-minimac2",
+ .name = TYPE_MILKYMIST_MINIMAC2,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistMinimac2State),
.class_init = milkymist_minimac2_class_init,
diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c
index 9080850..e421b86 100644
--- a/hw/net/mipsnet.c
+++ b/hw/net/mipsnet.c
@@ -19,8 +19,11 @@
#define MAX_ETH_FRAME_SIZE 1514
+#define TYPE_MIPS_NET "mipsnet"
+#define MIPS_NET(obj) OBJECT_CHECK(MIPSnetState, (obj), TYPE_MIPS_NET)
+
typedef struct MIPSnetState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
uint32_t busy;
uint32_t rx_count;
@@ -231,17 +234,18 @@
.impl.max_access_size = 4,
};
-static int mipsnet_sysbus_init(SysBusDevice *dev)
+static int mipsnet_sysbus_init(SysBusDevice *sbd)
{
- MIPSnetState *s = DO_UPCAST(MIPSnetState, busdev, dev);
+ DeviceState *dev = DEVICE(sbd);
+ MIPSnetState *s = MIPS_NET(dev);
memory_region_init_io(&s->io, OBJECT(dev), &mipsnet_ioport_ops, s,
"mipsnet-io", 36);
- sysbus_init_mmio(dev, &s->io);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_mmio(sbd, &s->io);
+ sysbus_init_irq(sbd, &s->irq);
s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
return 0;
@@ -249,7 +253,7 @@
static void mipsnet_sysbus_reset(DeviceState *dev)
{
- MIPSnetState *s = DO_UPCAST(MIPSnetState, busdev.qdev, dev);
+ MIPSnetState *s = MIPS_NET(dev);
mipsnet_reset(s);
}
@@ -264,6 +268,7 @@
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = mipsnet_sysbus_init;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
dc->desc = "MIPS Simulator network device";
dc->reset = mipsnet_sysbus_reset;
dc->vmsd = &vmstate_mipsnet;
@@ -271,7 +276,7 @@
}
static const TypeInfo mipsnet_info = {
- .name = "mipsnet",
+ .name = TYPE_MIPS_NET,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MIPSnetState),
.class_init = mipsnet_class_init,
diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c
index e3c8076..26b83ce 100644
--- a/hw/net/ne2000-isa.c
+++ b/hw/net/ne2000-isa.c
@@ -98,6 +98,7 @@
dc->realize = isa_ne2000_realizefn;
dc->props = ne2000_isa_properties;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
}
static const TypeInfo ne2000_isa_info = {
diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
index 8d43fd9..31afd28 100644
--- a/hw/net/ne2000.c
+++ b/hw/net/ne2000.c
@@ -772,6 +772,7 @@
k->class_id = PCI_CLASS_NETWORK_ETHERNET;
dc->vmsd = &vmstate_pci_ne2000;
dc->props = ne2000_properties;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
}
static const TypeInfo ne2000_info = {
diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c
index 4637557..4118d54 100644
--- a/hw/net/opencores_eth.c
+++ b/hw/net/opencores_eth.c
@@ -267,8 +267,12 @@
#define DEFAULT_PHY 1
+#define TYPE_OPEN_ETH "open_eth"
+#define OPEN_ETH(obj) OBJECT_CHECK(OpenEthState, (obj), TYPE_OPEN_ETH)
+
typedef struct OpenEthState {
- SysBusDevice dev;
+ SysBusDevice parent_obj;
+
NICState *nic;
NICConf conf;
MemoryRegion reg_io;
@@ -677,28 +681,30 @@
.write = open_eth_desc_write,
};
-static int sysbus_open_eth_init(SysBusDevice *dev)
+static int sysbus_open_eth_init(SysBusDevice *sbd)
{
- OpenEthState *s = DO_UPCAST(OpenEthState, dev, dev);
+ DeviceState *dev = DEVICE(sbd);
+ OpenEthState *s = OPEN_ETH(dev);
memory_region_init_io(&s->reg_io, OBJECT(dev), &open_eth_reg_ops, s,
"open_eth.regs", 0x54);
- sysbus_init_mmio(dev, &s->reg_io);
+ sysbus_init_mmio(sbd, &s->reg_io);
memory_region_init_io(&s->desc_io, OBJECT(dev), &open_eth_desc_ops, s,
"open_eth.desc", 0x400);
- sysbus_init_mmio(dev, &s->desc_io);
+ sysbus_init_mmio(sbd, &s->desc_io);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
s->nic = qemu_new_nic(&net_open_eth_info, &s->conf,
- object_get_typename(OBJECT(s)), s->dev.qdev.id, s);
+ object_get_typename(OBJECT(s)), dev->id, s);
return 0;
}
static void qdev_open_eth_reset(DeviceState *dev)
{
- OpenEthState *d = DO_UPCAST(OpenEthState, dev.qdev, dev);
+ OpenEthState *d = OPEN_ETH(dev);
+
open_eth_reset(d);
}
@@ -713,13 +719,14 @@
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = sysbus_open_eth_init;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
dc->desc = "Opencores 10/100 Mbit Ethernet";
dc->reset = qdev_open_eth_reset;
dc->props = open_eth_properties;
}
static const TypeInfo open_eth_info = {
- .name = "open_eth",
+ .name = TYPE_OPEN_ETH,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(OpenEthState),
.class_init = open_eth_class_init,
diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c
index 6ef28f7..a893165 100644
--- a/hw/net/pcnet-pci.c
+++ b/hw/net/pcnet-pci.c
@@ -284,8 +284,8 @@
memory_region_destroy(&d->state.mmio);
memory_region_destroy(&d->io_bar);
- qemu_del_timer(d->state.poll_timer);
- qemu_free_timer(d->state.poll_timer);
+ timer_del(d->state.poll_timer);
+ timer_free(d->state.poll_timer);
qemu_del_nic(d->state.nic);
}
@@ -366,6 +366,7 @@
dc->reset = pci_reset;
dc->vmsd = &vmstate_pci_pcnet;
dc->props = pcnet_properties;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
}
static const TypeInfo pcnet_info = {
diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
index b606d2b..7cb47b3 100644
--- a/hw/net/pcnet.c
+++ b/hw/net/pcnet.c
@@ -861,6 +861,8 @@
s->csr[0] |= 0x0101;
s->csr[0] &= ~0x0004; /* clear STOP bit */
+
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
}
static void pcnet_start(PCNetState *s)
@@ -878,6 +880,8 @@
s->csr[0] &= ~0x0004; /* clear STOP bit */
s->csr[0] |= 0x0002;
pcnet_poll_timer(s);
+
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
}
static void pcnet_stop(PCNetState *s)
@@ -1327,7 +1331,7 @@
{
PCNetState *s = opaque;
- qemu_del_timer(s->poll_timer);
+ timer_del(s->poll_timer);
if (CSR_TDMD(s)) {
pcnet_transmit(s);
@@ -1336,7 +1340,7 @@
pcnet_update_irq(s);
if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
- uint64_t now = qemu_get_clock_ns(vm_clock) * 33;
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) * 33;
if (!s->timer || !now)
s->timer = now;
else {
@@ -1347,8 +1351,8 @@
} else
CSR_POLL(s) = t;
}
- qemu_mod_timer(s->poll_timer,
- pcnet_get_next_poll_time(s,qemu_get_clock_ns(vm_clock)));
+ timer_mod(s->poll_timer,
+ pcnet_get_next_poll_time(s,qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)));
}
}
@@ -1727,7 +1731,7 @@
int i;
uint16_t checksum;
- s->poll_timer = qemu_new_timer_ns(vm_clock, pcnet_poll_timer, s);
+ s->poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pcnet_poll_timer, s);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s);
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index 6552034..c31199f 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -2648,7 +2648,7 @@
s->IntrMask = val;
- rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
+ rtl8139_set_next_tctr_time(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
rtl8139_update_irq(s);
}
@@ -2689,7 +2689,7 @@
* and probably emulated is slower is better to assume this resetting was
* done before testing on previous rtl8139_update_irq lead to IRQ losing
*/
- rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
+ rtl8139_set_next_tctr_time(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
rtl8139_update_irq(s);
#endif
@@ -2697,7 +2697,7 @@
static uint32_t rtl8139_IntrStatus_read(RTL8139State *s)
{
- rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
+ rtl8139_set_next_tctr_time(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
uint32_t ret = s->IntrStatus;
@@ -2913,7 +2913,7 @@
s->TimerExpire = next_time;
if ((s->IntrMask & PCSTimeout) != 0 && (s->IntrStatus & PCSTimeout) == 0) {
- qemu_mod_timer(s->timer, next_time);
+ timer_mod(s->timer, next_time);
}
}
@@ -2960,7 +2960,7 @@
case Timer:
DPRINTF("TCTR Timer reset on write\n");
- s->TCTR_base = qemu_get_clock_ns(vm_clock);
+ s->TCTR_base = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
rtl8139_set_next_tctr_time(s, s->TCTR_base);
break;
@@ -2968,7 +2968,7 @@
DPRINTF("FlashReg TimerInt write val=0x%08x\n", val);
if (s->TimerInt != val) {
s->TimerInt = val;
- rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
+ rtl8139_set_next_tctr_time(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
}
break;
@@ -3183,7 +3183,7 @@
break;
case Timer:
- ret = muldiv64(qemu_get_clock_ns(vm_clock) - s->TCTR_base,
+ ret = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->TCTR_base,
PCI_FREQUENCY, get_ticks_per_sec());
DPRINTF("TCTR Timer read val=0x%08x\n", ret);
break;
@@ -3245,7 +3245,7 @@
static int rtl8139_post_load(void *opaque, int version_id)
{
RTL8139State* s = opaque;
- rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
+ rtl8139_set_next_tctr_time(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
if (version_id < 4) {
s->cplus_enabled = s->CpCmd != 0;
}
@@ -3275,7 +3275,7 @@
static void rtl8139_pre_save(void *opaque)
{
RTL8139State* s = opaque;
- int64_t current_time = qemu_get_clock_ns(vm_clock);
+ int64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
/* set IntrStatus correctly */
rtl8139_set_next_tctr_time(s, current_time);
@@ -3446,7 +3446,7 @@
s->IntrStatus |= PCSTimeout;
rtl8139_update_irq(s);
- rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
+ rtl8139_set_next_tctr_time(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
}
static void rtl8139_cleanup(NetClientState *nc)
@@ -3466,8 +3466,8 @@
g_free(s->cplus_txbuffer);
s->cplus_txbuffer = NULL;
}
- qemu_del_timer(s->timer);
- qemu_free_timer(s->timer);
+ timer_del(s->timer);
+ timer_free(s->timer);
qemu_del_nic(s->nic);
}
@@ -3535,8 +3535,8 @@
s->cplus_txbuffer_offset = 0;
s->TimerExpire = 0;
- s->timer = qemu_new_timer_ns(vm_clock, rtl8139_timer, s);
- rtl8139_set_next_tctr_time(s, qemu_get_clock_ns(vm_clock));
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, rtl8139_timer, s);
+ rtl8139_set_next_tctr_time(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
add_boot_device_path(s->conf.bootindex, d, "/ethernet-phy@0");
@@ -3563,6 +3563,7 @@
dc->reset = rtl8139_reset;
dc->vmsd = &vmstate_rtl8139;
dc->props = rtl8139_properties;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
}
static const TypeInfo rtl8139_info = {
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
index c49e37a..f5963e2 100644
--- a/hw/net/smc91c111.c
+++ b/hw/net/smc91c111.c
@@ -16,8 +16,12 @@
/* Number of 2k memory pages available. */
#define NUM_PACKETS 4
+#define TYPE_SMC91C111 "smc91c111"
+#define SMC91C111(obj) OBJECT_CHECK(smc91c111_state, (obj), TYPE_SMC91C111)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
NICState *nic;
NICConf conf;
uint16_t tcr;
@@ -254,7 +258,8 @@
static void smc91c111_reset(DeviceState *dev)
{
- smc91c111_state *s = FROM_SYSBUS(smc91c111_state, SYS_BUS_DEVICE(dev));
+ smc91c111_state *s = SMC91C111(dev);
+
s->bank = 0;
s->tx_fifo_len = 0;
s->tx_fifo_done_len = 0;
@@ -302,8 +307,9 @@
return;
case 5:
SET_HIGH(rcr, value);
- if (s->rcr & RCR_SOFT_RST)
- smc91c111_reset(&s->busdev.qdev);
+ if (s->rcr & RCR_SOFT_RST) {
+ smc91c111_reset(DEVICE(s));
+ }
return;
case 10: case 11: /* RPCR */
/* Ignored */
@@ -744,16 +750,18 @@
.cleanup = smc91c111_cleanup,
};
-static int smc91c111_init1(SysBusDevice *dev)
+static int smc91c111_init1(SysBusDevice *sbd)
{
- smc91c111_state *s = FROM_SYSBUS(smc91c111_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ smc91c111_state *s = SMC91C111(dev);
+
memory_region_init_io(&s->mmio, OBJECT(s), &smc91c111_mem_ops, s,
"smc91c111-mmio", 16);
- sysbus_init_mmio(dev, &s->mmio);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_mmio(sbd, &s->mmio);
+ sysbus_init_irq(sbd, &s->irq);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
/* ??? Save/restore. */
return 0;
@@ -776,7 +784,7 @@
}
static const TypeInfo smc91c111_info = {
- .name = "smc91c111",
+ .name = TYPE_SMC91C111,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(smc91c111_state),
.class_init = smc91c111_class_init,
@@ -795,7 +803,7 @@
SysBusDevice *s;
qemu_check_nic_model(nd, "smc91c111");
- dev = qdev_create(NULL, "smc91c111");
+ dev = qdev_create(NULL, TYPE_SMC91C111);
qdev_set_nic_properties(dev, nd);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index 03a09f2..4ff0411 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -38,9 +38,9 @@
/*#define DEBUG*/
#ifdef DEBUG
-#define dprintf(fmt...) do { fprintf(stderr, fmt); } while (0)
+#define DPRINTF(fmt...) do { fprintf(stderr, fmt); } while (0)
#else
-#define dprintf(fmt...)
+#define DPRINTF(fmt...)
#endif
/*
@@ -81,9 +81,9 @@
VIOsPAPRDevice sdev;
NICConf nicconf;
NICState *nic;
- int isopen;
+ bool isopen;
target_ulong buf_list;
- int add_buf_ptr, use_buf_ptr, rx_bufs;
+ uint32_t add_buf_ptr, use_buf_ptr, rx_bufs;
target_ulong rxq_ptr;
} VIOsPAPRVLANDevice;
@@ -105,7 +105,7 @@
uint64_t handle;
uint8_t control;
- dprintf("spapr_vlan_receive() [%s] rx_bufs=%d\n", sdev->qdev.id,
+ DPRINTF("spapr_vlan_receive() [%s] rx_bufs=%d\n", sdev->qdev.id,
dev->rx_bufs);
if (!dev->isopen) {
@@ -123,7 +123,7 @@
}
bd = vio_ldq(sdev, dev->buf_list + buf_ptr);
- dprintf("use_buf_ptr=%d bd=0x%016llx\n",
+ DPRINTF("use_buf_ptr=%d bd=0x%016llx\n",
buf_ptr, (unsigned long long)bd);
} while ((!(bd & VLAN_BD_VALID) || (VLAN_BD_LEN(bd) < (size + 8)))
&& (buf_ptr != dev->use_buf_ptr));
@@ -138,14 +138,14 @@
dev->use_buf_ptr = buf_ptr;
vio_stq(sdev, dev->buf_list + dev->use_buf_ptr, 0);
- dprintf("Found buffer: ptr=%d num=%d\n", dev->use_buf_ptr, dev->rx_bufs);
+ DPRINTF("Found buffer: ptr=%d num=%d\n", dev->use_buf_ptr, dev->rx_bufs);
/* Transfer the packet data */
if (spapr_vio_dma_write(sdev, VLAN_BD_ADDR(bd) + 8, buf, size) < 0) {
return -1;
}
- dprintf("spapr_vlan_receive: DMA write completed\n");
+ DPRINTF("spapr_vlan_receive: DMA write completed\n");
/* Update the receive queue */
control = VLAN_RXQC_TOGGLE | VLAN_RXQC_VALID;
@@ -159,7 +159,7 @@
vio_sth(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 2, 8);
vio_stb(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr, control);
- dprintf("wrote rxq entry (ptr=0x%llx): 0x%016llx 0x%016llx\n",
+ DPRINTF("wrote rxq entry (ptr=0x%llx): 0x%016llx 0x%016llx\n",
(unsigned long long)dev->rxq_ptr,
(unsigned long long)vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) +
dev->rxq_ptr),
@@ -374,7 +374,7 @@
VIOsPAPRVLANDevice *dev = VIO_SPAPR_VLAN_DEVICE(sdev);
vlan_bd_t bd;
- dprintf("H_ADD_LOGICAL_LAN_BUFFER(0x" TARGET_FMT_lx
+ DPRINTF("H_ADD_LOGICAL_LAN_BUFFER(0x" TARGET_FMT_lx
", 0x" TARGET_FMT_lx ")\n", reg, buf);
if (!sdev) {
@@ -405,7 +405,7 @@
dev->rx_bufs++;
- dprintf("h_add_logical_lan_buffer(): Added buf ptr=%d rx_bufs=%d"
+ DPRINTF("h_add_logical_lan_buffer(): Added buf ptr=%d rx_bufs=%d"
" bd=0x%016llx\n", dev->add_buf_ptr, dev->rx_bufs,
(unsigned long long)buf);
@@ -425,14 +425,14 @@
int i, nbufs;
int ret;
- dprintf("H_SEND_LOGICAL_LAN(0x" TARGET_FMT_lx ", <bufs>, 0x"
+ DPRINTF("H_SEND_LOGICAL_LAN(0x" TARGET_FMT_lx ", <bufs>, 0x"
TARGET_FMT_lx ")\n", reg, continue_token);
if (!sdev) {
return H_PARAMETER;
}
- dprintf("rxbufs = %d\n", dev->rx_bufs);
+ DPRINTF("rxbufs = %d\n", dev->rx_bufs);
if (!dev->isopen) {
return H_DROPPED;
@@ -444,7 +444,7 @@
total_len = 0;
for (i = 0; i < 6; i++) {
- dprintf(" buf desc: 0x" TARGET_FMT_lx "\n", bufs[i]);
+ DPRINTF(" buf desc: 0x" TARGET_FMT_lx "\n", bufs[i]);
if (!(bufs[i] & VLAN_BD_VALID)) {
break;
}
@@ -452,7 +452,7 @@
}
nbufs = i;
- dprintf("h_send_logical_lan() %d buffers, total length 0x%x\n",
+ DPRINTF("h_send_logical_lan() %d buffers, total length 0x%x\n",
nbufs, total_len);
if (total_len == 0) {
@@ -500,6 +500,25 @@
DEFINE_PROP_END_OF_LIST(),
};
+static const VMStateDescription vmstate_spapr_llan = {
+ .name = "spapr_llan",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_SPAPR_VIO(sdev, VIOsPAPRVLANDevice),
+ /* LLAN state */
+ VMSTATE_BOOL(isopen, VIOsPAPRVLANDevice),
+ VMSTATE_UINTTL(buf_list, VIOsPAPRVLANDevice),
+ VMSTATE_UINT32(add_buf_ptr, VIOsPAPRVLANDevice),
+ VMSTATE_UINT32(use_buf_ptr, VIOsPAPRVLANDevice),
+ VMSTATE_UINT32(rx_bufs, VIOsPAPRVLANDevice),
+ VMSTATE_UINTTL(rxq_ptr, VIOsPAPRVLANDevice),
+
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static void spapr_vlan_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -514,6 +533,7 @@
k->signal_mask = 0x1;
dc->props = spapr_vlan_properties;
k->rtce_window_size = 0x10000000;
+ dc->vmsd = &vmstate_spapr_llan;
}
static const TypeInfo spapr_vlan_info = {
diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
index aac7c76..9dd77f7 100644
--- a/hw/net/stellaris_enet.c
+++ b/hw/net/stellaris_enet.c
@@ -42,8 +42,13 @@
#define SE_TCTL_CRC 0x04
#define SE_TCTL_DUPLEX 0x08
+#define TYPE_STELLARIS_ENET "stellaris_enet"
+#define STELLARIS_ENET(obj) \
+ OBJECT_CHECK(stellaris_enet_state, (obj), TYPE_STELLARIS_ENET)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
uint32_t ris;
uint32_t im;
uint32_t rctl;
@@ -386,11 +391,7 @@
{
stellaris_enet_state *s = qemu_get_nic_opaque(nc);
- unregister_savevm(&s->busdev.qdev, "stellaris_enet", s);
-
- memory_region_destroy(&s->mmio);
-
- g_free(s);
+ s->nic = NULL;
}
static NetClientInfo net_stellaris_enet_info = {
@@ -401,26 +402,36 @@
.cleanup = stellaris_enet_cleanup,
};
-static int stellaris_enet_init(SysBusDevice *dev)
+static int stellaris_enet_init(SysBusDevice *sbd)
{
- stellaris_enet_state *s = FROM_SYSBUS(stellaris_enet_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ stellaris_enet_state *s = STELLARIS_ENET(dev);
memory_region_init_io(&s->mmio, OBJECT(s), &stellaris_enet_ops, s,
"stellaris_enet", 0x1000);
- sysbus_init_mmio(dev, &s->mmio);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_mmio(sbd, &s->mmio);
+ sysbus_init_irq(sbd, &s->irq);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_stellaris_enet_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
stellaris_enet_reset(s);
- register_savevm(&s->busdev.qdev, "stellaris_enet", -1, 1,
+ register_savevm(dev, "stellaris_enet", -1, 1,
stellaris_enet_save, stellaris_enet_load, s);
return 0;
}
+static void stellaris_enet_unrealize(DeviceState *dev, Error **errp)
+{
+ stellaris_enet_state *s = STELLARIS_ENET(dev);
+
+ unregister_savevm(DEVICE(s), "stellaris_enet", s);
+
+ memory_region_destroy(&s->mmio);
+}
+
static Property stellaris_enet_properties[] = {
DEFINE_NIC_PROPERTIES(stellaris_enet_state, conf),
DEFINE_PROP_END_OF_LIST(),
@@ -432,11 +443,12 @@
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = stellaris_enet_init;
+ dc->unrealize = stellaris_enet_unrealize;
dc->props = stellaris_enet_properties;
}
static const TypeInfo stellaris_enet_info = {
- .name = "stellaris_enet",
+ .name = TYPE_STELLARIS_ENET,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(stellaris_enet_state),
.class_init = stellaris_enet_class_init,
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 679f50c..dd41008 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -162,14 +162,14 @@
if (virtio_net_started(n, queue_status) && !n->vhost_started) {
if (q->tx_timer) {
- qemu_mod_timer(q->tx_timer,
- qemu_get_clock_ns(vm_clock) + n->tx_timeout);
+ timer_mod(q->tx_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout);
} else {
qemu_bh_schedule(q->tx_bh);
}
} else {
if (q->tx_timer) {
- qemu_del_timer(q->tx_timer);
+ timer_del(q->tx_timer);
} else {
qemu_bh_cancel(q->tx_bh);
}
@@ -1131,12 +1131,12 @@
if (q->tx_waiting) {
virtio_queue_set_notification(vq, 1);
- qemu_del_timer(q->tx_timer);
+ timer_del(q->tx_timer);
q->tx_waiting = 0;
virtio_net_flush_tx(q);
} else {
- qemu_mod_timer(q->tx_timer,
- qemu_get_clock_ns(vm_clock) + n->tx_timeout);
+ timer_mod(q->tx_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout);
q->tx_waiting = 1;
virtio_queue_set_notification(vq, 0);
}
@@ -1233,7 +1233,7 @@
if (n->vqs[i].tx_timer) {
n->vqs[i].tx_vq =
virtio_add_queue(vdev, 256, virtio_net_handle_tx_timer);
- n->vqs[i].tx_timer = qemu_new_timer_ns(vm_clock,
+ n->vqs[i].tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
virtio_net_tx_timer,
&n->vqs[i]);
} else {
@@ -1513,7 +1513,7 @@
if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) {
n->vqs[0].tx_vq = virtio_add_queue(vdev, 256,
virtio_net_handle_tx_timer);
- n->vqs[0].tx_timer = qemu_new_timer_ns(vm_clock, virtio_net_tx_timer,
+ n->vqs[0].tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, virtio_net_tx_timer,
&n->vqs[0]);
} else {
n->vqs[0].tx_vq = virtio_add_queue(vdev, 256,
@@ -1598,8 +1598,8 @@
qemu_purge_queued_packets(nc);
if (q->tx_timer) {
- qemu_del_timer(q->tx_timer);
- qemu_free_timer(q->tx_timer);
+ timer_del(q->tx_timer);
+ timer_free(q->tx_timer);
} else {
qemu_bh_delete(q->tx_bh);
}
@@ -1638,6 +1638,7 @@
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->exit = virtio_net_device_exit;
dc->props = virtio_net_properties;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
vdc->init = virtio_net_device_init;
vdc->get_config = virtio_net_get_config;
vdc->set_config = virtio_net_set_config;
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index b39ff08..49c2466 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -528,7 +528,7 @@
break;
default:
- assert(false);
+ g_assert_not_reached();
return false;
}
@@ -575,7 +575,7 @@
stats->ucastBytesTxOK += tot_len;
break;
default:
- assert(false);
+ g_assert_not_reached();
}
if (s->offload_mode == VMXNET3_OM_TSO) {
@@ -599,7 +599,7 @@
break;
default:
- assert(false);
+ g_assert_not_reached();
}
}
@@ -634,7 +634,7 @@
stats->ucastBytesRxOK += tot_len;
break;
default:
- assert(false);
+ g_assert_not_reached();
}
if (tot_len > s->mtu) {
@@ -643,7 +643,7 @@
}
break;
default:
- assert(false);
+ g_assert_not_reached();
}
}
@@ -1106,7 +1106,7 @@
{
if (VMW_IS_MULTIREG_ADDR(addr, VMXNET3_REG_IMR,
VMXNET3_MAX_INTRS, VMXNET3_REG_ALIGN)) {
- assert(false);
+ g_assert_not_reached();
}
VMW_CBPRN("BAR0 unknown read [%" PRIx64 "], size %d", addr, size);
@@ -1651,7 +1651,7 @@
case VMXNET3_REG_ICR:
VMW_CBPRN("Write BAR1 [VMXNET3_REG_ICR] = %" PRIx64 ", size %d",
val, size);
- assert(false);
+ g_assert_not_reached();
break;
/* Event Cause Register */
@@ -1801,7 +1801,7 @@
break;
default:
- assert(false);
+ g_assert_not_reached();
}
return true;
@@ -2453,6 +2453,7 @@
dc->reset = vmxnet3_qdev_reset;
dc->vmsd = &vmstate_vmxnet3;
dc->props = vmxnet3_properties;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
}
static const TypeInfo vmxnet3_info = {
diff --git a/hw/net/vmxnet_tx_pkt.c b/hw/net/vmxnet_tx_pkt.c
index fc01e4d..f7344c4 100644
--- a/hw/net/vmxnet_tx_pkt.c
+++ b/hw/net/vmxnet_tx_pkt.c
@@ -287,7 +287,7 @@
break;
default:
- assert(false);
+ g_assert_not_reached();
}
if (csum_enable) {
diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c
index 997a5b5..9384fa0 100644
--- a/hw/net/xgmac.c
+++ b/hw/net/xgmac.c
@@ -135,8 +135,12 @@
uint64_t rx_mcast;
} RxTxStats;
+#define TYPE_XGMAC "xgmac"
+#define XGMAC(obj) OBJECT_CHECK(XgmacState, (obj), TYPE_XGMAC)
+
typedef struct XgmacState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
qemu_irq sbd_irq;
qemu_irq pmt_irq;
@@ -173,14 +177,14 @@
}
};
-static void xgmac_read_desc(struct XgmacState *s, struct desc *d, int rx)
+static void xgmac_read_desc(XgmacState *s, struct desc *d, int rx)
{
uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
s->regs[DMA_CUR_TX_DESC_ADDR];
cpu_physical_memory_read(addr, d, sizeof(*d));
}
-static void xgmac_write_desc(struct XgmacState *s, struct desc *d, int rx)
+static void xgmac_write_desc(XgmacState *s, struct desc *d, int rx)
{
int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
uint32_t addr = s->regs[reg];
@@ -195,7 +199,7 @@
cpu_physical_memory_write(addr, d, sizeof(*d));
}
-static void xgmac_enet_send(struct XgmacState *s)
+static void xgmac_enet_send(XgmacState *s)
{
struct desc bd;
int frame_size;
@@ -246,7 +250,7 @@
}
}
-static void enet_update_irq(struct XgmacState *s)
+static void enet_update_irq(XgmacState *s)
{
int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
qemu_set_irq(s->sbd_irq, !!stat);
@@ -254,7 +258,7 @@
static uint64_t enet_read(void *opaque, hwaddr addr, unsigned size)
{
- struct XgmacState *s = opaque;
+ XgmacState *s = opaque;
uint64_t r = 0;
addr >>= 2;
@@ -274,7 +278,7 @@
static void enet_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
- struct XgmacState *s = opaque;
+ XgmacState *s = opaque;
addr >>= 2;
switch (addr) {
@@ -310,7 +314,7 @@
static int eth_can_rx(NetClientState *nc)
{
- struct XgmacState *s = qemu_get_nic_opaque(nc);
+ XgmacState *s = qemu_get_nic_opaque(nc);
/* RX enabled? */
return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
@@ -318,7 +322,7 @@
static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
{
- struct XgmacState *s = qemu_get_nic_opaque(nc);
+ XgmacState *s = qemu_get_nic_opaque(nc);
static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
0xff, 0xff, 0xff};
int unicast, broadcast, multicast;
@@ -366,7 +370,8 @@
static void eth_cleanup(NetClientState *nc)
{
- struct XgmacState *s = qemu_get_nic_opaque(nc);
+ XgmacState *s = qemu_get_nic_opaque(nc);
+
s->nic = NULL;
}
@@ -378,20 +383,21 @@
.cleanup = eth_cleanup,
};
-static int xgmac_enet_init(SysBusDevice *dev)
+static int xgmac_enet_init(SysBusDevice *sbd)
{
- struct XgmacState *s = FROM_SYSBUS(typeof(*s), dev);
+ DeviceState *dev = DEVICE(sbd);
+ XgmacState *s = XGMAC(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &enet_mem_ops, s,
"xgmac", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->sbd_irq);
- sysbus_init_irq(dev, &s->pmt_irq);
- sysbus_init_irq(dev, &s->mci_irq);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->sbd_irq);
+ sysbus_init_irq(sbd, &s->pmt_irq);
+ sysbus_init_irq(sbd, &s->mci_irq);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
@@ -405,7 +411,7 @@
}
static Property xgmac_properties[] = {
- DEFINE_NIC_PROPERTIES(struct XgmacState, conf),
+ DEFINE_NIC_PROPERTIES(XgmacState, conf),
DEFINE_PROP_END_OF_LIST(),
};
@@ -420,9 +426,9 @@
}
static const TypeInfo xgmac_enet_info = {
- .name = "xgmac",
+ .name = TYPE_XGMAC,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(struct XgmacState),
+ .instance_size = sizeof(XgmacState),
.class_init = xgmac_enet_class_init,
};
diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index 2afc91a..3a2a6c2 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -47,9 +47,14 @@
#define CTRL_P 0x2
#define CTRL_S 0x1
+#define TYPE_XILINX_ETHLITE "xlnx.xps-ethernetlite"
+#define XILINX_ETHLITE(obj) \
+ OBJECT_CHECK(struct xlx_ethlite, (obj), TYPE_XILINX_ETHLITE)
+
struct xlx_ethlite
{
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion mmio;
qemu_irq irq;
NICState *nic;
@@ -214,20 +219,21 @@
.cleanup = eth_cleanup,
};
-static int xilinx_ethlite_init(SysBusDevice *dev)
+static int xilinx_ethlite_init(SysBusDevice *sbd)
{
- struct xlx_ethlite *s = FROM_SYSBUS(typeof (*s), dev);
+ DeviceState *dev = DEVICE(sbd);
+ struct xlx_ethlite *s = XILINX_ETHLITE(dev);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
s->rxbuf = 0;
memory_region_init_io(&s->mmio, OBJECT(s), ð_ops, s,
"xlnx.xps-ethernetlite", R_MAX * 4);
- sysbus_init_mmio(dev, &s->mmio);
+ sysbus_init_mmio(sbd, &s->mmio);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->qdev.id, s);
+ object_get_typename(OBJECT(dev)), dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
return 0;
}
@@ -249,7 +255,7 @@
}
static const TypeInfo xilinx_ethlite_info = {
- .name = "xlnx.xps-ethernetlite",
+ .name = TYPE_XILINX_ETHLITE,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct xlx_ethlite),
.class_init = xilinx_ethlite_class_init,
diff --git a/hw/nvram/ds1225y.c b/hw/nvram/ds1225y.c
index fa218ce..f9a700b 100644
--- a/hw/nvram/ds1225y.c
+++ b/hw/nvram/ds1225y.c
@@ -26,7 +26,6 @@
#include "trace.h"
typedef struct {
- DeviceState qdev;
MemoryRegion iomem;
uint32_t chip_size;
char *filename;
@@ -105,14 +104,19 @@
}
};
+#define TYPE_DS1225Y "ds1225y"
+#define DS1225Y(obj) OBJECT_CHECK(SysBusNvRamState, (obj), TYPE_DS1225Y)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
NvRamState nvram;
} SysBusNvRamState;
static int nvram_sysbus_initfn(SysBusDevice *dev)
{
- NvRamState *s = &FROM_SYSBUS(SysBusNvRamState, dev)->nvram;
+ SysBusNvRamState *sys = DS1225Y(dev);
+ NvRamState *s = &sys->nvram;
FILE *file;
s->contents = g_malloc0(s->chip_size);
@@ -152,7 +156,7 @@
}
static const TypeInfo nvram_sysbus_info = {
- .name = "ds1225y",
+ .name = TYPE_DS1225Y,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SysBusNvRamState),
.class_init = nvram_sysbus_class_init,
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 0a35015..d0820e5 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -324,7 +324,7 @@
static const MemoryRegionOps fw_cfg_comb_mem_ops = {
.read = fw_cfg_comb_read,
.write = fw_cfg_comb_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_LITTLE_ENDIAN,
.valid.accepts = fw_cfg_comb_valid,
};
diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
index 4144b34..988ca20 100644
--- a/hw/openrisc/cputimer.c
+++ b/hw/openrisc/cputimer.c
@@ -33,9 +33,9 @@
uint64_t now, next;
uint32_t wait;
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (!is_counting) {
- qemu_del_timer(cpu->env.timer);
+ timer_del(cpu->env.timer);
last_clk = now;
return;
}
@@ -52,7 +52,7 @@
}
next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
- qemu_mod_timer(cpu->env.timer, next);
+ timer_mod(cpu->env.timer, next);
}
void cpu_openrisc_count_start(OpenRISCCPU *cpu)
@@ -72,7 +72,7 @@
OpenRISCCPU *cpu = opaque;
if ((cpu->env.ttmr & TTMR_IE) &&
- qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
+ timer_expired(cpu->env.timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL))) {
CPUState *cs = CPU(cpu);
cpu->env.ttmr |= TTMR_IP;
@@ -97,7 +97,7 @@
void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
{
- cpu->env.timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, cpu);
+ cpu->env.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &openrisc_timer_cb, cpu);
cpu->env.ttmr = 0x00000000;
cpu->env.ttcr = 0x00000000;
}
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index 924438b..28fa41d 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -82,13 +82,12 @@
}
if (kernel_size < 0) {
- qemu_log("QEMU: couldn't load the kernel '%s'\n",
+ fprintf(stderr, "QEMU: couldn't load the kernel '%s'\n",
kernel_filename);
exit(1);
}
+ cpu->env.pc = entry;
}
-
- cpu->env.pc = entry;
}
static void openrisc_sim_init(QEMUMachineInitArgs *args)
@@ -96,7 +95,7 @@
ram_addr_t ram_size = args->ram_size;
const char *cpu_model = args->cpu_model;
const char *kernel_filename = args->kernel_filename;
- OpenRISCCPU *cpu = NULL;
+ OpenRISCCPU *cpu = NULL;
MemoryRegion *ram;
int n;
@@ -107,7 +106,7 @@
for (n = 0; n < smp_cpus; n++) {
cpu = cpu_openrisc_init(cpu_model);
if (cpu == NULL) {
- qemu_log("Unable to find CPU definition!\n");
+ fprintf(stderr, "Unable to find CPU definition!\n");
exit(1);
}
qemu_register_reset(main_cpu_reset, cpu);
diff --git a/hw/openrisc/pic_cpu.c b/hw/openrisc/pic_cpu.c
index ca0b7c1..2af1d60 100644
--- a/hw/openrisc/pic_cpu.c
+++ b/hw/openrisc/pic_cpu.c
@@ -26,26 +26,25 @@
{
OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
CPUState *cs = CPU(cpu);
- int i;
- uint32_t irq_bit = 1 << irq;
+ uint32_t irq_bit;
if (irq > 31 || irq < 0) {
return;
}
+ irq_bit = 1U << irq;
+
if (level) {
cpu->env.picsr |= irq_bit;
} else {
cpu->env.picsr &= ~irq_bit;
}
- for (i = 0; i < 32; i++) {
- if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
- cpu_interrupt(cs, CPU_INTERRUPT_HARD);
- } else {
- cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
- cpu->env.picsr &= ~(1 << i);
- }
+ if (cpu->env.picsr & cpu->env.picmr) {
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+ cpu->env.picsr = 0;
}
}
diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c
index efc07c4..e5e3be8 100644
--- a/hw/pci-bridge/dec.c
+++ b/hw/pci-bridge/dec.c
@@ -74,7 +74,7 @@
static const TypeInfo dec_21154_pci_bridge_info = {
.name = "dec-21154-p2p-bridge",
- .parent = TYPE_PCI_DEVICE,
+ .parent = TYPE_PCI_BRIDGE,
.instance_size = sizeof(PCIBridge),
.class_init = dec_21154_pci_bridge_class_init,
};
@@ -86,7 +86,7 @@
dev = pci_create_multifunction(parent_bus, devfn, false,
"dec-21154-p2p-bridge");
- br = DO_UPCAST(PCIBridge, dev, dev);
+ br = PCI_BRIDGE(dev);
pci_bridge_map_irq(br, "DEC 21154 PCI-PCI bridge", dec_map_irq);
qdev_init_nofail(&dev->qdev);
return pci_bridge_get_sec_bus(br);
diff --git a/hw/pci-bridge/i82801b11.c b/hw/pci-bridge/i82801b11.c
index b98bfb0..14cd7fd 100644
--- a/hw/pci-bridge/i82801b11.c
+++ b/hw/pci-bridge/i82801b11.c
@@ -52,7 +52,9 @@
#define I82801ba_SSVID_SSID 0
typedef struct I82801b11Bridge {
- PCIBridge br;
+ /*< private >*/
+ PCIBridge parent_obj;
+ /*< public >*/
} I82801b11Bridge;
static int i82801b11_bridge_initfn(PCIDevice *d)
@@ -81,17 +83,20 @@
static void i82801b11_bridge_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
k->is_bridge = 1;
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_82801BA_11;
k->revision = ICH9_D2P_A2_REVISION;
k->init = i82801b11_bridge_initfn;
+ k->config_write = pci_bridge_write_config;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
static const TypeInfo i82801b11_bridge_info = {
.name = "i82801b11-bridge",
- .parent = TYPE_PCI_DEVICE,
+ .parent = TYPE_PCI_BRIDGE,
.instance_size = sizeof(I82801b11Bridge),
.class_init = i82801b11_bridge_class_init,
};
@@ -107,8 +112,8 @@
if (!d) {
return NULL;
}
- br = DO_UPCAST(PCIBridge, dev, d);
- qdev = &br->dev.qdev;
+ br = PCI_BRIDGE(d);
+ qdev = DEVICE(d);
snprintf(buf, sizeof(buf), "pci.%d", sec_bus);
pci_bridge_map_irq(br, buf, pci_swizzle_map_irq_fn);
diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c
index bb541eb..0f7f209 100644
--- a/hw/pci-bridge/ioh3420.c
+++ b/hw/pci-bridge/ioh3420.c
@@ -92,9 +92,8 @@
static int ioh3420_initfn(PCIDevice *d)
{
- PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
- PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
- PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
+ PCIEPort *p = PCIE_PORT(d);
+ PCIESlot *s = PCIE_SLOT(d);
int rc;
rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
@@ -148,9 +147,7 @@
static void ioh3420_exitfn(PCIDevice *d)
{
- PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
- PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
- PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
+ PCIESlot *s = PCIE_SLOT(d);
pcie_aer_exit(d);
pcie_chassis_del_slot(s);
@@ -171,16 +168,16 @@
if (!d) {
return NULL;
}
- br = DO_UPCAST(PCIBridge, dev, d);
+ br = PCI_BRIDGE(d);
- qdev = &br->dev.qdev;
+ qdev = DEVICE(d);
pci_bridge_map_irq(br, bus_name, map_irq);
qdev_prop_set_uint8(qdev, "port", port);
qdev_prop_set_uint8(qdev, "chassis", chassis);
qdev_prop_set_uint16(qdev, "slot", slot);
qdev_init_nofail(qdev);
- return DO_UPCAST(PCIESlot, port, DO_UPCAST(PCIEPort, br, br));
+ return PCIE_SLOT(d);
}
static const VMStateDescription vmstate_ioh3420 = {
@@ -190,23 +187,13 @@
.minimum_version_id_old = 1,
.post_load = pcie_cap_slot_post_load,
.fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(port.br.dev, PCIESlot),
- VMSTATE_STRUCT(port.br.dev.exp.aer_log, PCIESlot, 0,
- vmstate_pcie_aer_log, PCIEAERLog),
+ VMSTATE_PCIE_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
+ VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log,
+ PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog),
VMSTATE_END_OF_LIST()
}
};
-static Property ioh3420_properties[] = {
- DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
- DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
- DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
- DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
- port.br.dev.exp.aer_log.log_max,
- PCIE_AER_LOG_MAX_DEFAULT),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void ioh3420_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -220,16 +207,15 @@
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_IOH_EPORT;
k->revision = PCI_DEVICE_ID_IOH_REV;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->desc = "Intel IOH device id 3420 PCIE Root Port";
dc->reset = ioh3420_reset;
dc->vmsd = &vmstate_ioh3420;
- dc->props = ioh3420_properties;
}
static const TypeInfo ioh3420_info = {
.name = "ioh3420",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIESlot),
+ .parent = TYPE_PCIE_SLOT,
.class_init = ioh3420_class_init,
};
diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c
index 5f11323..a9392c7 100644
--- a/hw/pci-bridge/pci_bridge_dev.c
+++ b/hw/pci-bridge/pci_bridge_dev.c
@@ -27,8 +27,15 @@
#include "exec/memory.h"
#include "hw/pci/pci_bus.h"
+#define TYPE_PCI_BRIDGE_DEV "pci-bridge"
+#define PCI_BRIDGE_DEV(obj) \
+ OBJECT_CHECK(PCIBridgeDev, (obj), TYPE_PCI_BRIDGE_DEV)
+
struct PCIBridgeDev {
- PCIBridge bridge;
+ /*< private >*/
+ PCIBridge parent_obj;
+ /*< public >*/
+
MemoryRegion bar;
uint8_t chassis_nr;
#define PCI_BRIDGE_DEV_F_MSI_REQ 0
@@ -38,8 +45,8 @@
static int pci_bridge_dev_initfn(PCIDevice *dev)
{
- PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
- PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
+ PCIBridge *br = PCI_BRIDGE(dev);
+ PCIBridgeDev *bridge_dev = PCI_BRIDGE_DEV(dev);
int err;
err = pci_bridge_initfn(dev, TYPE_PCI_BUS);
@@ -81,8 +88,7 @@
static void pci_bridge_dev_exitfn(PCIDevice *dev)
{
- PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
- PCIBridgeDev *bridge_dev = DO_UPCAST(PCIBridgeDev, bridge, br);
+ PCIBridgeDev *bridge_dev = PCI_BRIDGE_DEV(dev);
if (msi_present(dev)) {
msi_uninit(dev);
}
@@ -104,7 +110,7 @@
static void qdev_pci_bridge_dev_reset(DeviceState *qdev)
{
- PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
+ PCIDevice *dev = PCI_DEVICE(qdev);
pci_bridge_reset(qdev);
shpc_reset(dev);
@@ -120,8 +126,8 @@
static const VMStateDescription pci_bridge_dev_vmstate = {
.name = "pci_bridge",
.fields = (VMStateField[]) {
- VMSTATE_PCI_DEVICE(bridge.dev, PCIBridgeDev),
- SHPC_VMSTATE(bridge.dev.shpc, PCIBridgeDev),
+ VMSTATE_PCI_DEVICE(parent_obj, PCIBridge),
+ SHPC_VMSTATE(shpc, PCIDevice),
VMSTATE_END_OF_LIST()
}
};
@@ -141,11 +147,12 @@
dc->reset = qdev_pci_bridge_dev_reset;
dc->props = pci_bridge_dev_properties;
dc->vmsd = &pci_bridge_dev_vmstate;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
static const TypeInfo pci_bridge_dev_info = {
- .name = "pci-bridge",
- .parent = TYPE_PCI_DEVICE,
+ .name = TYPE_PCI_BRIDGE_DEV,
+ .parent = TYPE_PCI_BRIDGE,
.instance_size = sizeof(PCIBridgeDev),
.class_init = pci_bridge_dev_class_init,
};
diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
index 1810dd2..94f9781 100644
--- a/hw/pci-bridge/xio3130_downstream.c
+++ b/hw/pci-bridge/xio3130_downstream.c
@@ -56,9 +56,8 @@
static int xio3130_downstream_initfn(PCIDevice *d)
{
- PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
- PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
- PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
+ PCIEPort *p = PCIE_PORT(d);
+ PCIESlot *s = PCIE_SLOT(d);
int rc;
rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
@@ -113,9 +112,7 @@
static void xio3130_downstream_exitfn(PCIDevice *d)
{
- PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
- PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
- PCIESlot *s = DO_UPCAST(PCIESlot, port, p);
+ PCIESlot *s = PCIE_SLOT(d);
pcie_aer_exit(d);
pcie_chassis_del_slot(s);
@@ -138,16 +135,16 @@
if (!d) {
return NULL;
}
- br = DO_UPCAST(PCIBridge, dev, d);
+ br = PCI_BRIDGE(d);
- qdev = &br->dev.qdev;
+ qdev = DEVICE(d);
pci_bridge_map_irq(br, bus_name, map_irq);
qdev_prop_set_uint8(qdev, "port", port);
qdev_prop_set_uint8(qdev, "chassis", chassis);
qdev_prop_set_uint16(qdev, "slot", slot);
qdev_init_nofail(qdev);
- return DO_UPCAST(PCIESlot, port, DO_UPCAST(PCIEPort, br, br));
+ return PCIE_SLOT(d);
}
static const VMStateDescription vmstate_xio3130_downstream = {
@@ -157,23 +154,13 @@
.minimum_version_id_old = 1,
.post_load = pcie_cap_slot_post_load,
.fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(port.br.dev, PCIESlot),
- VMSTATE_STRUCT(port.br.dev.exp.aer_log, PCIESlot, 0,
- vmstate_pcie_aer_log, PCIEAERLog),
+ VMSTATE_PCIE_DEVICE(parent_obj.parent_obj.parent_obj, PCIESlot),
+ VMSTATE_STRUCT(parent_obj.parent_obj.parent_obj.exp.aer_log,
+ PCIESlot, 0, vmstate_pcie_aer_log, PCIEAERLog),
VMSTATE_END_OF_LIST()
}
};
-static Property xio3130_downstream_properties[] = {
- DEFINE_PROP_UINT8("port", PCIESlot, port.port, 0),
- DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
- DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
- DEFINE_PROP_UINT16("aer_log_max", PCIESlot,
- port.br.dev.exp.aer_log.log_max,
- PCIE_AER_LOG_MAX_DEFAULT),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -187,16 +174,15 @@
k->vendor_id = PCI_VENDOR_ID_TI;
k->device_id = PCI_DEVICE_ID_TI_XIO3130D;
k->revision = XIO3130_REVISION;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->desc = "TI X3130 Downstream Port of PCI Express Switch";
dc->reset = xio3130_downstream_reset;
dc->vmsd = &vmstate_xio3130_downstream;
- dc->props = xio3130_downstream_properties;
}
static const TypeInfo xio3130_downstream_info = {
.name = "xio3130-downstream",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIESlot),
+ .parent = TYPE_PCIE_SLOT,
.class_init = xio3130_downstream_class_init,
};
diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c
index 8e0d97a..59f97f6 100644
--- a/hw/pci-bridge/xio3130_upstream.c
+++ b/hw/pci-bridge/xio3130_upstream.c
@@ -53,8 +53,7 @@
static int xio3130_upstream_initfn(PCIDevice *d)
{
- PCIBridge* br = DO_UPCAST(PCIBridge, dev, d);
- PCIEPort *p = DO_UPCAST(PCIEPort, br, br);
+ PCIEPort *p = PCIE_PORT(d);
int rc;
rc = pci_bridge_initfn(d, TYPE_PCIE_BUS);
@@ -118,14 +117,14 @@
if (!d) {
return NULL;
}
- br = DO_UPCAST(PCIBridge, dev, d);
+ br = PCI_BRIDGE(d);
- qdev = &br->dev.qdev;
+ qdev = DEVICE(d);
pci_bridge_map_irq(br, bus_name, map_irq);
qdev_prop_set_uint8(qdev, "port", port);
qdev_init_nofail(qdev);
- return DO_UPCAST(PCIEPort, br, br);
+ return PCIE_PORT(d);
}
static const VMStateDescription vmstate_xio3130_upstream = {
@@ -134,20 +133,13 @@
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
- VMSTATE_PCIE_DEVICE(br.dev, PCIEPort),
- VMSTATE_STRUCT(br.dev.exp.aer_log, PCIEPort, 0, vmstate_pcie_aer_log,
- PCIEAERLog),
+ VMSTATE_PCIE_DEVICE(parent_obj.parent_obj, PCIEPort),
+ VMSTATE_STRUCT(parent_obj.parent_obj.exp.aer_log, PCIEPort, 0,
+ vmstate_pcie_aer_log, PCIEAERLog),
VMSTATE_END_OF_LIST()
}
};
-static Property xio3130_upstream_properties[] = {
- DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
- DEFINE_PROP_UINT16("aer_log_max", PCIEPort, br.dev.exp.aer_log.log_max,
- PCIE_AER_LOG_MAX_DEFAULT),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void xio3130_upstream_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -161,16 +153,15 @@
k->vendor_id = PCI_VENDOR_ID_TI;
k->device_id = PCI_DEVICE_ID_TI_XIO3130U;
k->revision = XIO3130_REVISION;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->desc = "TI X3130 Upstream Port of PCI Express Switch";
dc->reset = xio3130_upstream_reset;
dc->vmsd = &vmstate_xio3130_upstream;
- dc->props = xio3130_upstream_properties;
}
static const TypeInfo xio3130_upstream_info = {
.name = "x3130-upstream",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIEPort),
+ .parent = TYPE_PCIE_PORT,
.class_init = xio3130_upstream_class_init,
};
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 06ace08..92f289f 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -70,9 +70,14 @@
#define MAX_IVEC 0x40
#define NO_IRQ_REQUEST (MAX_IVEC + 1)
+#define TYPE_APB "pbm"
+
+#define APB_DEVICE(obj) \
+ OBJECT_CHECK(APBState, (obj), TYPE_APB)
+
typedef struct APBState {
- SysBusDevice busdev;
- PCIBus *bus;
+ PCIHostState parent_obj;
+
MemoryRegion apb_config;
MemoryRegion pci_config;
MemoryRegion pci_mmio;
@@ -284,10 +289,11 @@
uint64_t val, unsigned size)
{
APBState *s = opaque;
+ PCIHostState *phb = PCI_HOST_BRIDGE(s);
val = qemu_bswap_len(val, size);
APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
- pci_data_write(s->bus, addr, val, size);
+ pci_data_write(phb->bus, addr, val, size);
}
static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
@@ -295,63 +301,14 @@
{
uint32_t ret;
APBState *s = opaque;
+ PCIHostState *phb = PCI_HOST_BRIDGE(s);
- ret = pci_data_read(s->bus, addr, size);
+ ret = pci_data_read(phb->bus, addr, size);
ret = qemu_bswap_len(ret, size);
APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret);
return ret;
}
-static void pci_apb_iowriteb (void *opaque, hwaddr addr,
- uint32_t val)
-{
- cpu_outb(addr & IOPORTS_MASK, val);
-}
-
-static void pci_apb_iowritew (void *opaque, hwaddr addr,
- uint32_t val)
-{
- cpu_outw(addr & IOPORTS_MASK, bswap16(val));
-}
-
-static void pci_apb_iowritel (void *opaque, hwaddr addr,
- uint32_t val)
-{
- cpu_outl(addr & IOPORTS_MASK, bswap32(val));
-}
-
-static uint32_t pci_apb_ioreadb (void *opaque, hwaddr addr)
-{
- uint32_t val;
-
- val = cpu_inb(addr & IOPORTS_MASK);
- return val;
-}
-
-static uint32_t pci_apb_ioreadw (void *opaque, hwaddr addr)
-{
- uint32_t val;
-
- val = bswap16(cpu_inw(addr & IOPORTS_MASK));
- return val;
-}
-
-static uint32_t pci_apb_ioreadl (void *opaque, hwaddr addr)
-{
- uint32_t val;
-
- val = bswap32(cpu_inl(addr & IOPORTS_MASK));
- return val;
-}
-
-static const MemoryRegionOps pci_ioport_ops = {
- .old_mmio = {
- .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl },
- .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, },
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
/* The APB host has an IRQ line for each IRQ line of each slot. */
static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
{
@@ -431,12 +388,13 @@
{
DeviceState *dev;
SysBusDevice *s;
+ PCIHostState *phb;
APBState *d;
PCIDevice *pci_dev;
PCIBridge *br;
/* Ultrasparc PBM main bus */
- dev = qdev_create(NULL, "pbm");
+ dev = qdev_create(NULL, TYPE_APB);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
/* apb_config */
@@ -445,46 +403,47 @@
sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
/* pci_ioport */
sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
- d = FROM_SYSBUS(APBState, s);
+ d = APB_DEVICE(dev);
memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL);
memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
- d->bus = pci_register_bus(&d->busdev.qdev, "pci",
- pci_apb_set_irq, pci_pbm_map_irq, d,
- &d->pci_mmio,
- get_system_io(),
- 0, 32, TYPE_PCI_BUS);
+ phb = PCI_HOST_BRIDGE(dev);
+ phb->bus = pci_register_bus(DEVICE(phb), "pci",
+ pci_apb_set_irq, pci_pbm_map_irq, d,
+ &d->pci_mmio,
+ get_system_io(),
+ 0, 32, TYPE_PCI_BUS);
*pbm_irqs = d->pbm_irqs;
d->ivec_irqs = ivec_irqs;
- pci_create_simple(d->bus, 0, "pbm-pci");
+ pci_create_simple(phb->bus, 0, "pbm-pci");
/* APB secondary busses */
- pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
+ pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
"pbm-bridge");
- br = DO_UPCAST(PCIBridge, dev, pci_dev);
+ br = PCI_BRIDGE(pci_dev);
pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
pci_apb_map_irq);
qdev_init_nofail(&pci_dev->qdev);
*bus2 = pci_bridge_get_sec_bus(br);
- pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
+ pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
"pbm-bridge");
- br = DO_UPCAST(PCIBridge, dev, pci_dev);
+ br = PCI_BRIDGE(pci_dev);
pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
pci_apb_map_irq);
qdev_init_nofail(&pci_dev->qdev);
*bus3 = pci_bridge_get_sec_bus(br);
- return d->bus;
+ return phb->bus;
}
static void pci_pbm_reset(DeviceState *d)
{
unsigned int i;
- APBState *s = container_of(d, APBState, busdev.qdev);
+ APBState *s = APB_DEVICE(d);
for (i = 0; i < 8; i++) {
s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
@@ -513,7 +472,7 @@
APBState *s;
unsigned int i;
- s = FROM_SYSBUS(APBState, dev);
+ s = APB_DEVICE(dev);
for (i = 0; i < 8; i++) {
s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
}
@@ -536,8 +495,8 @@
sysbus_init_mmio(dev, &s->pci_config);
/* pci_ioport */
- memory_region_init_io(&s->pci_ioport, OBJECT(s), &pci_ioport_ops, s,
- "apb-pci-ioport", 0x10000);
+ memory_region_init_alias(&s->pci_ioport, OBJECT(s), "apb-pci-ioport",
+ get_system_io(), 0, 0x10000);
/* at region 2 */
sysbus_init_mmio(dev, &s->pci_ioport);
@@ -577,12 +536,13 @@
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = pci_pbm_init_device;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->reset = pci_pbm_reset;
}
static const TypeInfo pbm_host_info = {
- .name = "pbm",
- .parent = TYPE_SYS_BUS_DEVICE,
+ .name = TYPE_APB,
+ .parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(APBState),
.class_init = pbm_host_class_init,
};
@@ -599,14 +559,14 @@
k->revision = 0x11;
k->config_write = pci_bridge_write_config;
k->is_bridge = 1;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->reset = pci_bridge_reset;
dc->vmsd = &vmstate_pci_device;
}
static const TypeInfo pbm_pci_bridge_info = {
.name = "pbm-bridge",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIBridge),
+ .parent = TYPE_PCI_BRIDGE,
.class_init = pbm_pci_bridge_class_init,
};
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index 592d666..5086d42 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -210,14 +210,8 @@
MemoryRegion iomem;
MemoryRegion iomem_ldma;
MemoryRegion iomem_cop;
-
- hwaddr bonito_pciio_start;
- hwaddr bonito_pciio_length;
- int bonito_pciio_handle;
-
- hwaddr bonito_localio_start;
- hwaddr bonito_localio_length;
- int bonito_localio_handle;
+ MemoryRegion bonito_pciio;
+ MemoryRegion bonito_localio;
} PCIBonitoState;
@@ -750,15 +744,16 @@
sysbus_mmio_map(sysbus, 4, 0xbfe00300);
/* Map PCI IO Space 0x1fd0 0000 - 0x1fd1 0000 */
- s->bonito_pciio_start = BONITO_PCIIO_BASE;
- s->bonito_pciio_length = BONITO_PCIIO_SIZE;
- isa_mem_base = s->bonito_pciio_start;
- isa_mmio_init(s->bonito_pciio_start, s->bonito_pciio_length);
+ memory_region_init_alias(&s->bonito_pciio, OBJECT(s), "isa_mmio",
+ get_system_io(), 0, BONITO_PCIIO_SIZE);
+ sysbus_init_mmio(sysbus, &s->bonito_pciio);
+ sysbus_mmio_map(sysbus, 5, BONITO_PCIIO_BASE);
/* add pci local io mapping */
- s->bonito_localio_start = BONITO_DEV_BASE;
- s->bonito_localio_length = BONITO_DEV_SIZE;
- isa_mmio_init(s->bonito_localio_start, s->bonito_localio_length);
+ memory_region_init_alias(&s->bonito_localio, OBJECT(s), "isa_mmio",
+ get_system_io(), 0, BONITO_DEV_SIZE);
+ sysbus_init_mmio(sysbus, &s->bonito_localio);
+ sysbus_mmio_map(sysbus, 6, BONITO_DEV_BASE);
/* set the default value of north bridge pci config */
pci_set_word(dev->config + PCI_COMMAND, 0x0000);
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 3908860..dc1718f 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -32,14 +32,22 @@
#include "hw/xen/xen.h"
#include "hw/pci-host/pam.h"
#include "sysemu/sysemu.h"
+#include "hw/i386/ioapic.h"
+#include "qapi/visitor.h"
/*
* I440FX chipset data sheet.
* http://download.intel.com/design/chipsets/datashts/29054901.pdf
*/
+#define TYPE_I440FX_PCI_HOST_BRIDGE "i440FX-pcihost"
+#define I440FX_PCI_HOST_BRIDGE(obj) \
+ OBJECT_CHECK(I440FXState, (obj), TYPE_I440FX_PCI_HOST_BRIDGE)
+
typedef struct I440FXState {
PCIHostState parent_obj;
+ PcPciInfo pci_info;
+ uint64_t pci_hole64_size;
} I440FXState;
#define PIIX_NUM_PIC_IRQS 16 /* i8259 * 2 */
@@ -203,14 +211,71 @@
}
};
+static void i440fx_pcihost_get_pci_hole_start(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
+ uint32_t value = s->pci_info.w32.begin;
+
+ visit_type_uint32(v, &value, name, errp);
+}
+
+static void i440fx_pcihost_get_pci_hole_end(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
+ uint32_t value = s->pci_info.w32.end;
+
+ visit_type_uint32(v, &value, name, errp);
+}
+
+static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
+
+ visit_type_uint64(v, &s->pci_info.w64.begin, name, errp);
+}
+
+static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
+
+ visit_type_uint64(v, &s->pci_info.w64.end, name, errp);
+}
+
static void i440fx_pcihost_initfn(Object *obj)
{
PCIHostState *s = PCI_HOST_BRIDGE(obj);
+ I440FXState *d = I440FX_PCI_HOST_BRIDGE(obj);
memory_region_init_io(&s->conf_mem, obj, &pci_host_conf_le_ops, s,
"pci-conf-idx", 4);
memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s,
"pci-conf-data", 4);
+
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
+ i440fx_pcihost_get_pci_hole_start,
+ NULL, NULL, NULL, NULL);
+
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
+ i440fx_pcihost_get_pci_hole_end,
+ NULL, NULL, NULL, NULL);
+
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
+ i440fx_pcihost_get_pci_hole64_start,
+ NULL, NULL, NULL, NULL);
+
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
+ i440fx_pcihost_get_pci_hole64_end,
+ NULL, NULL, NULL, NULL);
+
+ d->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS;
}
static void i440fx_pcihost_realize(DeviceState *dev, Error **errp)
@@ -235,19 +300,17 @@
return 0;
}
-static PCIBus *i440fx_common_init(const char *device_name,
- PCII440FXState **pi440fx_state,
- int *piix3_devfn,
- ISABus **isa_bus, qemu_irq *pic,
- MemoryRegion *address_space_mem,
- MemoryRegion *address_space_io,
- ram_addr_t ram_size,
- hwaddr pci_hole_start,
- hwaddr pci_hole_size,
- hwaddr pci_hole64_start,
- hwaddr pci_hole64_size,
- MemoryRegion *pci_address_space,
- MemoryRegion *ram_memory)
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
+ int *piix3_devfn,
+ ISABus **isa_bus, qemu_irq *pic,
+ MemoryRegion *address_space_mem,
+ MemoryRegion *address_space_io,
+ ram_addr_t ram_size,
+ hwaddr pci_hole_start,
+ hwaddr pci_hole_size,
+ ram_addr_t above_4g_mem_size,
+ MemoryRegion *pci_address_space,
+ MemoryRegion *ram_memory)
{
DeviceState *dev;
PCIBus *b;
@@ -256,8 +319,9 @@
PIIX3State *piix3;
PCII440FXState *f;
unsigned i;
+ I440FXState *i440fx;
- dev = qdev_create(NULL, "i440FX-pcihost");
+ dev = qdev_create(NULL, TYPE_I440FX_PCI_HOST_BRIDGE);
s = PCI_HOST_BRIDGE(dev);
b = pci_bus_new(dev, NULL, pci_address_space,
address_space_io, 0, TYPE_PCI_BUS);
@@ -265,20 +329,37 @@
object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
qdev_init_nofail(dev);
- d = pci_create_simple(b, 0, device_name);
+ d = pci_create_simple(b, 0, TYPE_I440FX_PCI_DEVICE);
*pi440fx_state = I440FX_PCI_DEVICE(d);
f = *pi440fx_state;
f->system_memory = address_space_mem;
f->pci_address_space = pci_address_space;
f->ram_memory = ram_memory;
+
+ i440fx = I440FX_PCI_HOST_BRIDGE(dev);
+ /* Set PCI window size the way seabios has always done it. */
+ /* Power of 2 so bios can cover it with a single MTRR */
+ if (ram_size <= 0x80000000) {
+ i440fx->pci_info.w32.begin = 0x80000000;
+ } else if (ram_size <= 0xc0000000) {
+ i440fx->pci_info.w32.begin = 0xc0000000;
+ } else {
+ i440fx->pci_info.w32.begin = 0xe0000000;
+ }
+
memory_region_init_alias(&f->pci_hole, OBJECT(d), "pci-hole", f->pci_address_space,
pci_hole_start, pci_hole_size);
memory_region_add_subregion(f->system_memory, pci_hole_start, &f->pci_hole);
+
+ pc_init_pci64_hole(&i440fx->pci_info, 0x100000000ULL + above_4g_mem_size,
+ i440fx->pci_hole64_size);
memory_region_init_alias(&f->pci_hole_64bit, OBJECT(d), "pci-hole64",
f->pci_address_space,
- pci_hole64_start, pci_hole64_size);
- if (pci_hole64_size) {
- memory_region_add_subregion(f->system_memory, pci_hole64_start,
+ i440fx->pci_info.w64.begin,
+ i440fx->pci_hole64_size);
+ if (i440fx->pci_hole64_size) {
+ memory_region_add_subregion(f->system_memory,
+ i440fx->pci_info.w64.begin,
&f->pci_hole_64bit);
}
memory_region_init_alias(&f->smram_region, OBJECT(d), "smram-region",
@@ -326,29 +407,6 @@
return b;
}
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
- ISABus **isa_bus, qemu_irq *pic,
- MemoryRegion *address_space_mem,
- MemoryRegion *address_space_io,
- ram_addr_t ram_size,
- hwaddr pci_hole_start,
- hwaddr pci_hole_size,
- hwaddr pci_hole64_start,
- hwaddr pci_hole64_size,
- MemoryRegion *pci_memory, MemoryRegion *ram_memory)
-
-{
- PCIBus *b;
-
- b = i440fx_common_init(TYPE_I440FX_PCI_DEVICE, pi440fx_state,
- piix3_devfn, isa_bus, pic,
- address_space_mem, address_space_io, ram_size,
- pci_hole_start, pci_hole_size,
- pci_hole64_start, pci_hole64_size,
- pci_memory, ram_memory);
- return b;
-}
-
/* PIIX3 PCI to ISA bridge */
static void piix3_set_irq_pic(PIIX3State *piix3, int pic_irq)
{
@@ -649,6 +707,12 @@
return "0000";
}
+static Property i440fx_props[] = {
+ DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, I440FXState,
+ pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -658,10 +722,11 @@
dc->realize = i440fx_pcihost_realize;
dc->fw_name = "pci";
dc->no_user = 1;
+ dc->props = i440fx_props;
}
static const TypeInfo i440fx_pcihost_info = {
- .name = "i440FX-pcihost",
+ .name = TYPE_I440FX_PCI_HOST_BRIDGE,
.parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(I440FXState),
.instance_init = i440fx_pcihost_initfn,
diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c
index 646204e..f00793d 100644
--- a/hw/pci-host/ppce500.c
+++ b/hw/pci-host/ppce500.c
@@ -407,6 +407,7 @@
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = e500_pcihost_initfn;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->props = pcihost_properties;
dc->vmsd = &vmstate_ppce500_pci;
}
diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c
index b41d564..e120058 100644
--- a/hw/pci-host/prep.c
+++ b/hw/pci-host/prep.c
@@ -119,6 +119,8 @@
MemoryRegion *address_space_mem = get_system_memory();
int i;
+ isa_mem_base = 0xc0000000;
+
for (i = 0; i < 4; i++) {
sysbus_init_irq(dev, &s->irq[i]);
}
@@ -210,6 +212,7 @@
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->realize = raven_pcihost_realizefn;
dc->fw_name = "pci";
dc->no_user = 1;
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 6b1b3b7..12314d8 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -29,6 +29,7 @@
*/
#include "hw/hw.h"
#include "hw/pci-host/q35.h"
+#include "qapi/visitor.h"
/****************************************************************************
* Q35 host
@@ -64,9 +65,49 @@
return "0000";
}
+static void q35_host_get_pci_hole_start(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ Q35PCIHost *s = Q35_HOST_DEVICE(obj);
+ uint32_t value = s->mch.pci_info.w32.begin;
+
+ visit_type_uint32(v, &value, name, errp);
+}
+
+static void q35_host_get_pci_hole_end(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ Q35PCIHost *s = Q35_HOST_DEVICE(obj);
+ uint32_t value = s->mch.pci_info.w32.end;
+
+ visit_type_uint32(v, &value, name, errp);
+}
+
+static void q35_host_get_pci_hole64_start(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ Q35PCIHost *s = Q35_HOST_DEVICE(obj);
+
+ visit_type_uint64(v, &s->mch.pci_info.w64.begin, name, errp);
+}
+
+static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ Q35PCIHost *s = Q35_HOST_DEVICE(obj);
+
+ visit_type_uint64(v, &s->mch.pci_info.w64.end, name, errp);
+}
+
static Property mch_props[] = {
DEFINE_PROP_UINT64("MCFG", Q35PCIHost, parent_obj.base_addr,
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT),
+ DEFINE_PROP_SIZE(PCI_HOST_PROP_PCI_HOLE64_SIZE, Q35PCIHost,
+ mch.pci_hole64_size, DEFAULT_PCI_HOLE64_SIZE),
DEFINE_PROP_END_OF_LIST(),
};
@@ -78,6 +119,7 @@
hc->root_bus_path = q35_host_root_bus_path;
dc->realize = q35_host_realize;
dc->props = mch_props;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->fw_name = "pci";
}
@@ -95,6 +137,31 @@
object_property_add_child(OBJECT(s), "mch", OBJECT(&s->mch), NULL);
qdev_prop_set_uint32(DEVICE(&s->mch), "addr", PCI_DEVFN(0, 0));
qdev_prop_set_bit(DEVICE(&s->mch), "multifunction", false);
+
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
+ q35_host_get_pci_hole_start,
+ NULL, NULL, NULL, NULL);
+
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "int",
+ q35_host_get_pci_hole_end,
+ NULL, NULL, NULL, NULL);
+
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "int",
+ q35_host_get_pci_hole64_start,
+ NULL, NULL, NULL, NULL);
+
+ object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "int",
+ q35_host_get_pci_hole64_end,
+ NULL, NULL, NULL, NULL);
+
+ /* Leave enough space for the biggest MCFG BAR */
+ /* TODO: this matches current bios behaviour, but
+ * it's not a power of two, which means an MTRR
+ * can't cover it exactly.
+ */
+ s->mch.pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT +
+ MCH_HOST_BRIDGE_PCIEXBAR_MAX;
+ s->mch.pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS;
}
static const TypeInfo q35_host_info = {
@@ -252,17 +319,8 @@
static int mch_init(PCIDevice *d)
{
int i;
- hwaddr pci_hole64_size;
MCHPCIState *mch = MCH_PCI_DEVICE(d);
- /* Leave enough space for the biggest MCFG BAR */
- /* TODO: this matches current bios behaviour, but
- * it's not a power of two, which means an MTRR
- * can't cover it exactly.
- */
- mch->guest_info->pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT +
- MCH_HOST_BRIDGE_PCIEXBAR_MAX;
-
/* setup pci memory regions */
memory_region_init_alias(&mch->pci_hole, OBJECT(mch), "pci-hole",
mch->pci_address_space,
@@ -270,15 +328,16 @@
0x100000000ULL - mch->below_4g_mem_size);
memory_region_add_subregion(mch->system_memory, mch->below_4g_mem_size,
&mch->pci_hole);
- pci_hole64_size = (sizeof(hwaddr) == 4 ? 0 :
- ((uint64_t)1 << 62));
+
+ pc_init_pci64_hole(&mch->pci_info, 0x100000000ULL + mch->above_4g_mem_size,
+ mch->pci_hole64_size);
memory_region_init_alias(&mch->pci_hole_64bit, OBJECT(mch), "pci-hole64",
mch->pci_address_space,
- 0x100000000ULL + mch->above_4g_mem_size,
- pci_hole64_size);
- if (pci_hole64_size) {
+ mch->pci_info.w64.begin,
+ mch->pci_hole64_size);
+ if (mch->pci_hole64_size) {
memory_region_add_subregion(mch->system_memory,
- 0x100000000ULL + mch->above_4g_mem_size,
+ mch->pci_info.w64.begin,
&mch->pci_hole_64bit);
}
/* smram */
@@ -306,6 +365,7 @@
k->init = mch_init;
k->config_write = mch_write_config;
dc->reset = mch_reset;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->desc = "Host bridge";
dc->vmsd = &vmstate_mch;
k->vendor_id = PCI_VENDOR_ID_INTEL;
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 81cf5a9..4c004f5 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -397,7 +397,7 @@
pci_update_mappings(s);
if (pc->is_bridge) {
- PCIBridge *b = container_of(s, PCIBridge, dev);
+ PCIBridge *b = PCI_BRIDGE(s);
pci_bridge_update_mappings(b);
}
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 02a396b..a90671d 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -141,8 +141,9 @@
MemoryRegion *parent_space,
bool enabled)
{
- pcibus_t base = pci_bridge_get_base(&bridge->dev, type);
- pcibus_t limit = pci_bridge_get_limit(&bridge->dev, type);
+ PCIDevice *bridge_dev = PCI_DEVICE(bridge);
+ pcibus_t base = pci_bridge_get_base(bridge_dev, type);
+ pcibus_t limit = pci_bridge_get_limit(bridge_dev, type);
/* TODO: this doesn't handle base = 0 limit = 2^64 - 1 correctly.
* Apparently no way to do this with existing memory APIs. */
pcibus_t size = enabled && limit >= base ? limit + 1 - base : 0;
@@ -154,7 +155,8 @@
static void pci_bridge_init_vga_aliases(PCIBridge *br, PCIBus *parent,
MemoryRegion *alias_vga)
{
- uint16_t brctl = pci_get_word(br->dev.config + PCI_BRIDGE_CONTROL);
+ PCIDevice *pd = PCI_DEVICE(br);
+ uint16_t brctl = pci_get_word(pd->config + PCI_BRIDGE_CONTROL);
memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_LO], OBJECT(br),
"pci_bridge_vga_io_lo", &br->address_space_io,
@@ -167,7 +169,7 @@
QEMU_PCI_VGA_MEM_BASE, QEMU_PCI_VGA_MEM_SIZE);
if (brctl & PCI_BRIDGE_CTL_VGA) {
- pci_register_vga(&br->dev, &alias_vga[QEMU_PCI_VGA_MEM],
+ pci_register_vga(pd, &alias_vga[QEMU_PCI_VGA_MEM],
&alias_vga[QEMU_PCI_VGA_IO_LO],
&alias_vga[QEMU_PCI_VGA_IO_HI]);
}
@@ -175,9 +177,10 @@
static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br)
{
- PCIBus *parent = br->dev.bus;
+ PCIDevice *pd = PCI_DEVICE(br);
+ PCIBus *parent = pd->bus;
PCIBridgeWindows *w = g_new(PCIBridgeWindows, 1);
- uint16_t cmd = pci_get_word(br->dev.config + PCI_COMMAND);
+ uint16_t cmd = pci_get_word(pd->config + PCI_COMMAND);
pci_bridge_init_alias(br, &w->alias_pref_mem,
PCI_BASE_ADDRESS_MEM_PREFETCH,
@@ -205,12 +208,13 @@
static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w)
{
- PCIBus *parent = br->dev.bus;
+ PCIDevice *pd = PCI_DEVICE(br);
+ PCIBus *parent = pd->bus;
memory_region_del_subregion(parent->address_space_io, &w->alias_io);
memory_region_del_subregion(parent->address_space_mem, &w->alias_mem);
memory_region_del_subregion(parent->address_space_mem, &w->alias_pref_mem);
- pci_unregister_vga(&br->dev);
+ pci_unregister_vga(pd);
}
static void pci_bridge_region_cleanup(PCIBridge *br, PCIBridgeWindows *w)
@@ -241,7 +245,7 @@
void pci_bridge_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len)
{
- PCIBridge *s = container_of(d, PCIBridge, dev);
+ PCIBridge *s = PCI_BRIDGE(d);
uint16_t oldctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
uint16_t newctl;
@@ -331,7 +335,7 @@
int pci_bridge_initfn(PCIDevice *dev, const char *typename)
{
PCIBus *parent = dev->bus;
- PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
+ PCIBridge *br = PCI_BRIDGE(dev);
PCIBus *sec_bus = &br->sec_bus;
pci_word_test_and_set_mask(dev->config + PCI_STATUS,
@@ -379,7 +383,7 @@
/* default qdev clean up function for PCI-to-PCI bridge */
void pci_bridge_exitfn(PCIDevice *pci_dev)
{
- PCIBridge *s = DO_UPCAST(PCIBridge, dev, pci_dev);
+ PCIBridge *s = PCI_BRIDGE(pci_dev);
assert(QLIST_EMPTY(&s->sec_bus.child));
QLIST_REMOVE(&s->sec_bus, sibling);
pci_bridge_region_del(s, s->windows);
@@ -400,3 +404,17 @@
br->map_irq = map_irq;
br->bus_name = bus_name;
}
+
+static const TypeInfo pci_bridge_type_info = {
+ .name = TYPE_PCI_BRIDGE,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(PCIBridge),
+ .abstract = true,
+};
+
+static void pci_bridge_register_types(void)
+{
+ type_register_static(&pci_bridge_type_info);
+}
+
+type_init(pci_bridge_register_types)
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 62bd0b8..50af3c1 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -305,7 +305,7 @@
dev->exp.hpev_notified = false;
- pci_bus_hotplug(pci_bridge_get_sec_bus(DO_UPCAST(PCIBridge, dev, dev)),
+ pci_bus_hotplug(pci_bridge_get_sec_bus(PCI_BRIDGE(dev)),
pcie_cap_slot_hotplug, &dev->qdev);
}
diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
index 91b53a0..2adb030 100644
--- a/hw/pci/pcie_port.c
+++ b/hw/pci/pcie_port.c
@@ -116,3 +116,55 @@
{
QLIST_REMOVE(s, next);
}
+
+static Property pcie_port_props[] = {
+ DEFINE_PROP_UINT8("port", PCIEPort, port, 0),
+ DEFINE_PROP_UINT16("aer_log_max", PCIEPort,
+ parent_obj.parent_obj.exp.aer_log.log_max,
+ PCIE_AER_LOG_MAX_DEFAULT),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void pcie_port_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->props = pcie_port_props;
+}
+
+static const TypeInfo pcie_port_type_info = {
+ .name = TYPE_PCIE_PORT,
+ .parent = TYPE_PCI_BRIDGE,
+ .instance_size = sizeof(PCIEPort),
+ .abstract = true,
+ .class_init = pcie_port_class_init,
+};
+
+static Property pcie_slot_props[] = {
+ DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
+ DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void pcie_slot_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->props = pcie_slot_props;
+}
+
+static const TypeInfo pcie_slot_type_info = {
+ .name = TYPE_PCIE_SLOT,
+ .parent = TYPE_PCIE_PORT,
+ .instance_size = sizeof(PCIESlot),
+ .abstract = true,
+ .class_init = pcie_slot_class_init,
+};
+
+static void pcie_port_register_types(void)
+{
+ type_register_static(&pcie_port_type_info);
+ type_register_static(&pcie_slot_type_info);
+}
+
+type_init(pcie_port_register_types)
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index f00a62a..e79612b 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -124,13 +124,14 @@
}
static int ppce500_load_device_tree(CPUPPCState *env,
+ QEMUMachineInitArgs *args,
PPCE500Params *params,
hwaddr addr,
hwaddr initrd_base,
hwaddr initrd_size)
{
int ret = -1;
- uint64_t mem_reg_property[] = { 0, cpu_to_be64(params->ram_size) };
+ uint64_t mem_reg_property[] = { 0, cpu_to_be64(args->ram_size) };
int fdt_size;
void *fdt;
uint8_t hypercall[16];
@@ -205,7 +206,7 @@
}
ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
- params->kernel_cmdline);
+ args->kernel_cmdline);
if (ret < 0)
fprintf(stderr, "couldn't set /chosen/bootargs\n");
@@ -559,7 +560,7 @@
return mpic;
}
-void ppce500_init(PPCE500Params *params)
+void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params)
{
MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *ram = g_new(MemoryRegion, 1);
@@ -584,8 +585,8 @@
PPCE500CCSRState *ccsr;
/* Setup CPUs */
- if (params->cpu_model == NULL) {
- params->cpu_model = "e500v2_v30";
+ if (args->cpu_model == NULL) {
+ args->cpu_model = "e500v2_v30";
}
irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
@@ -595,7 +596,7 @@
CPUState *cs;
qemu_irq *input;
- cpu = cpu_ppc_init(params->cpu_model);
+ cpu = cpu_ppc_init(args->cpu_model);
if (cpu == NULL) {
fprintf(stderr, "Unable to initialize CPU!\n");
exit(1);
@@ -634,7 +635,7 @@
/* Fixup Memory size on a alignment boundary */
ram_size &= ~(RAM_SIZES_ALIGN - 1);
- params->ram_size = ram_size;
+ args->ram_size = ram_size;
/* Register Memory */
memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size);
@@ -701,11 +702,11 @@
sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);
/* Load kernel. */
- if (params->kernel_filename) {
- kernel_size = load_uimage(params->kernel_filename, &entry,
+ if (args->kernel_filename) {
+ kernel_size = load_uimage(args->kernel_filename, &entry,
&loadaddr, NULL);
if (kernel_size < 0) {
- kernel_size = load_elf(params->kernel_filename, NULL, NULL,
+ kernel_size = load_elf(args->kernel_filename, NULL, NULL,
&elf_entry, &elf_lowaddr, NULL, 1,
ELF_MACHINE, 0);
entry = elf_entry;
@@ -714,7 +715,7 @@
/* XXX try again as binary */
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
- params->kernel_filename);
+ args->kernel_filename);
exit(1);
}
@@ -726,14 +727,14 @@
}
/* Load initrd. */
- if (params->initrd_filename) {
+ if (args->initrd_filename) {
initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK;
- initrd_size = load_image_targphys(params->initrd_filename, initrd_base,
+ initrd_size = load_image_targphys(args->initrd_filename, initrd_base,
ram_size - initrd_base);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
- params->initrd_filename);
+ args->initrd_filename);
exit(1);
}
@@ -741,12 +742,12 @@
}
/* If we're loading a kernel directly, we must load the device tree too. */
- if (params->kernel_filename) {
+ if (args->kernel_filename) {
struct boot_info *boot_info;
int dt_size;
- dt_size = ppce500_load_device_tree(env, params, dt_base, initrd_base,
- initrd_size);
+ dt_size = ppce500_load_device_tree(env, args, params, dt_base,
+ initrd_base, initrd_size);
if (dt_size < 0) {
fprintf(stderr, "couldn't load device tree\n");
exit(1);
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
index 226c93d..52726a2 100644
--- a/hw/ppc/e500.h
+++ b/hw/ppc/e500.h
@@ -1,25 +1,18 @@
#ifndef PPCE500_H
#define PPCE500_H
+#include "hw/boards.h"
+
typedef struct PPCE500Params {
- /* Standard QEMU machine init params */
- ram_addr_t ram_size;
- const char *boot_device;
- const char *kernel_filename;
- const char *kernel_cmdline;
- const char *initrd_filename;
- const char *cpu_model;
int pci_first_slot;
int pci_nr_slots;
- /* e500-specific params */
-
/* required -- must at least add toplevel board compatible */
void (*fixup_devtree)(struct PPCE500Params *params, void *fdt);
int mpic_version;
} PPCE500Params;
-void ppce500_init(PPCE500Params *params);
+void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params);
#endif
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index c852995..bf65b69 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -30,19 +30,7 @@
static void e500plat_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *boot_device = args->boot_device;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
PPCE500Params params = {
- .ram_size = ram_size,
- .boot_device = boot_device,
- .kernel_filename = kernel_filename,
- .kernel_cmdline = kernel_cmdline,
- .initrd_filename = initrd_filename,
- .cpu_model = cpu_model,
.pci_first_slot = 0x1,
.pci_nr_slots = PCI_SLOT_MAX - 1,
.fixup_devtree = e500plat_fixup_devtree,
@@ -55,7 +43,7 @@
params.mpic_version = OPENPIC_MODEL_FSL_MPIC_20;
}
- ppce500_init(¶ms);
+ ppce500_init(args, ¶ms);
}
static QEMUMachine e500plat_machine = {
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index fe80348..7ef806e 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -152,6 +152,7 @@
CPUPPCState *env = NULL;
char *filename;
qemu_irq *pic, **openpic_irqs;
+ MemoryRegion *isa = g_new(MemoryRegion, 1);
MemoryRegion *unin_memory = g_new(MemoryRegion, 1);
MemoryRegion *unin2_memory = g_new(MemoryRegion, 1);
int linux_boot, i, j, k;
@@ -288,7 +289,9 @@
}
/* Register 8 MB of ISA IO space */
- isa_mmio_init(0xf2000000, 0x00800000);
+ memory_region_init_alias(isa, NULL, "isa_mmio",
+ get_system_io(), 0, 0x00800000);
+ memory_region_add_subregion(get_system_memory(), 0xf2000000, isa);
/* UniN init: XXX should be a real device */
memory_region_init_io(unin_memory, NULL, &unin_ops, token, "unin", 0x1000);
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 8b8c6b9..42bb9d5 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -87,6 +87,7 @@
int linux_boot, i;
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *bios = g_new(MemoryRegion, 1);
+ MemoryRegion *isa = g_new(MemoryRegion, 1);
uint32_t kernel_base, initrd_base, cmdline_base = 0;
int32_t kernel_size, initrd_size;
PCIBus *pci_bus;
@@ -225,7 +226,9 @@
}
/* Register 2 MB of ISA IO space */
- isa_mmio_init(0xfe000000, 0x00200000);
+ memory_region_init_alias(isa, NULL, "isa_mmio",
+ get_system_io(), 0, 0x00200000);
+ memory_region_add_subregion(sysmem, 0xfe000000, isa);
/* XXX: we register only 1 output pin for heathrow PIC */
heathrow_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c
index 444da02..1888e75 100644
--- a/hw/ppc/mpc8544ds.c
+++ b/hw/ppc/mpc8544ds.c
@@ -28,26 +28,14 @@
static void mpc8544ds_init(QEMUMachineInitArgs *args)
{
- ram_addr_t ram_size = args->ram_size;
- const char *boot_device = args->boot_device;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
PPCE500Params params = {
- .ram_size = ram_size,
- .boot_device = boot_device,
- .kernel_filename = kernel_filename,
- .kernel_cmdline = kernel_cmdline,
- .initrd_filename = initrd_filename,
- .cpu_model = cpu_model,
.pci_first_slot = 0x11,
.pci_nr_slots = 2,
.fixup_devtree = mpc8544ds_fixup_devtree,
.mpic_version = OPENPIC_MODEL_FSL_MPIC_20,
};
- ppce500_init(¶ms);
+ ppce500_init(args, ¶ms);
}
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index e1c095c..59b41cb 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -471,7 +471,7 @@
return env->spr[SPR_TBL];
}
- tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
+ tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);
LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
return tb;
@@ -482,7 +482,7 @@
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
+ tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);
LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
return tb >> 32;
@@ -510,9 +510,9 @@
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
+ tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);
tb &= 0xFFFFFFFF00000000ULL;
- cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+ cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
&tb_env->tb_offset, tb | (uint64_t)value);
}
@@ -521,9 +521,9 @@
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
+ tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset);
tb &= 0x00000000FFFFFFFFULL;
- cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+ cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
&tb_env->tb_offset, ((uint64_t)value << 32) | tb);
}
@@ -537,7 +537,7 @@
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
+ tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);
LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
return tb;
@@ -548,7 +548,7 @@
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
+ tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);
LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
return tb >> 32;
@@ -559,9 +559,9 @@
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
+ tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);
tb &= 0xFFFFFFFF00000000ULL;
- cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+ cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
&tb_env->atb_offset, tb | (uint64_t)value);
}
@@ -570,9 +570,9 @@
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
- tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
+ tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset);
tb &= 0x00000000FFFFFFFFULL;
- cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
+ cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
&tb_env->atb_offset, ((uint64_t)value << 32) | tb);
}
@@ -583,7 +583,7 @@
/* If the time base is already frozen, do nothing */
if (tb_env->tb_freq != 0) {
- vmclk = qemu_get_clock_ns(vm_clock);
+ vmclk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
/* Get the time base */
tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
/* Get the alternate time base */
@@ -605,7 +605,7 @@
/* If the time base is not frozen, do nothing */
if (tb_env->tb_freq == 0) {
- vmclk = qemu_get_clock_ns(vm_clock);
+ vmclk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
/* Get the time base from tb_offset */
tb = tb_env->tb_offset;
/* Get the alternate time base from atb_offset */
@@ -625,7 +625,7 @@
uint32_t decr;
int64_t diff;
- diff = next - qemu_get_clock_ns(vm_clock);
+ diff = next - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (diff >= 0) {
decr = muldiv64(diff, tb_env->decr_freq, get_ticks_per_sec());
} else if (tb_env->flags & PPC_TIMER_BOOKE) {
@@ -661,7 +661,7 @@
ppc_tb_t *tb_env = env->tb_env;
uint64_t diff;
- diff = qemu_get_clock_ns(vm_clock) - tb_env->purr_start;
+ diff = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - tb_env->purr_start;
return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, get_ticks_per_sec());
}
@@ -701,7 +701,7 @@
return;
}
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
if (is_excp) {
next += *nextp - now;
@@ -711,7 +711,7 @@
}
*nextp = next;
/* Adjust timer */
- qemu_mod_timer(timer, next);
+ timer_mod(timer, next);
/* If we set a negative value and the decrementer was positive, raise an
* exception.
@@ -776,7 +776,7 @@
ppc_tb_t *tb_env = cpu->env.tb_env;
tb_env->purr_load = value;
- tb_env->purr_start = qemu_get_clock_ns(vm_clock);
+ tb_env->purr_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
@@ -806,11 +806,11 @@
env->tb_env = tb_env;
tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
/* Create new timer */
- tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, cpu);
+ tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_decr_cb, cpu);
if (0) {
/* XXX: find a suitable condition to enable the hypervisor decrementer
*/
- tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb,
+ tb_env->hdecr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_ppc_hdecr_cb,
cpu);
} else {
tb_env->hdecr_timer = NULL;
@@ -877,7 +877,7 @@
cpu = ppc_env_get_cpu(env);
tb_env = env->tb_env;
ppc40x_timer = tb_env->opaque;
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
case 0:
next = 1 << 9;
@@ -898,7 +898,7 @@
next = now + muldiv64(next, get_ticks_per_sec(), tb_env->tb_freq);
if (next == now)
next++;
- qemu_mod_timer(ppc40x_timer->fit_timer, next);
+ timer_mod(ppc40x_timer->fit_timer, next);
env->spr[SPR_40x_TSR] |= 1 << 26;
if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) {
ppc_set_irq(cpu, PPC_INTERRUPT_FIT, 1);
@@ -920,18 +920,18 @@
(is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
/* Stop PIT */
LOG_TB("%s: stop PIT\n", __func__);
- qemu_del_timer(tb_env->decr_timer);
+ timer_del(tb_env->decr_timer);
} else {
LOG_TB("%s: start PIT %016" PRIx64 "\n",
__func__, ppc40x_timer->pit_reload);
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
next = now + muldiv64(ppc40x_timer->pit_reload,
get_ticks_per_sec(), tb_env->decr_freq);
if (is_excp)
next += tb_env->decr_next - now;
if (next == now)
next++;
- qemu_mod_timer(tb_env->decr_timer, next);
+ timer_mod(tb_env->decr_timer, next);
tb_env->decr_next = next;
}
}
@@ -973,7 +973,7 @@
cpu = ppc_env_get_cpu(env);
tb_env = env->tb_env;
ppc40x_timer = tb_env->opaque;
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
case 0:
next = 1 << 17;
@@ -999,12 +999,12 @@
switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
case 0x0:
case 0x1:
- qemu_mod_timer(ppc40x_timer->wdt_timer, next);
+ timer_mod(ppc40x_timer->wdt_timer, next);
ppc40x_timer->wdt_next = next;
env->spr[SPR_40x_TSR] |= 1 << 31;
break;
case 0x2:
- qemu_mod_timer(ppc40x_timer->wdt_timer, next);
+ timer_mod(ppc40x_timer->wdt_timer, next);
ppc40x_timer->wdt_next = next;
env->spr[SPR_40x_TSR] |= 1 << 30;
if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) {
@@ -1076,11 +1076,11 @@
LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
if (ppc40x_timer != NULL) {
/* We use decr timer for PIT */
- tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_4xx_pit_cb, env);
+ tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_pit_cb, env);
ppc40x_timer->fit_timer =
- qemu_new_timer_ns(vm_clock, &cpu_4xx_fit_cb, env);
+ timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_fit_cb, env);
ppc40x_timer->wdt_timer =
- qemu_new_timer_ns(vm_clock, &cpu_4xx_wdt_cb, env);
+ timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_wdt_cb, env);
ppc40x_timer->decr_excp = decr_excp;
}
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 290f71a..0ef5254 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1348,7 +1348,7 @@
switch (addr) {
case 0x00:
/* Time base counter */
- ret = muldiv64(qemu_get_clock_ns(vm_clock) + gpt->tb_offset,
+ ret = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + gpt->tb_offset,
gpt->tb_freq, get_ticks_per_sec());
break;
case 0x10:
@@ -1405,7 +1405,7 @@
case 0x00:
/* Time base counter */
gpt->tb_offset = muldiv64(value, get_ticks_per_sec(), gpt->tb_freq)
- - qemu_get_clock_ns(vm_clock);
+ - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ppc4xx_gpt_compute_timer(gpt);
break;
case 0x10:
@@ -1476,7 +1476,7 @@
int i;
gpt = opaque;
- qemu_del_timer(gpt->timer);
+ timer_del(gpt->timer);
gpt->oe = 0x00000000;
gpt->ol = 0x00000000;
gpt->im = 0x00000000;
@@ -1497,7 +1497,7 @@
for (i = 0; i < 5; i++) {
gpt->irqs[i] = irqs[i];
}
- gpt->timer = qemu_new_timer_ns(vm_clock, &ppc4xx_gpt_cb, gpt);
+ gpt->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ppc4xx_gpt_cb, gpt);
#ifdef DEBUG_GPT
printf("%s: offset " TARGET_FMT_plx "\n", __func__, base);
#endif
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 5b039ab..369ab9e 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -164,6 +164,7 @@
const char *initrd_filename = args->initrd_filename;
unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
MemoryRegion *address_space_mem = get_system_memory();
+ MemoryRegion *isa = g_new(MemoryRegion, 1);
MemoryRegion *ram_memories
= g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
@@ -225,7 +226,9 @@
exit(1);
}
- isa_mmio_init(PPC440EP_PCI_IO, PPC440EP_PCI_IOLEN);
+ memory_region_init_alias(isa, NULL, "isa_mmio",
+ get_system_io(), 0, PPC440EP_PCI_IOLEN);
+ memory_region_add_subregion(get_system_memory(), PPC440EP_PCI_IO, isa);
if (serial_hds[0] != NULL) {
serial_mm_init(address_space_mem, 0xef600300, 0, pic[0],
diff --git a/hw/ppc/ppc_booke.c b/hw/ppc/ppc_booke.c
index 000c27f..8bbfc72 100644
--- a/hw/ppc/ppc_booke.c
+++ b/hw/ppc/ppc_booke.c
@@ -136,7 +136,7 @@
uint64_t period;
uint64_t now;
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
tb = cpu_ppc_get_tb(tb_env, now, tb_env->tb_offset);
period = 1ULL << target_bit;
delta_tick = period - (tb & (period - 1));
@@ -167,7 +167,7 @@
(*next)++;
}
- qemu_mod_timer(timer, *next);
+ timer_mod(timer, *next);
}
static void booke_decr_cb(void *opaque)
@@ -303,12 +303,12 @@
tb_env->tb_freq = freq;
tb_env->decr_freq = freq;
tb_env->opaque = booke_timer;
- tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, cpu);
+ tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &booke_decr_cb, cpu);
booke_timer->fit_timer =
- qemu_new_timer_ns(vm_clock, &booke_fit_cb, cpu);
+ timer_new_ns(QEMU_CLOCK_VIRTUAL, &booke_fit_cb, cpu);
booke_timer->wdt_timer =
- qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu);
+ timer_new_ns(QEMU_CLOCK_VIRTUAL, &booke_wdt_cb, cpu);
ret = kvmppc_booke_watchdog_enable(cpu);
diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c
index 11b7de2..78b23fa 100644
--- a/hw/ppc/ppce500_spin.c
+++ b/hw/ppc/ppce500_spin.c
@@ -42,8 +42,12 @@
uint64_t reserved;
} QEMU_PACKED SpinInfo;
-typedef struct spin_state {
- SysBusDevice busdev;
+#define TYPE_E500_SPIN "e500-spin"
+#define E500_SPIN(obj) OBJECT_CHECK(SpinState, (obj), TYPE_E500_SPIN)
+
+typedef struct SpinState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
SpinInfo spin[MAX_CPUS];
} SpinState;
@@ -187,9 +191,7 @@
static int ppce500_spin_initfn(SysBusDevice *dev)
{
- SpinState *s;
-
- s = FROM_SYSBUS(SpinState, SYS_BUS_DEVICE(dev));
+ SpinState *s = E500_SPIN(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &spin_rw_ops, s,
"e500 spin pv device", sizeof(SpinInfo) * MAX_CPUS);
@@ -208,7 +210,7 @@
}
static const TypeInfo ppce500_spin_info = {
- .name = "e500-spin",
+ .name = TYPE_E500_SPIN,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SpinState),
.class_init = ppce500_spin_class_init,
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 19f2442..7e04b1a 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -410,7 +410,7 @@
.read = { PPC_prep_io_readb, PPC_prep_io_readw, PPC_prep_io_readl },
.write = { PPC_prep_io_writeb, PPC_prep_io_writew, PPC_prep_io_writel },
},
- .endianness = DEVICE_LITTLE_ENDIAN,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
#define NVRAM_SIZE 0x2000
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 48ae092..4b566aa 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -32,6 +32,7 @@
#include "sysemu/cpus.h"
#include "sysemu/kvm.h"
#include "kvm_ppc.h"
+#include "mmu-hash64.h"
#include "hw/boards.h"
#include "hw/ppc/ppc.h"
@@ -128,6 +129,34 @@
return first;
}
+static XICSState *try_create_xics(const char *type, int nr_servers,
+ int nr_irqs)
+{
+ DeviceState *dev;
+
+ dev = qdev_create(NULL, type);
+ qdev_prop_set_uint32(dev, "nr_servers", nr_servers);
+ qdev_prop_set_uint32(dev, "nr_irqs", nr_irqs);
+ if (qdev_init(dev) < 0) {
+ return NULL;
+ }
+
+ return XICS(dev);
+}
+
+static XICSState *xics_system_init(int nr_servers, int nr_irqs)
+{
+ XICSState *icp = NULL;
+
+ icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs);
+ if (!icp) {
+ perror("Failed to create XICS\n");
+ abort();
+ }
+
+ return icp;
+}
+
static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr)
{
int ret = 0, offset;
@@ -666,7 +695,7 @@
env->spr[SPR_HIOR] = 0;
- env->external_htab = spapr->htab;
+ env->external_htab = (uint8_t *)spapr->htab;
env->htab_base = -1;
env->htab_mask = HTAB_SIZE(spapr) - 1;
env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab |
@@ -710,6 +739,330 @@
}
}
+static const VMStateDescription vmstate_spapr = {
+ .name = "spapr",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(next_irq, sPAPREnvironment),
+
+ /* RTC offset */
+ VMSTATE_UINT64(rtc_offset, sPAPREnvironment),
+
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+#define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2))
+#define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID)
+#define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY)
+#define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY))
+
+static int htab_save_setup(QEMUFile *f, void *opaque)
+{
+ sPAPREnvironment *spapr = opaque;
+
+ /* "Iteration" header */
+ qemu_put_be32(f, spapr->htab_shift);
+
+ if (spapr->htab) {
+ spapr->htab_save_index = 0;
+ spapr->htab_first_pass = true;
+ } else {
+ assert(kvm_enabled());
+
+ spapr->htab_fd = kvmppc_get_htab_fd(false);
+ if (spapr->htab_fd < 0) {
+ fprintf(stderr, "Unable to open fd for reading hash table from KVM: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ }
+
+
+ return 0;
+}
+
+static void htab_save_first_pass(QEMUFile *f, sPAPREnvironment *spapr,
+ int64_t max_ns)
+{
+ int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64;
+ int index = spapr->htab_save_index;
+ int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
+
+ assert(spapr->htab_first_pass);
+
+ do {
+ int chunkstart;
+
+ /* Consume invalid HPTEs */
+ while ((index < htabslots)
+ && !HPTE_VALID(HPTE(spapr->htab, index))) {
+ index++;
+ CLEAN_HPTE(HPTE(spapr->htab, index));
+ }
+
+ /* Consume valid HPTEs */
+ chunkstart = index;
+ while ((index < htabslots)
+ && HPTE_VALID(HPTE(spapr->htab, index))) {
+ index++;
+ CLEAN_HPTE(HPTE(spapr->htab, index));
+ }
+
+ if (index > chunkstart) {
+ int n_valid = index - chunkstart;
+
+ qemu_put_be32(f, chunkstart);
+ qemu_put_be16(f, n_valid);
+ qemu_put_be16(f, 0);
+ qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
+ HASH_PTE_SIZE_64 * n_valid);
+
+ if ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
+ break;
+ }
+ }
+ } while ((index < htabslots) && !qemu_file_rate_limit(f));
+
+ if (index >= htabslots) {
+ assert(index == htabslots);
+ index = 0;
+ spapr->htab_first_pass = false;
+ }
+ spapr->htab_save_index = index;
+}
+
+static int htab_save_later_pass(QEMUFile *f, sPAPREnvironment *spapr,
+ int64_t max_ns)
+{
+ bool final = max_ns < 0;
+ int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64;
+ int examined = 0, sent = 0;
+ int index = spapr->htab_save_index;
+ int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
+
+ assert(!spapr->htab_first_pass);
+
+ do {
+ int chunkstart, invalidstart;
+
+ /* Consume non-dirty HPTEs */
+ while ((index < htabslots)
+ && !HPTE_DIRTY(HPTE(spapr->htab, index))) {
+ index++;
+ examined++;
+ }
+
+ chunkstart = index;
+ /* Consume valid dirty HPTEs */
+ while ((index < htabslots)
+ && HPTE_DIRTY(HPTE(spapr->htab, index))
+ && HPTE_VALID(HPTE(spapr->htab, index))) {
+ CLEAN_HPTE(HPTE(spapr->htab, index));
+ index++;
+ examined++;
+ }
+
+ invalidstart = index;
+ /* Consume invalid dirty HPTEs */
+ while ((index < htabslots)
+ && HPTE_DIRTY(HPTE(spapr->htab, index))
+ && !HPTE_VALID(HPTE(spapr->htab, index))) {
+ CLEAN_HPTE(HPTE(spapr->htab, index));
+ index++;
+ examined++;
+ }
+
+ if (index > chunkstart) {
+ int n_valid = invalidstart - chunkstart;
+ int n_invalid = index - invalidstart;
+
+ qemu_put_be32(f, chunkstart);
+ qemu_put_be16(f, n_valid);
+ qemu_put_be16(f, n_invalid);
+ qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
+ HASH_PTE_SIZE_64 * n_valid);
+ sent += index - chunkstart;
+
+ if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
+ break;
+ }
+ }
+
+ if (examined >= htabslots) {
+ break;
+ }
+
+ if (index >= htabslots) {
+ assert(index == htabslots);
+ index = 0;
+ }
+ } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final));
+
+ if (index >= htabslots) {
+ assert(index == htabslots);
+ index = 0;
+ }
+
+ spapr->htab_save_index = index;
+
+ return (examined >= htabslots) && (sent == 0) ? 1 : 0;
+}
+
+#define MAX_ITERATION_NS 5000000 /* 5 ms */
+#define MAX_KVM_BUF_SIZE 2048
+
+static int htab_save_iterate(QEMUFile *f, void *opaque)
+{
+ sPAPREnvironment *spapr = opaque;
+ int rc = 0;
+
+ /* Iteration header */
+ qemu_put_be32(f, 0);
+
+ if (!spapr->htab) {
+ assert(kvm_enabled());
+
+ rc = kvmppc_save_htab(f, spapr->htab_fd,
+ MAX_KVM_BUF_SIZE, MAX_ITERATION_NS);
+ if (rc < 0) {
+ return rc;
+ }
+ } else if (spapr->htab_first_pass) {
+ htab_save_first_pass(f, spapr, MAX_ITERATION_NS);
+ } else {
+ rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS);
+ }
+
+ /* End marker */
+ qemu_put_be32(f, 0);
+ qemu_put_be16(f, 0);
+ qemu_put_be16(f, 0);
+
+ return rc;
+}
+
+static int htab_save_complete(QEMUFile *f, void *opaque)
+{
+ sPAPREnvironment *spapr = opaque;
+
+ /* Iteration header */
+ qemu_put_be32(f, 0);
+
+ if (!spapr->htab) {
+ int rc;
+
+ assert(kvm_enabled());
+
+ rc = kvmppc_save_htab(f, spapr->htab_fd, MAX_KVM_BUF_SIZE, -1);
+ if (rc < 0) {
+ return rc;
+ }
+ close(spapr->htab_fd);
+ spapr->htab_fd = -1;
+ } else {
+ htab_save_later_pass(f, spapr, -1);
+ }
+
+ /* End marker */
+ qemu_put_be32(f, 0);
+ qemu_put_be16(f, 0);
+ qemu_put_be16(f, 0);
+
+ return 0;
+}
+
+static int htab_load(QEMUFile *f, void *opaque, int version_id)
+{
+ sPAPREnvironment *spapr = opaque;
+ uint32_t section_hdr;
+ int fd = -1;
+
+ if (version_id < 1 || version_id > 1) {
+ fprintf(stderr, "htab_load() bad version\n");
+ return -EINVAL;
+ }
+
+ section_hdr = qemu_get_be32(f);
+
+ if (section_hdr) {
+ /* First section, just the hash shift */
+ if (spapr->htab_shift != section_hdr) {
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ if (!spapr->htab) {
+ assert(kvm_enabled());
+
+ fd = kvmppc_get_htab_fd(true);
+ if (fd < 0) {
+ fprintf(stderr, "Unable to open fd to restore KVM hash table: %s\n",
+ strerror(errno));
+ }
+ }
+
+ while (true) {
+ uint32_t index;
+ uint16_t n_valid, n_invalid;
+
+ index = qemu_get_be32(f);
+ n_valid = qemu_get_be16(f);
+ n_invalid = qemu_get_be16(f);
+
+ if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) {
+ /* End of Stream */
+ break;
+ }
+
+ if ((index + n_valid + n_invalid) >
+ (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) {
+ /* Bad index in stream */
+ fprintf(stderr, "htab_load() bad index %d (%hd+%hd entries) "
+ "in htab stream (htab_shift=%d)\n", index, n_valid, n_invalid,
+ spapr->htab_shift);
+ return -EINVAL;
+ }
+
+ if (spapr->htab) {
+ if (n_valid) {
+ qemu_get_buffer(f, HPTE(spapr->htab, index),
+ HASH_PTE_SIZE_64 * n_valid);
+ }
+ if (n_invalid) {
+ memset(HPTE(spapr->htab, index + n_valid), 0,
+ HASH_PTE_SIZE_64 * n_invalid);
+ }
+ } else {
+ int rc;
+
+ assert(fd >= 0);
+
+ rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+ }
+
+ if (!spapr->htab) {
+ assert(fd >= 0);
+ close(fd);
+ }
+
+ return 0;
+}
+
+static SaveVMHandlers savevm_htab_handlers = {
+ .save_live_setup = htab_save_setup,
+ .save_live_iterate = htab_save_iterate,
+ .save_live_complete = htab_save_complete,
+ .load_state = htab_load,
+};
+
/* pSeries LPAR / sPAPR hardware init */
static void ppc_spapr_init(QEMUMachineInitArgs *args)
{
@@ -848,9 +1201,6 @@
/* Set up EPOW events infrastructure */
spapr_events_init(spapr);
- /* Set up IOMMU */
- spapr_iommu_init();
-
/* Set up VIO bus */
spapr->vio_bus = spapr_vio_bus_init();
@@ -953,6 +1303,10 @@
spapr->entry_point = 0x100;
+ vmstate_register(NULL, 0, &vmstate_spapr, spapr);
+ register_savevm_live(NULL, "spapr/htab", -1, 1,
+ &savevm_htab_handlers, spapr);
+
/* Prepare the device tree */
spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
initrd_base, initrd_size,
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index ed32dec..67d6cd9 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -115,7 +115,7 @@
}
ppc_hash64_store_hpte1(env, hpte, ptel);
/* eieio(); FIXME: need some sort of barrier for smp? */
- ppc_hash64_store_hpte0(env, hpte, pteh);
+ ppc_hash64_store_hpte0(env, hpte, pteh | HPTE64_V_HPTE_DIRTY);
args[0] = pte_index + i;
return H_SUCCESS;
@@ -152,7 +152,7 @@
}
*vp = v;
*rp = r;
- ppc_hash64_store_hpte0(env, hpte, 0);
+ ppc_hash64_store_hpte0(env, hpte, HPTE64_V_HPTE_DIRTY);
rb = compute_tlbie_rb(v, r, ptex);
ppc_tlb_invalidate_one(env, rb);
return REMOVE_SUCCESS;
@@ -282,11 +282,11 @@
r |= (flags << 48) & HPTE64_R_KEY_HI;
r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO);
rb = compute_tlbie_rb(v, r, pte_index);
- ppc_hash64_store_hpte0(env, hpte, v & ~HPTE64_V_VALID);
+ ppc_hash64_store_hpte0(env, hpte, (v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY);
ppc_tlb_invalidate_one(env, rb);
ppc_hash64_store_hpte1(env, hpte, r);
/* Don't need a memory barrier, due to qemu's global lock */
- ppc_hash64_store_hpte0(env, hpte, v);
+ ppc_hash64_store_hpte0(env, hpte, v | HPTE64_V_HPTE_DIRTY);
return H_SUCCESS;
}
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 89b33a5..3d4a1fc 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -36,17 +36,6 @@
SPAPR_TCE_RW = 3,
};
-struct sPAPRTCETable {
- uint32_t liobn;
- uint32_t window_size;
- sPAPRTCE *table;
- bool bypass;
- int fd;
- MemoryRegion iommu;
- QLIST_ENTRY(sPAPRTCETable) list;
-};
-
-
QLIST_HEAD(spapr_tce_tables, sPAPRTCETable) spapr_tce_tables;
static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
@@ -96,7 +85,7 @@
return (IOMMUTLBEntry) { .perm = IOMMU_NONE };
}
- tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT].tce;
+ tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT];
#ifdef DEBUG_TCE
fprintf(stderr, " -> *paddr=0x%llx, *len=0x%llx\n",
@@ -112,10 +101,68 @@
};
}
+static int spapr_tce_table_pre_load(void *opaque)
+{
+ sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque);
+
+ tcet->nb_table = tcet->window_size >> SPAPR_TCE_PAGE_SHIFT;
+
+ return 0;
+}
+
+static const VMStateDescription vmstate_spapr_tce_table = {
+ .name = "spapr_iommu",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .pre_load = spapr_tce_table_pre_load,
+ .fields = (VMStateField []) {
+ /* Sanity check */
+ VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable),
+ VMSTATE_UINT32_EQUAL(window_size, sPAPRTCETable),
+
+ /* IOMMU state */
+ VMSTATE_BOOL(bypass, sPAPRTCETable),
+ VMSTATE_VARRAY_UINT32(table, sPAPRTCETable, nb_table, 0, vmstate_info_uint64, uint64_t),
+
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static MemoryRegionIOMMUOps spapr_iommu_ops = {
.translate = spapr_tce_translate_iommu,
};
+static int spapr_tce_table_realize(DeviceState *dev)
+{
+ sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
+
+ if (kvm_enabled()) {
+ tcet->table = kvmppc_create_spapr_tce(tcet->liobn,
+ tcet->window_size,
+ &tcet->fd);
+ }
+
+ if (!tcet->table) {
+ size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
+ * sizeof(uint64_t);
+ tcet->table = g_malloc0(table_size);
+ }
+ tcet->nb_table = tcet->window_size >> SPAPR_TCE_PAGE_SHIFT;
+
+#ifdef DEBUG_TCE
+ fprintf(stderr, "spapr_iommu: New TCE table @ %p, liobn=0x%x, "
+ "table @ %p, fd=%d\n", tcet, liobn, tcet->table, tcet->fd);
+#endif
+
+ memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops,
+ "iommu-spapr", UINT64_MAX);
+
+ QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
+
+ return 0;
+}
+
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, size_t window_size)
{
sPAPRTCETable *tcet;
@@ -130,37 +177,21 @@
return NULL;
}
- tcet = g_malloc0(sizeof(*tcet));
+ tcet = SPAPR_TCE_TABLE(object_new(TYPE_SPAPR_TCE_TABLE));
tcet->liobn = liobn;
tcet->window_size = window_size;
- if (kvm_enabled()) {
- tcet->table = kvmppc_create_spapr_tce(liobn,
- window_size,
- &tcet->fd);
- }
+ object_property_add_child(OBJECT(owner), "tce-table", OBJECT(tcet), NULL);
- if (!tcet->table) {
- size_t table_size = (window_size >> SPAPR_TCE_PAGE_SHIFT)
- * sizeof(sPAPRTCE);
- tcet->table = g_malloc0(table_size);
- }
-
-#ifdef DEBUG_TCE
- fprintf(stderr, "spapr_iommu: New TCE table @ %p, liobn=0x%x, "
- "table @ %p, fd=%d\n", tcet, liobn, tcet->table, tcet->fd);
-#endif
-
- memory_region_init_iommu(&tcet->iommu, OBJECT(owner), &spapr_iommu_ops,
- "iommu-spapr", UINT64_MAX);
-
- QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
+ qdev_init_nofail(DEVICE(tcet));
return tcet;
}
-void spapr_tce_free(sPAPRTCETable *tcet)
+static void spapr_tce_table_finalize(Object *obj)
{
+ sPAPRTCETable *tcet = SPAPR_TCE_TABLE(obj);
+
QLIST_REMOVE(tcet, list);
if (!kvm_enabled() ||
@@ -168,8 +199,6 @@
tcet->window_size) != 0)) {
g_free(tcet->table);
}
-
- g_free(tcet);
}
MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet)
@@ -182,10 +211,11 @@
tcet->bypass = bypass;
}
-void spapr_tce_reset(sPAPRTCETable *tcet)
+static void spapr_tce_reset(DeviceState *dev)
{
+ sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
- * sizeof(sPAPRTCE);
+ * sizeof(uint64_t);
tcet->bypass = false;
memset(tcet->table, 0, table_size);
@@ -194,7 +224,6 @@
static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
target_ulong tce)
{
- sPAPRTCE *tcep;
IOMMUTLBEntry entry;
if (ioba >= tcet->window_size) {
@@ -203,8 +232,7 @@
return H_PARAMETER;
}
- tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT);
- tcep->tce = tce;
+ tcet->table[ioba >> SPAPR_TCE_PAGE_SHIFT] = tce;
entry.target_as = &address_space_memory,
entry.iova = ioba & ~SPAPR_TCE_PAGE_MASK;
@@ -238,14 +266,6 @@
return H_PARAMETER;
}
-void spapr_iommu_init(void)
-{
- QLIST_INIT(&spapr_tce_tables);
-
- /* hcall-tce */
- spapr_register_hypercall(H_PUT_TCE, h_put_tce);
-}
-
int spapr_dma_dt(void *fdt, int node_off, const char *propname,
uint32_t liobn, uint64_t window, uint32_t size)
{
@@ -286,3 +306,31 @@
return spapr_dma_dt(fdt, node_off, propname,
tcet->liobn, 0, tcet->window_size);
}
+
+static void spapr_tce_table_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->vmsd = &vmstate_spapr_tce_table;
+ dc->init = spapr_tce_table_realize;
+ dc->reset = spapr_tce_reset;
+
+ QLIST_INIT(&spapr_tce_tables);
+
+ /* hcall-tce */
+ spapr_register_hypercall(H_PUT_TCE, h_put_tce);
+}
+
+static TypeInfo spapr_tce_table_info = {
+ .name = TYPE_SPAPR_TCE_TABLE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(sPAPRTCETable),
+ .class_init = spapr_tce_table_class_init,
+ .instance_finalize = spapr_tce_table_finalize,
+};
+
+static void register_types(void)
+{
+ type_register_static(&spapr_tce_table_info);
+}
+
+type_init(register_types);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 318bc9d..1ca35a0 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -440,43 +440,6 @@
qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level);
}
-static uint64_t spapr_io_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- switch (size) {
- case 1:
- return cpu_inb(addr);
- case 2:
- return cpu_inw(addr);
- case 4:
- return cpu_inl(addr);
- }
- g_assert_not_reached();
-}
-
-static void spapr_io_write(void *opaque, hwaddr addr,
- uint64_t data, unsigned size)
-{
- switch (size) {
- case 1:
- cpu_outb(addr, data);
- return;
- case 2:
- cpu_outw(addr, data);
- return;
- case 4:
- cpu_outl(addr, data);
- return;
- }
- g_assert_not_reached();
-}
-
-static const MemoryRegionOps spapr_io_ops = {
- .endianness = DEVICE_LITTLE_ENDIAN,
- .read = spapr_io_read,
- .write = spapr_io_write
-};
-
/*
* MSI/MSIX memory region implementation.
* The handler handles both MSI and MSIX.
@@ -516,6 +479,7 @@
static int spapr_phb_init(SysBusDevice *s)
{
+ DeviceState *dev = DEVICE(s);
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
PCIHostState *phb = PCI_HOST_BRIDGE(s);
const char *busname;
@@ -605,8 +569,8 @@
memory_region_add_subregion(get_system_io(), 0, &sphb->iospace);
sprintf(namebuf, "%s.io-alias", sphb->dtbusname);
- memory_region_init_io(&sphb->iowindow, OBJECT(sphb), &spapr_io_ops, sphb,
- namebuf, SPAPR_PCI_IO_WIN_SIZE);
+ memory_region_init_alias(&sphb->iowindow, OBJECT(sphb), namebuf,
+ get_system_io(), 0, SPAPR_PCI_IO_WIN_SIZE);
memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
&sphb->iowindow);
@@ -633,14 +597,14 @@
* since it's unique by construction, and makes the guest visible
* BUID clear.
*/
- if (s->qdev.id) {
+ if (dev->id) {
busname = NULL;
} else if (sphb->index == 0) {
busname = "pci";
} else {
busname = sphb->dtbusname;
}
- bus = pci_register_bus(DEVICE(s), busname,
+ bus = pci_register_bus(dev, busname,
pci_spapr_set_irq, pci_spapr_map_irq, sphb,
&sphb->memspace, &sphb->iospace,
PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
@@ -648,7 +612,7 @@
sphb->dma_window_start = 0;
sphb->dma_window_size = 0x40000000;
- sphb->tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn,
+ sphb->tcet = spapr_tce_new_table(dev, sphb->dma_liobn,
sphb->dma_window_size);
if (!sphb->tcet) {
fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname);
@@ -682,7 +646,7 @@
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
/* Reset the IOMMU state */
- spapr_tce_reset(sphb->tcet);
+ device_reset(DEVICE(sphb->tcet));
}
static Property spapr_phb_properties[] = {
@@ -699,6 +663,54 @@
DEFINE_PROP_END_OF_LIST(),
};
+static const VMStateDescription vmstate_spapr_pci_lsi = {
+ .name = "spapr_pci/lsi",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32_EQUAL(irq, struct spapr_pci_lsi),
+
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static const VMStateDescription vmstate_spapr_pci_msi = {
+ .name = "spapr_pci/lsi",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(config_addr, struct spapr_pci_msi),
+ VMSTATE_UINT32(irq, struct spapr_pci_msi),
+ VMSTATE_UINT32(nvec, struct spapr_pci_msi),
+
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static const VMStateDescription vmstate_spapr_pci = {
+ .name = "spapr_pci",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT64_EQUAL(buid, sPAPRPHBState),
+ VMSTATE_UINT32_EQUAL(dma_liobn, sPAPRPHBState),
+ VMSTATE_UINT64_EQUAL(mem_win_addr, sPAPRPHBState),
+ VMSTATE_UINT64_EQUAL(mem_win_size, sPAPRPHBState),
+ VMSTATE_UINT64_EQUAL(io_win_addr, sPAPRPHBState),
+ VMSTATE_UINT64_EQUAL(io_win_size, sPAPRPHBState),
+ VMSTATE_UINT64_EQUAL(msi_win_addr, sPAPRPHBState),
+ VMSTATE_STRUCT_ARRAY(lsi_table, sPAPRPHBState, PCI_NUM_PINS, 0,
+ vmstate_spapr_pci_lsi, struct spapr_pci_lsi),
+ VMSTATE_STRUCT_ARRAY(msi_table, sPAPRPHBState, SPAPR_MSIX_MAX_DEVS, 0,
+ vmstate_spapr_pci_msi, struct spapr_pci_msi),
+
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static const char *spapr_phb_root_bus_path(PCIHostState *host_bridge,
PCIBus *rootbus)
{
@@ -717,6 +729,7 @@
sdc->init = spapr_phb_init;
dc->props = spapr_phb_properties;
dc->reset = spapr_phb_reset;
+ dc->vmsd = &vmstate_spapr_pci;
}
static const TypeInfo spapr_phb_info = {
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 7c6f6e4..a6a0a51 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -39,10 +39,10 @@
/* #define DEBUG_SPAPR */
#ifdef DEBUG_SPAPR
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
#else
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { } while (0)
#endif
@@ -201,7 +201,7 @@
dev->crq.qsize = queue_len;
dev->crq.qnext = 0;
- dprintf("CRQ for dev 0x" TARGET_FMT_lx " registered at 0x"
+ DPRINTF("CRQ for dev 0x" TARGET_FMT_lx " registered at 0x"
TARGET_FMT_lx "/0x" TARGET_FMT_lx "\n",
reg, queue_addr, queue_len);
return H_SUCCESS;
@@ -213,7 +213,7 @@
dev->crq.qsize = 0;
dev->crq.qnext = 0;
- dprintf("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
+ DPRINTF("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
return H_SUCCESS;
}
@@ -316,7 +316,7 @@
static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
{
if (dev->tcet) {
- spapr_tce_reset(dev->tcet);
+ device_reset(DEVICE(dev->tcet));
}
free_crq(dev);
}
@@ -542,6 +542,26 @@
.class_init = spapr_vio_bridge_class_init,
};
+const VMStateDescription vmstate_spapr_vio = {
+ .name = "spapr_vio",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ /* Sanity check */
+ VMSTATE_UINT32_EQUAL(reg, VIOsPAPRDevice),
+ VMSTATE_UINT32_EQUAL(irq, VIOsPAPRDevice),
+
+ /* General VIO device state */
+ VMSTATE_UINTTL(signal_state, VIOsPAPRDevice),
+ VMSTATE_UINT64(crq.qladdr, VIOsPAPRDevice),
+ VMSTATE_UINT32(crq.qsize, VIOsPAPRDevice),
+ VMSTATE_UINT32(crq.qnext, VIOsPAPRDevice),
+
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 0aeb003..d69adb2 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -154,17 +154,19 @@
env->psw.mask = IPL_PSW_MASK;
if (!ipl->kernel) {
- /* booting firmware, tell what device to boot from */
+ /* Tell firmware, if there is a preferred boot device */
+ env->regs[7] = -1;
DeviceState *dev_st = get_boot_device(0);
- VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
- OBJECT(&(dev_st->parent_obj)), "virtio-blk-ccw");
+ if (dev_st) {
+ VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
+ OBJECT(qdev_get_parent_bus(dev_st)->parent),
+ TYPE_VIRTIO_CCW_DEVICE);
- if (ccw_dev) {
- env->regs[7] = ccw_dev->sch->cssid << 24 |
- ccw_dev->sch->ssid << 16 |
- ccw_dev->sch->devno;
- } else {
- env->regs[7] = -1;
+ if (ccw_dev) {
+ env->regs[7] = ccw_dev->sch->cssid << 24 |
+ ccw_dev->sch->ssid << 16 |
+ ccw_dev->sch->devno;
+ }
}
}
diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 207eb82..f0aa941 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -38,10 +38,10 @@
/* #define DEBUG_S390 */
#ifdef DEBUG_S390
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
#else
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { } while (0)
#endif
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index edbde00..439d732 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -41,10 +41,10 @@
//#define DEBUG_S390
#ifdef DEBUG_S390
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
#else
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { } while (0)
#endif
diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c
index 2ac21d4..d7ec173 100644
--- a/hw/scsi/esp-pci.c
+++ b/hw/scsi/esp-pci.c
@@ -392,6 +392,7 @@
k->device_id = PCI_DEVICE_ID_AMD_SCSI;
k->revision = 0x10;
k->class_id = PCI_CLASS_STORAGE_SCSI;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->desc = "AMD Am53c974 PCscsi-PCI SCSI adapter";
dc->reset = esp_pci_hard_reset;
dc->vmsd = &vmstate_esp_pci_scsi;
@@ -512,6 +513,7 @@
k->init = dc390_scsi_init;
k->config_read = dc390_read_config;
k->config_write = dc390_write_config;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->desc = "Tekram DC-390 SCSI adapter";
}
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 94639b8..101e957 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -720,6 +720,7 @@
dc->realize = sysbus_esp_realize;
dc->reset = sysbus_esp_hard_reset;
dc->vmsd = &vmstate_sysbus_esp_scsi;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo sysbus_esp_info = {
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index 776e31a..611f2aa 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -2141,6 +2141,7 @@
k->subsystem_id = 0x1000;
dc->reset = lsi_scsi_reset;
dc->vmsd = &vmstate_lsi_scsi;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo lsi_info = {
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index eb52164..a6d5285 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2213,6 +2213,7 @@
dc->props = megasas_properties;
dc->reset = megasas_scsi_reset;
dc->vmsd = &vmstate_megasas;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->desc = "LSI MegaRAID SAS 1078";
}
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index b5a863a..fbf9173 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -1881,6 +1881,7 @@
static void scsi_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *k = DEVICE_CLASS(klass);
+ set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
k->bus_type = TYPE_SCSI_BUS;
k->init = scsi_qdev_init;
k->unplug = scsi_qdev_unplug;
diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c
index 55b44b9..e9090e5 100644
--- a/hw/scsi/spapr_vscsi.c
+++ b/hw/scsi/spapr_vscsi.c
@@ -45,10 +45,10 @@
/*#define DEBUG_VSCSI*/
#ifdef DEBUG_VSCSI
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
#else
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { } while (0)
#endif
@@ -75,20 +75,19 @@
/* SCSI request tracking */
SCSIRequest *sreq;
uint32_t qtag; /* qemu tag != srp tag */
- int lun;
- int active;
- long data_len;
- int writing;
- int senselen;
+ bool active;
+ uint32_t data_len;
+ bool writing;
+ uint32_t senselen;
uint8_t sense[SCSI_SENSE_BUF_SIZE];
/* RDMA related bits */
uint8_t dma_fmt;
- struct srp_direct_buf ext_desc;
- struct srp_direct_buf *cur_desc;
- struct srp_indirect_buf *ind_desc;
- int local_desc;
- int total_desc;
+ uint16_t local_desc;
+ uint16_t total_desc;
+ uint16_t cdb_offset;
+ uint16_t cur_desc_num;
+ uint16_t cur_desc_offset;
} vscsi_req;
#define TYPE_VIO_SPAPR_VSCSI_DEVICE "spapr-vscsi"
@@ -217,8 +216,9 @@
union viosrp_iu *iu = &req->iu;
uint64_t tag = iu->srp.rsp.tag;
int total_len = sizeof(iu->srp.rsp);
+ uint8_t sol_not = iu->srp.cmd.sol_not;
- dprintf("VSCSI: Sending resp status: 0x%x, "
+ DPRINTF("VSCSI: Sending resp status: 0x%x, "
"res_in: %d, res_out: %d\n", status, res_in, res_out);
memset(iu, 0, sizeof(struct srp_rsp));
@@ -249,7 +249,7 @@
/* Handle success vs. failure */
iu->srp.rsp.status = status;
if (status) {
- iu->srp.rsp.sol_not = (iu->srp.cmd.sol_not & 0x04) >> 2;
+ iu->srp.rsp.sol_not = (sol_not & 0x04) >> 2;
if (req->senselen) {
req->iu.srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
req->iu.srp.rsp.sense_data_len = cpu_to_be32(req->senselen);
@@ -257,114 +257,167 @@
total_len += req->senselen;
}
} else {
- iu->srp.rsp.sol_not = (iu->srp.cmd.sol_not & 0x02) >> 1;
+ iu->srp.rsp.sol_not = (sol_not & 0x02) >> 1;
}
vscsi_send_iu(s, req, total_len, VIOSRP_SRP_FORMAT);
return 0;
}
-static inline void vscsi_swap_desc(struct srp_direct_buf *desc)
+static inline struct srp_direct_buf vscsi_swap_desc(struct srp_direct_buf desc)
{
- desc->va = be64_to_cpu(desc->va);
- desc->len = be32_to_cpu(desc->len);
+ desc.va = be64_to_cpu(desc.va);
+ desc.len = be32_to_cpu(desc.len);
+ return desc;
+}
+
+static int vscsi_fetch_desc(VSCSIState *s, struct vscsi_req *req,
+ unsigned n, unsigned buf_offset,
+ struct srp_direct_buf *ret)
+{
+ struct srp_cmd *cmd = &req->iu.srp.cmd;
+
+ switch (req->dma_fmt) {
+ case SRP_NO_DATA_DESC: {
+ DPRINTF("VSCSI: no data descriptor\n");
+ return 0;
+ }
+ case SRP_DATA_DESC_DIRECT: {
+ memcpy(ret, cmd->add_data + req->cdb_offset, sizeof(*ret));
+ assert(req->cur_desc_num == 0);
+ DPRINTF("VSCSI: direct segment\n");
+ break;
+ }
+ case SRP_DATA_DESC_INDIRECT: {
+ struct srp_indirect_buf *tmp = (struct srp_indirect_buf *)
+ (cmd->add_data + req->cdb_offset);
+ if (n < req->local_desc) {
+ *ret = tmp->desc_list[n];
+ DPRINTF("VSCSI: indirect segment local tag=0x%x desc#%d/%d\n",
+ req->qtag, n, req->local_desc);
+
+ } else if (n < req->total_desc) {
+ int rc;
+ struct srp_direct_buf tbl_desc = vscsi_swap_desc(tmp->table_desc);
+ unsigned desc_offset = n * sizeof(struct srp_direct_buf);
+
+ if (desc_offset >= tbl_desc.len) {
+ DPRINTF("VSCSI: #%d is ouf of range (%d bytes)\n",
+ n, desc_offset);
+ return -1;
+ }
+ rc = spapr_vio_dma_read(&s->vdev, tbl_desc.va + desc_offset,
+ ret, sizeof(struct srp_direct_buf));
+ if (rc) {
+ DPRINTF("VSCSI: spapr_vio_dma_read -> %d reading ext_desc\n",
+ rc);
+ return -1;
+ }
+ DPRINTF("VSCSI: indirect segment ext. tag=0x%x desc#%d/%d { va=%"PRIx64" len=%x }\n",
+ req->qtag, n, req->total_desc, tbl_desc.va, tbl_desc.len);
+ } else {
+ DPRINTF("VSCSI: Out of descriptors !\n");
+ return 0;
+ }
+ break;
+ }
+ default:
+ fprintf(stderr, "VSCSI: Unknown format %x\n", req->dma_fmt);
+ return -1;
+ }
+
+ *ret = vscsi_swap_desc(*ret);
+ if (buf_offset > ret->len) {
+ DPRINTF(" offset=%x is out of a descriptor #%d boundary=%x\n",
+ buf_offset, req->cur_desc_num, ret->len);
+ return -1;
+ }
+ ret->va += buf_offset;
+ ret->len -= buf_offset;
+
+ DPRINTF(" cur=%d offs=%x ret { va=%"PRIx64" len=%x }\n",
+ req->cur_desc_num, req->cur_desc_offset, ret->va, ret->len);
+
+ return ret->len ? 1 : 0;
}
static int vscsi_srp_direct_data(VSCSIState *s, vscsi_req *req,
uint8_t *buf, uint32_t len)
{
- struct srp_direct_buf *md = req->cur_desc;
+ struct srp_direct_buf md;
uint32_t llen;
int rc = 0;
- dprintf("VSCSI: direct segment 0x%x bytes, va=0x%llx desc len=0x%x\n",
- len, (unsigned long long)md->va, md->len);
+ rc = vscsi_fetch_desc(s, req, req->cur_desc_num, req->cur_desc_offset, &md);
+ if (rc < 0) {
+ return -1;
+ } else if (rc == 0) {
+ return 0;
+ }
- llen = MIN(len, md->len);
+ llen = MIN(len, md.len);
if (llen) {
if (req->writing) { /* writing = to device = reading from memory */
- rc = spapr_vio_dma_read(&s->vdev, md->va, buf, llen);
+ rc = spapr_vio_dma_read(&s->vdev, md.va, buf, llen);
} else {
- rc = spapr_vio_dma_write(&s->vdev, md->va, buf, llen);
+ rc = spapr_vio_dma_write(&s->vdev, md.va, buf, llen);
}
}
- md->len -= llen;
- md->va += llen;
if (rc) {
return -1;
}
+ req->cur_desc_offset += llen;
+
return llen;
}
static int vscsi_srp_indirect_data(VSCSIState *s, vscsi_req *req,
uint8_t *buf, uint32_t len)
{
- struct srp_direct_buf *td = &req->ind_desc->table_desc;
- struct srp_direct_buf *md = req->cur_desc;
+ struct srp_direct_buf md;
int rc = 0;
uint32_t llen, total = 0;
- dprintf("VSCSI: indirect segment 0x%x bytes, td va=0x%llx len=0x%x\n",
- len, (unsigned long long)td->va, td->len);
+ DPRINTF("VSCSI: indirect segment 0x%x bytes\n", len);
/* While we have data ... */
while (len) {
- /* If we have a descriptor but it's empty, go fetch a new one */
- if (md && md->len == 0) {
- /* More local available, use one */
- if (req->local_desc) {
- md = ++req->cur_desc;
- --req->local_desc;
- --req->total_desc;
- td->va += sizeof(struct srp_direct_buf);
- } else {
- md = req->cur_desc = NULL;
- }
- }
- /* No descriptor at hand, fetch one */
- if (!md) {
- if (!req->total_desc) {
- dprintf("VSCSI: Out of descriptors !\n");
- break;
- }
- md = req->cur_desc = &req->ext_desc;
- dprintf("VSCSI: Reading desc from 0x%llx\n",
- (unsigned long long)td->va);
- rc = spapr_vio_dma_read(&s->vdev, td->va, md,
- sizeof(struct srp_direct_buf));
- if (rc) {
- dprintf("VSCSI: spapr_vio_dma_read -> %d reading ext_desc\n",
- rc);
- break;
- }
- vscsi_swap_desc(md);
- td->va += sizeof(struct srp_direct_buf);
- --req->total_desc;
- }
- dprintf("VSCSI: [desc va=0x%llx,len=0x%x] remaining=0x%x\n",
- (unsigned long long)md->va, md->len, len);
-
- /* Perform transfer */
- llen = MIN(len, md->len);
- if (req->writing) { /* writing = to device = reading from memory */
- rc = spapr_vio_dma_read(&s->vdev, md->va, buf, llen);
- } else {
- rc = spapr_vio_dma_write(&s->vdev, md->va, buf, llen);
- }
- if (rc) {
- dprintf("VSCSI: spapr_vio_dma_r/w(%d) -> %d\n", req->writing, rc);
+ rc = vscsi_fetch_desc(s, req, req->cur_desc_num, req->cur_desc_offset, &md);
+ if (rc < 0) {
+ return -1;
+ } else if (rc == 0) {
break;
}
- dprintf("VSCSI: data: %02x %02x %02x %02x...\n",
+
+ /* Perform transfer */
+ llen = MIN(len, md.len);
+ if (req->writing) { /* writing = to device = reading from memory */
+ rc = spapr_vio_dma_read(&s->vdev, md.va, buf, llen);
+ } else {
+ rc = spapr_vio_dma_write(&s->vdev, md.va, buf, llen);
+ }
+ if (rc) {
+ DPRINTF("VSCSI: spapr_vio_dma_r/w(%d) -> %d\n", req->writing, rc);
+ break;
+ }
+ DPRINTF("VSCSI: data: %02x %02x %02x %02x...\n",
buf[0], buf[1], buf[2], buf[3]);
len -= llen;
buf += llen;
+
total += llen;
- md->va += llen;
- md->len -= llen;
+
+ /* Update current position in the current descriptor */
+ req->cur_desc_offset += llen;
+ if (md.len == llen) {
+ /* Go to the next descriptor if the current one finished */
+ ++req->cur_desc_num;
+ req->cur_desc_offset = 0;
+ }
}
+
return rc ? -1 : total;
}
@@ -375,7 +428,7 @@
switch (req->dma_fmt) {
case SRP_NO_DATA_DESC:
- dprintf("VSCSI: no data desc transfer, skipping 0x%x bytes\n", len);
+ DPRINTF("VSCSI: no data desc transfer, skipping 0x%x bytes\n", len);
break;
case SRP_DATA_DESC_DIRECT:
err = vscsi_srp_direct_data(s, req, buf, len);
@@ -412,14 +465,13 @@
static int vscsi_preprocess_desc(vscsi_req *req)
{
struct srp_cmd *cmd = &req->iu.srp.cmd;
- int offset, i;
- offset = cmd->add_cdb_len & ~3;
+ req->cdb_offset = cmd->add_cdb_len & ~3;
if (req->writing) {
req->dma_fmt = cmd->buf_fmt >> 4;
} else {
- offset += data_out_desc_size(cmd);
+ req->cdb_offset += data_out_desc_size(cmd);
req->dma_fmt = cmd->buf_fmt & ((1U << 4) - 1);
}
@@ -427,31 +479,18 @@
case SRP_NO_DATA_DESC:
break;
case SRP_DATA_DESC_DIRECT:
- req->cur_desc = (struct srp_direct_buf *)(cmd->add_data + offset);
req->total_desc = req->local_desc = 1;
- vscsi_swap_desc(req->cur_desc);
- dprintf("VSCSI: using direct RDMA %s, 0x%x bytes MD: 0x%llx\n",
- req->writing ? "write" : "read",
- req->cur_desc->len, (unsigned long long)req->cur_desc->va);
break;
- case SRP_DATA_DESC_INDIRECT:
- req->ind_desc = (struct srp_indirect_buf *)(cmd->add_data + offset);
- vscsi_swap_desc(&req->ind_desc->table_desc);
- req->total_desc = req->ind_desc->table_desc.len /
- sizeof(struct srp_direct_buf);
+ case SRP_DATA_DESC_INDIRECT: {
+ struct srp_indirect_buf *ind_tmp = (struct srp_indirect_buf *)
+ (cmd->add_data + req->cdb_offset);
+
+ req->total_desc = be32_to_cpu(ind_tmp->table_desc.len) /
+ sizeof(struct srp_direct_buf);
req->local_desc = req->writing ? cmd->data_out_desc_cnt :
- cmd->data_in_desc_cnt;
- for (i = 0; i < req->local_desc; i++) {
- vscsi_swap_desc(&req->ind_desc->desc_list[i]);
- }
- req->cur_desc = req->local_desc ? &req->ind_desc->desc_list[0] : NULL;
- dprintf("VSCSI: using indirect RDMA %s, 0x%x bytes %d descs "
- "(%d local) VA: 0x%llx\n",
- req->writing ? "read" : "write",
- be32_to_cpu(req->ind_desc->len),
- req->total_desc, req->local_desc,
- (unsigned long long)req->ind_desc->table_desc.va);
+ cmd->data_in_desc_cnt;
break;
+ }
default:
fprintf(stderr,
"vscsi_preprocess_desc: Unknown format %x\n", req->dma_fmt);
@@ -469,7 +508,7 @@
uint8_t *buf;
int rc = 0;
- dprintf("VSCSI: SCSI xfer complete tag=0x%x len=0x%x, req=%p\n",
+ DPRINTF("VSCSI: SCSI xfer complete tag=0x%x len=0x%x, req=%p\n",
sreq->tag, len, req);
if (req == NULL) {
fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag);
@@ -499,8 +538,8 @@
vscsi_req *req = sreq->hba_private;
int32_t res_in = 0, res_out = 0;
- dprintf("VSCSI: SCSI cmd complete, r=0x%x tag=0x%x status=0x%x, req=%p\n",
- reason, sreq->tag, status, req);
+ DPRINTF("VSCSI: SCSI cmd complete, tag=0x%x status=0x%x, req=%p\n",
+ sreq->tag, status, req);
if (req == NULL) {
fprintf(stderr, "VSCSI: Can't find request for tag 0x%x\n", sreq->tag);
return;
@@ -509,16 +548,16 @@
if (status == CHECK_CONDITION) {
req->senselen = scsi_req_get_sense(req->sreq, req->sense,
sizeof(req->sense));
- dprintf("VSCSI: Sense data, %d bytes:\n", len);
- dprintf(" %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ DPRINTF("VSCSI: Sense data, %d bytes:\n", req->senselen);
+ DPRINTF(" %02x %02x %02x %02x %02x %02x %02x %02x\n",
req->sense[0], req->sense[1], req->sense[2], req->sense[3],
req->sense[4], req->sense[5], req->sense[6], req->sense[7]);
- dprintf(" %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ DPRINTF(" %02x %02x %02x %02x %02x %02x %02x %02x\n",
req->sense[8], req->sense[9], req->sense[10], req->sense[11],
req->sense[12], req->sense[13], req->sense[14], req->sense[15]);
}
- dprintf("VSCSI: Command complete err=%d\n", status);
+ DPRINTF("VSCSI: Command complete err=%d\n", status);
if (status == 0) {
/* We handle overflows, not underflows for normal commands,
* but hopefully nobody cares
@@ -540,13 +579,76 @@
vscsi_put_req(req);
}
+static const VMStateDescription vmstate_spapr_vscsi_req = {
+ .name = "spapr_vscsi_req",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_BUFFER(crq.raw, vscsi_req),
+ VMSTATE_BUFFER(iu.srp.reserved, vscsi_req),
+ VMSTATE_UINT32(qtag, vscsi_req),
+ VMSTATE_BOOL(active, vscsi_req),
+ VMSTATE_UINT32(data_len, vscsi_req),
+ VMSTATE_BOOL(writing, vscsi_req),
+ VMSTATE_UINT32(senselen, vscsi_req),
+ VMSTATE_BUFFER(sense, vscsi_req),
+ VMSTATE_UINT8(dma_fmt, vscsi_req),
+ VMSTATE_UINT16(local_desc, vscsi_req),
+ VMSTATE_UINT16(total_desc, vscsi_req),
+ VMSTATE_UINT16(cdb_offset, vscsi_req),
+ /*Restart SCSI request from the beginning for now */
+ /*VMSTATE_UINT16(cur_desc_num, vscsi_req),
+ VMSTATE_UINT16(cur_desc_offset, vscsi_req),*/
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void vscsi_save_request(QEMUFile *f, SCSIRequest *sreq)
+{
+ vscsi_req *req = sreq->hba_private;
+ assert(req->active);
+
+ vmstate_save_state(f, &vmstate_spapr_vscsi_req, req);
+
+ DPRINTF("VSCSI: saving tag=%u, current desc#%d, offset=%x\n",
+ req->qtag, req->cur_desc_num, req->cur_desc_offset);
+}
+
+static void *vscsi_load_request(QEMUFile *f, SCSIRequest *sreq)
+{
+ SCSIBus *bus = sreq->bus;
+ VSCSIState *s = VIO_SPAPR_VSCSI_DEVICE(bus->qbus.parent);
+ vscsi_req *req;
+ int rc;
+
+ assert(sreq->tag < VSCSI_REQ_LIMIT);
+ req = &s->reqs[sreq->tag];
+ assert(!req->active);
+
+ memset(req, 0, sizeof(*req));
+ rc = vmstate_load_state(f, &vmstate_spapr_vscsi_req, req, 1);
+ if (rc) {
+ fprintf(stderr, "VSCSI: failed loading request tag#%u\n", sreq->tag);
+ return NULL;
+ }
+ assert(req->active);
+
+ req->sreq = scsi_req_ref(sreq);
+
+ DPRINTF("VSCSI: restoring tag=%u, current desc#%d, offset=%x\n",
+ req->qtag, req->cur_desc_num, req->cur_desc_offset);
+
+ return req;
+}
+
static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
{
union viosrp_iu *iu = &req->iu;
struct srp_login_rsp *rsp = &iu->srp.login_rsp;
uint64_t tag = iu->srp.rsp.tag;
- dprintf("VSCSI: Got login, sendin response !\n");
+ DPRINTF("VSCSI: Got login, sendin response !\n");
/* TODO handle case that requested size is wrong and
* buffer format is wrong
@@ -612,7 +714,8 @@
sdev = vscsi_device_find(&s->bus, be64_to_cpu(srp->cmd.lun), &lun);
if (!sdev) {
- dprintf("VSCSI: Command for lun %08" PRIx64 " with no drive\n", be64_to_cpu(srp->cmd.lun));
+ DPRINTF("VSCSI: Command for lun %08" PRIx64 " with no drive\n",
+ be64_to_cpu(srp->cmd.lun));
if (srp->cmd.cdb[0] == INQUIRY) {
vscsi_inquiry_no_target(s, req);
} else {
@@ -621,12 +724,11 @@
} return 1;
}
- req->lun = lun;
req->sreq = scsi_req_new(sdev, req->qtag, lun, srp->cmd.cdb, req);
n = scsi_req_enqueue(req->sreq);
- dprintf("VSCSI: Queued command tag 0x%x CMD 0x%x ID %d LUN %d ret: %d\n",
- req->qtag, srp->cmd.cdb[0], id, lun, n);
+ DPRINTF("VSCSI: Queued command tag 0x%x CMD 0x%x LUN %d ret: %d\n",
+ req->qtag, srp->cmd.cdb[0], lun, n);
if (n) {
/* Transfer direction must be set before preprocessing the
@@ -838,7 +940,7 @@
crq.s.IU_length = be16_to_cpu(crq.s.IU_length);
crq.s.IU_data_ptr = be64_to_cpu(crq.s.IU_data_ptr);
- dprintf("VSCSI: do_crq %02x %02x ...\n", crq.raw[0], crq.raw[1]);
+ DPRINTF("VSCSI: do_crq %02x %02x ...\n", crq.raw[0], crq.raw[1]);
switch (crq.s.valid) {
case 0xc0: /* Init command/response */
@@ -895,7 +997,9 @@
.transfer_data = vscsi_transfer_data,
.complete = vscsi_command_complete,
- .cancel = vscsi_request_cancelled
+ .cancel = vscsi_request_cancelled,
+ .save_request = vscsi_save_request,
+ .load_request = vscsi_load_request,
};
static void spapr_vscsi_reset(VIOsPAPRDevice *dev)
@@ -959,6 +1063,20 @@
DEFINE_PROP_END_OF_LIST(),
};
+static const VMStateDescription vmstate_spapr_vscsi = {
+ .name = "spapr_vscsi",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_SPAPR_VIO(vdev, VSCSIState),
+ /* VSCSI state */
+ /* ???? */
+
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -973,6 +1091,7 @@
k->signal_mask = 0x00000001;
dc->props = spapr_vscsi_properties;
k->rtce_window_size = 0x10000000;
+ dc->vmsd = &vmstate_spapr_vscsi;
}
static const TypeInfo spapr_vscsi_info = {
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 785e93f..9e770fb 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -267,6 +267,7 @@
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->exit = vhost_scsi_exit;
dc->props = vhost_scsi_properties;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->init = vhost_scsi_init;
vdc->get_features = vhost_scsi_get_features;
vdc->set_config = vhost_scsi_set_config;
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 42cb73b..05da56b 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -669,8 +669,10 @@
static void virtio_scsi_common_class_init(ObjectClass *klass, void *data)
{
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
vdc->get_config = virtio_scsi_get_config;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static void virtio_scsi_class_init(ObjectClass *klass, void *data)
@@ -679,6 +681,7 @@
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->exit = virtio_scsi_device_exit;
dc->props = virtio_scsi_properties;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
vdc->init = virtio_scsi_device_init;
vdc->set_config = virtio_scsi_set_config;
vdc->get_features = virtio_scsi_get_features;
diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c
index e1074e1..d42b359 100644
--- a/hw/scsi/vmw_pvscsi.c
+++ b/hw/scsi/vmw_pvscsi.c
@@ -1197,6 +1197,7 @@
dc->reset = pvscsi_reset;
dc->vmsd = &vmstate_pvscsi;
dc->props = pvscsi_properties;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
k->config_write = pvscsi_write_config;
}
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index f69775c..42613b3 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -58,8 +58,13 @@
R_MAX
};
+#define TYPE_MILKYMIST_MEMCARD "milkymist-memcard"
+#define MILKYMIST_MEMCARD(obj) \
+ OBJECT_CHECK(MilkymistMemcardState, (obj), TYPE_MILKYMIST_MEMCARD)
+
struct MilkymistMemcardState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion regs_region;
SDState *card;
@@ -231,8 +236,7 @@
static void milkymist_memcard_reset(DeviceState *d)
{
- MilkymistMemcardState *s =
- container_of(d, MilkymistMemcardState, busdev.qdev);
+ MilkymistMemcardState *s = MILKYMIST_MEMCARD(d);
int i;
s->command_write_ptr = 0;
@@ -246,7 +250,7 @@
static int milkymist_memcard_init(SysBusDevice *dev)
{
- MilkymistMemcardState *s = FROM_SYSBUS(typeof(*s), dev);
+ MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev);
DriveInfo *dinfo;
dinfo = drive_get_next(IF_SD);
@@ -289,7 +293,7 @@
}
static const TypeInfo milkymist_memcard_info = {
- .name = "milkymist-memcard",
+ .name = TYPE_MILKYMIST_MEMCARD,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistMemcardState),
.class_init = milkymist_memcard_class_init,
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index f5eb1e4..03875bf 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -22,8 +22,12 @@
#define PL181_FIFO_LEN 16
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PL181 "pl181"
+#define PL181(obj) OBJECT_CHECK(PL181State, (obj), TYPE_PL181)
+
+typedef struct PL181State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
SDState *card;
uint32_t clock;
@@ -50,29 +54,29 @@
qemu_irq irq[2];
/* GPIO outputs for 'card is readonly' and 'card inserted' */
qemu_irq cardstatus[2];
-} pl181_state;
+} PL181State;
static const VMStateDescription vmstate_pl181 = {
.name = "pl181",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(clock, pl181_state),
- VMSTATE_UINT32(power, pl181_state),
- VMSTATE_UINT32(cmdarg, pl181_state),
- VMSTATE_UINT32(cmd, pl181_state),
- VMSTATE_UINT32(datatimer, pl181_state),
- VMSTATE_UINT32(datalength, pl181_state),
- VMSTATE_UINT32(respcmd, pl181_state),
- VMSTATE_UINT32_ARRAY(response, pl181_state, 4),
- VMSTATE_UINT32(datactrl, pl181_state),
- VMSTATE_UINT32(datacnt, pl181_state),
- VMSTATE_UINT32(status, pl181_state),
- VMSTATE_UINT32_ARRAY(mask, pl181_state, 2),
- VMSTATE_INT32(fifo_pos, pl181_state),
- VMSTATE_INT32(fifo_len, pl181_state),
- VMSTATE_INT32(linux_hack, pl181_state),
- VMSTATE_UINT32_ARRAY(fifo, pl181_state, PL181_FIFO_LEN),
+ VMSTATE_UINT32(clock, PL181State),
+ VMSTATE_UINT32(power, PL181State),
+ VMSTATE_UINT32(cmdarg, PL181State),
+ VMSTATE_UINT32(cmd, PL181State),
+ VMSTATE_UINT32(datatimer, PL181State),
+ VMSTATE_UINT32(datalength, PL181State),
+ VMSTATE_UINT32(respcmd, PL181State),
+ VMSTATE_UINT32_ARRAY(response, PL181State, 4),
+ VMSTATE_UINT32(datactrl, PL181State),
+ VMSTATE_UINT32(datacnt, PL181State),
+ VMSTATE_UINT32(status, PL181State),
+ VMSTATE_UINT32_ARRAY(mask, PL181State, 2),
+ VMSTATE_INT32(fifo_pos, PL181State),
+ VMSTATE_INT32(fifo_len, PL181State),
+ VMSTATE_INT32(linux_hack, PL181State),
+ VMSTATE_UINT32_ARRAY(fifo, PL181State, PL181_FIFO_LEN),
VMSTATE_END_OF_LIST()
}
};
@@ -125,7 +129,7 @@
static const unsigned char pl181_id[] =
{ 0x81, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
-static void pl181_update(pl181_state *s)
+static void pl181_update(PL181State *s)
{
int i;
for (i = 0; i < 2; i++) {
@@ -133,7 +137,7 @@
}
}
-static void pl181_fifo_push(pl181_state *s, uint32_t value)
+static void pl181_fifo_push(PL181State *s, uint32_t value)
{
int n;
@@ -147,7 +151,7 @@
DPRINTF("FIFO push %08x\n", (int)value);
}
-static uint32_t pl181_fifo_pop(pl181_state *s)
+static uint32_t pl181_fifo_pop(PL181State *s)
{
uint32_t value;
@@ -162,7 +166,7 @@
return value;
}
-static void pl181_send_command(pl181_state *s)
+static void pl181_send_command(PL181State *s)
{
SDRequest request;
uint8_t response[16];
@@ -207,7 +211,7 @@
the FIFO holding 32-bit words and the card taking data in single byte
chunks. FIFO bytes are transferred in little-endian order. */
-static void pl181_fifo_run(pl181_state *s)
+static void pl181_fifo_run(PL181State *s)
{
uint32_t bits;
uint32_t value = 0;
@@ -288,7 +292,7 @@
static uint64_t pl181_read(void *opaque, hwaddr offset,
unsigned size)
{
- pl181_state *s = (pl181_state *)opaque;
+ PL181State *s = (PL181State *)opaque;
uint32_t tmp;
if (offset >= 0xfe0 && offset < 0x1000) {
@@ -372,7 +376,7 @@
static void pl181_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
- pl181_state *s = (pl181_state *)opaque;
+ PL181State *s = (PL181State *)opaque;
switch (offset) {
case 0x00: /* Power */
@@ -449,7 +453,7 @@
static void pl181_reset(DeviceState *d)
{
- pl181_state *s = DO_UPCAST(pl181_state, busdev.qdev, d);
+ PL181State *s = PL181(d);
s->power = 0;
s->cmdarg = 0;
@@ -474,16 +478,17 @@
sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
}
-static int pl181_init(SysBusDevice *dev)
+static int pl181_init(SysBusDevice *sbd)
{
- pl181_state *s = FROM_SYSBUS(pl181_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ PL181State *s = PL181(dev);
DriveInfo *dinfo;
memory_region_init_io(&s->iomem, OBJECT(s), &pl181_ops, s, "pl181", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq[0]);
- sysbus_init_irq(dev, &s->irq[1]);
- qdev_init_gpio_out(&s->busdev.qdev, s->cardstatus, 2);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq[0]);
+ sysbus_init_irq(sbd, &s->irq[1]);
+ qdev_init_gpio_out(dev, s->cardstatus, 2);
dinfo = drive_get_next(IF_SD);
s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false);
return 0;
@@ -501,9 +506,9 @@
}
static const TypeInfo pl181_info = {
- .name = "pl181",
+ .name = TYPE_PL181,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl181_state),
+ .instance_size = sizeof(PL181State),
.class_init = pl181_class_init,
};
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index d2dbddc..1483e19 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -134,8 +134,8 @@
SDHCIState *s = (SDHCIState *)opaque;
if (s->norintsts & SDHC_NIS_REMOVE) {
- qemu_mod_timer(s->insert_timer,
- qemu_get_clock_ns(vm_clock) + SDHC_INSERTION_DELAY);
+ timer_mod(s->insert_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + SDHC_INSERTION_DELAY);
} else {
s->prnsts = 0x1ff0000;
if (s->norintstsen & SDHC_NISEN_INSERT) {
@@ -152,8 +152,8 @@
if ((s->norintsts & SDHC_NIS_REMOVE) && level) {
/* Give target some time to notice card ejection */
- qemu_mod_timer(s->insert_timer,
- qemu_get_clock_ns(vm_clock) + SDHC_INSERTION_DELAY);
+ timer_mod(s->insert_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + SDHC_INSERTION_DELAY);
} else {
if (level) {
s->prnsts = 0x1ff0000;
@@ -186,8 +186,8 @@
static void sdhci_reset(SDHCIState *s)
{
- qemu_del_timer(s->insert_timer);
- qemu_del_timer(s->transfer_timer);
+ timer_del(s->insert_timer);
+ timer_del(s->transfer_timer);
/* Set all registers to 0. Capabilities registers are not cleared
* and assumed to always preserve their value, given to them during
* initialization */
@@ -764,8 +764,8 @@
}
/* we have unfinished business - reschedule to continue ADMA */
- qemu_mod_timer(s->transfer_timer,
- qemu_get_clock_ns(vm_clock) + SDHC_TRANSFER_DELAY);
+ timer_mod(s->transfer_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + SDHC_TRANSFER_DELAY);
}
/* Perform data transfer according to controller configuration */
@@ -1170,18 +1170,18 @@
s->ro_cb = qemu_allocate_irqs(sdhci_card_readonly_cb, s, 1)[0];
sd_set_cb(s->card, s->ro_cb, s->eject_cb);
- s->insert_timer = qemu_new_timer_ns(vm_clock, sdhci_raise_insertion_irq, s);
- s->transfer_timer = qemu_new_timer_ns(vm_clock, sdhci_do_data_transfer, s);
+ s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s);
+ s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_do_data_transfer, s);
}
static void sdhci_uninitfn(Object *obj)
{
SDHCIState *s = SDHCI(obj);
- qemu_del_timer(s->insert_timer);
- qemu_free_timer(s->insert_timer);
- qemu_del_timer(s->transfer_timer);
- qemu_free_timer(s->transfer_timer);
+ timer_del(s->insert_timer);
+ timer_free(s->insert_timer);
+ timer_del(s->transfer_timer);
+ timer_free(s->transfer_timer);
qemu_free_irqs(&s->eject_cb);
qemu_free_irqs(&s->ro_cb);
diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c
index c33a72f..e81176a 100644
--- a/hw/sh4/sh_pci.c
+++ b/hw/sh4/sh_pci.c
@@ -28,9 +28,14 @@
#include "qemu/bswap.h"
#include "exec/address-spaces.h"
+#define TYPE_SH_PCI_HOST_BRIDGE "sh_pci"
+
+#define SH_PCI_HOST_BRIDGE(obj) \
+ OBJECT_CHECK(SHPCIState, (obj), TYPE_SH_PCI_HOST_BRIDGE)
+
typedef struct SHPCIState {
- SysBusDevice busdev;
- PCIBus *bus;
+ PCIHostState parent_obj;
+
PCIDevice *dev;
qemu_irq irq[4];
MemoryRegion memconfig_p4;
@@ -45,6 +50,8 @@
unsigned size)
{
SHPCIState *pcic = p;
+ PCIHostState *phb = PCI_HOST_BRIDGE(pcic);
+
switch(addr) {
case 0 ... 0xfc:
cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val);
@@ -64,7 +71,7 @@
}
break;
case 0x220:
- pci_data_write(pcic->bus, pcic->par, val, 4);
+ pci_data_write(phb->bus, pcic->par, val, 4);
break;
}
}
@@ -73,6 +80,8 @@
unsigned size)
{
SHPCIState *pcic = p;
+ PCIHostState *phb = PCI_HOST_BRIDGE(pcic);
+
switch(addr) {
case 0 ... 0xfc:
return le32_to_cpup((uint32_t*)(pcic->dev->config + addr));
@@ -83,7 +92,7 @@
case 0x1c8:
return pcic->iobr;
case 0x220:
- return pci_data_read(pcic->bus, pcic->par, 4);
+ return pci_data_read(phb->bus, pcic->par, 4);
}
return 0;
}
@@ -112,30 +121,33 @@
static int sh_pci_device_init(SysBusDevice *dev)
{
+ PCIHostState *phb;
SHPCIState *s;
int i;
- s = FROM_SYSBUS(SHPCIState, dev);
+ s = SH_PCI_HOST_BRIDGE(dev);
+ phb = PCI_HOST_BRIDGE(s);
for (i = 0; i < 4; i++) {
sysbus_init_irq(dev, &s->irq[i]);
}
- s->bus = pci_register_bus(&s->busdev.qdev, "pci",
- sh_pci_set_irq, sh_pci_map_irq,
- s->irq,
- get_system_memory(),
- get_system_io(),
- PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
+ phb->bus = pci_register_bus(DEVICE(dev), "pci",
+ sh_pci_set_irq, sh_pci_map_irq,
+ s->irq,
+ get_system_memory(),
+ get_system_io(),
+ PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
memory_region_init_io(&s->memconfig_p4, OBJECT(s), &sh_pci_reg_ops, s,
"sh_pci", 0x224);
memory_region_init_alias(&s->memconfig_a7, OBJECT(s), "sh_pci.2",
&s->memconfig_p4, 0, 0x224);
- isa_mmio_setup(&s->isa, 0x40000);
+ memory_region_init_alias(&s->isa, OBJECT(s), "sh_pci.isa",
+ get_system_io(), 0, 0x40000);
sysbus_init_mmio(dev, &s->memconfig_p4);
sysbus_init_mmio(dev, &s->memconfig_a7);
s->iobr = 0xfe240000;
memory_region_add_subregion(get_system_memory(), s->iobr, &s->isa);
- s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host");
+ s->dev = pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "sh_pci_host");
return 0;
}
@@ -171,8 +183,8 @@
}
static const TypeInfo sh_pci_device_info = {
- .name = "sh_pci",
- .parent = TYPE_SYS_BUS_DEVICE,
+ .name = TYPE_SH_PCI_HOST_BRIDGE,
+ .parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(SHPCIState),
.class_init = sh_pci_device_class_init,
};
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 7a0c1ab..36ef36f 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -66,6 +66,8 @@
#define PROM_FILENAME "openbios-sparc32"
#define CFG_ADDR 0xd00000510ULL
#define FW_CFG_SUN4M_DEPTH (FW_CFG_ARCH_LOCAL + 0x00)
+#define FW_CFG_SUN4M_WIDTH (FW_CFG_ARCH_LOCAL + 0x01)
+#define FW_CFG_SUN4M_HEIGHT (FW_CFG_ARCH_LOCAL + 0x02)
#define MAX_CPUS 16
#define MAX_PILS 16
@@ -557,6 +559,9 @@
}
/* NCR89C100/MACIO Internal ID register */
+
+#define TYPE_MACIO_ID_REGISTER "macio_idreg"
+
static const uint8_t idreg_data[] = { 0xfe, 0x81, 0x01, 0x03 };
static void idreg_init(hwaddr addr)
@@ -564,7 +569,7 @@
DeviceState *dev;
SysBusDevice *s;
- dev = qdev_create(NULL, "macio_idreg");
+ dev = qdev_create(NULL, TYPE_MACIO_ID_REGISTER);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
@@ -572,14 +577,18 @@
cpu_physical_memory_write_rom(addr, idreg_data, sizeof(idreg_data));
}
+#define MACIO_ID_REGISTER(obj) \
+ OBJECT_CHECK(IDRegState, (obj), TYPE_MACIO_ID_REGISTER)
+
typedef struct IDRegState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion mem;
} IDRegState;
static int idreg_init1(SysBusDevice *dev)
{
- IDRegState *s = FROM_SYSBUS(IDRegState, dev);
+ IDRegState *s = MACIO_ID_REGISTER(dev);
memory_region_init_ram(&s->mem, OBJECT(s),
"sun4m.idreg", sizeof(idreg_data));
@@ -597,14 +606,18 @@
}
static const TypeInfo idreg_info = {
- .name = "macio_idreg",
+ .name = TYPE_MACIO_ID_REGISTER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IDRegState),
.class_init = idreg_class_init,
};
+#define TYPE_TCX_AFX "tcx_afx"
+#define TCX_AFX(obj) OBJECT_CHECK(AFXState, (obj), TYPE_TCX_AFX)
+
typedef struct AFXState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion mem;
} AFXState;
@@ -614,7 +627,7 @@
DeviceState *dev;
SysBusDevice *s;
- dev = qdev_create(NULL, "tcx_afx");
+ dev = qdev_create(NULL, TYPE_TCX_AFX);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
@@ -623,7 +636,7 @@
static int afx_init1(SysBusDevice *dev)
{
- AFXState *s = FROM_SYSBUS(AFXState, dev);
+ AFXState *s = TCX_AFX(dev);
memory_region_init_ram(&s->mem, OBJECT(s), "sun4m.afx", 4);
vmstate_register_ram_global(&s->mem);
@@ -639,14 +652,18 @@
}
static const TypeInfo afx_info = {
- .name = "tcx_afx",
+ .name = TYPE_TCX_AFX,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(AFXState),
.class_init = afx_class_init,
};
+#define TYPE_OPENPROM "openprom"
+#define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM)
+
typedef struct PROMState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion prom;
} PROMState;
@@ -664,7 +681,7 @@
char *filename;
int ret;
- dev = qdev_create(NULL, "openprom");
+ dev = qdev_create(NULL, TYPE_OPENPROM);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
@@ -693,7 +710,7 @@
static int prom_init1(SysBusDevice *dev)
{
- PROMState *s = FROM_SYSBUS(PROMState, dev);
+ PROMState *s = OPENPROM(dev);
memory_region_init_ram(&s->prom, OBJECT(s), "sun4m.prom", PROM_SIZE_MAX);
vmstate_register_ram_global(&s->prom);
@@ -716,15 +733,18 @@
}
static const TypeInfo prom_info = {
- .name = "openprom",
+ .name = TYPE_OPENPROM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PROMState),
.class_init = prom_class_init,
};
-typedef struct RamDevice
-{
- SysBusDevice busdev;
+#define TYPE_SUN4M_MEMORY "memory"
+#define SUN4M_RAM(obj) OBJECT_CHECK(RamDevice, (obj), TYPE_SUN4M_MEMORY)
+
+typedef struct RamDevice {
+ SysBusDevice parent_obj;
+
MemoryRegion ram;
uint64_t size;
} RamDevice;
@@ -732,7 +752,7 @@
/* System RAM */
static int ram_init1(SysBusDevice *dev)
{
- RamDevice *d = FROM_SYSBUS(RamDevice, dev);
+ RamDevice *d = SUN4M_RAM(dev);
memory_region_init_ram(&d->ram, OBJECT(d), "sun4m.ram", d->size);
vmstate_register_ram_global(&d->ram);
@@ -758,7 +778,7 @@
dev = qdev_create(NULL, "memory");
s = SYS_BUS_DEVICE(dev);
- d = FROM_SYSBUS(RamDevice, s);
+ d = SUN4M_RAM(dev);
d->size = RAM_size;
qdev_init_nofail(dev);
@@ -780,7 +800,7 @@
}
static const TypeInfo ram_info = {
- .name = "memory",
+ .name = TYPE_SUN4M_MEMORY,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(RamDevice),
.class_init = ram_class_init,
@@ -816,12 +836,10 @@
{
}
-static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
- const char *boot_device,
- const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename, const char *cpu_model)
+static void sun4m_hw_init(const struct sun4m_hwdef *hwdef,
+ QEMUMachineInitArgs *args)
{
+ const char *cpu_model = args->cpu_model;
unsigned int i;
void *iommu, *espdma, *ledma, *nvram;
qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
@@ -847,10 +865,10 @@
/* set up devices */
- ram_init(0, RAM_size, hwdef->max_mem);
+ ram_init(0, args->ram_size, hwdef->max_mem);
/* models without ECC don't trap when missing ram is accessed */
if (!hwdef->ecc_base) {
- empty_slot_init(RAM_size, hwdef->max_mem - RAM_size);
+ empty_slot_init(args->ram_size, hwdef->max_mem - args->ram_size);
}
prom_init(hwdef->slavio_base, bios_name);
@@ -973,11 +991,12 @@
empty_slot_init(hwdef->bpp_base, 0x20);
}
- kernel_size = sun4m_load_kernel(kernel_filename, initrd_filename,
- RAM_size);
+ kernel_size = sun4m_load_kernel(args->kernel_filename,
+ args->initrd_filename,
+ args->ram_size);
- nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline,
- boot_device, RAM_size, kernel_size, graphic_width,
+ nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, args->kernel_cmdline,
+ args->boot_device, args->ram_size, kernel_size, graphic_width,
graphic_height, graphic_depth, hwdef->nvram_machine_id,
"Sun4m");
@@ -991,21 +1010,24 @@
fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth);
+ fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_WIDTH, graphic_width);
+ fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_HEIGHT, graphic_height);
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR);
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
- if (kernel_cmdline) {
+ if (args->kernel_cmdline) {
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR);
- pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, kernel_cmdline);
- fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+ pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE,
+ args->kernel_cmdline);
+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, args->kernel_cmdline);
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
- strlen(kernel_cmdline) + 1);
+ strlen(args->kernel_cmdline) + 1);
} else {
fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0);
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
}
fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR);
fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used
- fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_device[0]);
+ fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, args->boot_device[0]);
qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
}
@@ -1269,118 +1291,55 @@
/* SPARCstation 5 hardware initialisation */
static void ss5_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- sun4m_hw_init(&sun4m_hwdefs[0], RAM_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model);
+ sun4m_hw_init(&sun4m_hwdefs[0], args);
}
/* SPARCstation 10 hardware initialisation */
static void ss10_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- sun4m_hw_init(&sun4m_hwdefs[1], RAM_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model);
+ sun4m_hw_init(&sun4m_hwdefs[1], args);
}
/* SPARCserver 600MP hardware initialisation */
static void ss600mp_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- sun4m_hw_init(&sun4m_hwdefs[2], RAM_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model);
+ sun4m_hw_init(&sun4m_hwdefs[2], args);
}
/* SPARCstation 20 hardware initialisation */
static void ss20_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- sun4m_hw_init(&sun4m_hwdefs[3], RAM_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model);
+ sun4m_hw_init(&sun4m_hwdefs[3], args);
}
/* SPARCstation Voyager hardware initialisation */
static void vger_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- sun4m_hw_init(&sun4m_hwdefs[4], RAM_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model);
+ sun4m_hw_init(&sun4m_hwdefs[4], args);
}
/* SPARCstation LX hardware initialisation */
static void ss_lx_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- sun4m_hw_init(&sun4m_hwdefs[5], RAM_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model);
+ sun4m_hw_init(&sun4m_hwdefs[5], args);
}
/* SPARCstation 4 hardware initialisation */
static void ss4_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- sun4m_hw_init(&sun4m_hwdefs[6], RAM_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model);
+ sun4m_hw_init(&sun4m_hwdefs[6], args);
}
/* SPARCClassic hardware initialisation */
static void scls_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- sun4m_hw_init(&sun4m_hwdefs[7], RAM_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model);
+ sun4m_hw_init(&sun4m_hwdefs[7], args);
}
/* SPARCbook hardware initialisation */
static void sbook_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_device = args->boot_device;
- sun4m_hw_init(&sun4m_hwdefs[8], RAM_size, boot_device, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model);
+ sun4m_hw_init(&sun4m_hwdefs[8], args);
}
static QEMUMachine ss5_machine = {
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 564c195..9da0833 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -363,7 +363,7 @@
qemu_put_be64s(f, &s->disabled_mask);
qemu_put_sbe64s(f, &s->clock_offset);
- qemu_put_timer(f, s->qtimer);
+ timer_put(f, s->qtimer);
}
void cpu_get_timer(QEMUFile *f, CPUTimer *s)
@@ -373,7 +373,7 @@
qemu_get_be64s(f, &s->disabled_mask);
qemu_get_sbe64s(f, &s->clock_offset);
- qemu_get_timer(f, s->qtimer);
+ timer_get(f, s->qtimer);
}
static CPUTimer *cpu_timer_create(const char *name, SPARCCPU *cpu,
@@ -387,9 +387,9 @@
timer->disabled_mask = disabled_mask;
timer->disabled = 1;
- timer->clock_offset = qemu_get_clock_ns(vm_clock);
+ timer->clock_offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- timer->qtimer = qemu_new_timer_ns(vm_clock, cb, cpu);
+ timer->qtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cb, cpu);
return timer;
}
@@ -397,9 +397,9 @@
static void cpu_timer_reset(CPUTimer *timer)
{
timer->disabled = 1;
- timer->clock_offset = qemu_get_clock_ns(vm_clock);
+ timer->clock_offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- qemu_del_timer(timer->qtimer);
+ timer_del(timer->qtimer);
}
static void main_cpu_reset(void *opaque)
@@ -495,7 +495,7 @@
uint64_t real_count = count & ~timer->disabled_mask;
uint64_t disabled_bit = count & timer->disabled_mask;
- int64_t vm_clock_offset = qemu_get_clock_ns(vm_clock) -
+ int64_t vm_clock_offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
cpu_to_timer_ticks(real_count, timer->frequency);
TIMER_DPRINTF("%s set_count count=0x%016lx (%s) p=%p\n",
@@ -509,7 +509,7 @@
uint64_t cpu_tick_get_count(CPUTimer *timer)
{
uint64_t real_count = timer_to_cpu_ticks(
- qemu_get_clock_ns(vm_clock) - timer->clock_offset,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - timer->clock_offset,
timer->frequency);
TIMER_DPRINTF("%s get_count count=0x%016lx (%s) p=%p\n",
@@ -524,7 +524,7 @@
void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
{
- int64_t now = qemu_get_clock_ns(vm_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
uint64_t real_limit = limit & ~timer->disabled_mask;
timer->disabled = (limit & timer->disabled_mask) ? 1 : 0;
@@ -548,11 +548,11 @@
if (!real_limit) {
TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n",
timer->name);
- qemu_del_timer(timer->qtimer);
+ timer_del(timer->qtimer);
} else if (timer->disabled) {
- qemu_del_timer(timer->qtimer);
+ timer_del(timer->qtimer);
} else {
- qemu_mod_timer(timer->qtimer, expires);
+ timer_mod(timer->qtimer, expires);
}
}
@@ -605,9 +605,11 @@
pci_dev->config[0x09] = 0x00; // programming i/f
pci_dev->config[0x0D] = 0x0a; // latency_timer
- isa_mmio_setup(&s->bar0, 0x1000000);
+ memory_region_init_alias(&s->bar0, OBJECT(s), "bar0", get_system_io(),
+ 0, 0x1000000);
pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0);
- isa_mmio_setup(&s->bar1, 0x800000);
+ memory_region_init_alias(&s->bar1, OBJECT(s), "bar1", get_system_io(),
+ 0, 0x800000);
pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1);
return 0;
}
@@ -630,8 +632,12 @@
.class_init = ebus_class_init,
};
+#define TYPE_OPENPROM "openprom"
+#define OPENPROM(obj) OBJECT_CHECK(PROMState, (obj), TYPE_OPENPROM)
+
typedef struct PROMState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion prom;
} PROMState;
@@ -649,7 +655,7 @@
char *filename;
int ret;
- dev = qdev_create(NULL, "openprom");
+ dev = qdev_create(NULL, TYPE_OPENPROM);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
@@ -678,7 +684,7 @@
static int prom_init1(SysBusDevice *dev)
{
- PROMState *s = FROM_SYSBUS(PROMState, dev);
+ PROMState *s = OPENPROM(dev);
memory_region_init_ram(&s->prom, OBJECT(s), "sun4u.prom", PROM_SIZE_MAX);
vmstate_register_ram_global(&s->prom);
@@ -701,16 +707,19 @@
}
static const TypeInfo prom_info = {
- .name = "openprom",
+ .name = TYPE_OPENPROM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PROMState),
.class_init = prom_class_init,
};
-typedef struct RamDevice
-{
- SysBusDevice busdev;
+#define TYPE_SUN4U_MEMORY "memory"
+#define SUN4U_RAM(obj) OBJECT_CHECK(RamDevice, (obj), TYPE_SUN4U_MEMORY)
+
+typedef struct RamDevice {
+ SysBusDevice parent_obj;
+
MemoryRegion ram;
uint64_t size;
} RamDevice;
@@ -718,7 +727,7 @@
/* System RAM */
static int ram_init1(SysBusDevice *dev)
{
- RamDevice *d = FROM_SYSBUS(RamDevice, dev);
+ RamDevice *d = SUN4U_RAM(dev);
memory_region_init_ram(&d->ram, OBJECT(d), "sun4u.ram", d->size);
vmstate_register_ram_global(&d->ram);
@@ -733,10 +742,10 @@
RamDevice *d;
/* allocate RAM */
- dev = qdev_create(NULL, "memory");
+ dev = qdev_create(NULL, TYPE_SUN4U_MEMORY);
s = SYS_BUS_DEVICE(dev);
- d = FROM_SYSBUS(RamDevice, s);
+ d = SUN4U_RAM(dev);
d->size = RAM_size;
qdev_init_nofail(dev);
@@ -758,7 +767,7 @@
}
static const TypeInfo ram_info = {
- .name = "memory",
+ .name = TYPE_SUN4U_MEMORY,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(RamDevice),
.class_init = ram_class_init,
@@ -802,10 +811,7 @@
}
static void sun4uv_init(MemoryRegion *address_space_mem,
- ram_addr_t RAM_size,
- const char *boot_devices,
- const char *kernel_filename, const char *kernel_cmdline,
- const char *initrd_filename, const char *cpu_model,
+ QEMUMachineInitArgs *args,
const struct hwdef *hwdef)
{
SPARCCPU *cpu;
@@ -820,10 +826,10 @@
FWCfgState *fw_cfg;
/* init CPUs */
- cpu = cpu_devinit(cpu_model, hwdef);
+ cpu = cpu_devinit(args->cpu_model, hwdef);
/* set up devices */
- ram_init(0, RAM_size);
+ ram_init(0, args->ram_size);
prom_init(hwdef->prom_addr, bios_name);
@@ -869,13 +875,15 @@
initrd_size = 0;
initrd_addr = 0;
- kernel_size = sun4u_load_kernel(kernel_filename, initrd_filename,
+ kernel_size = sun4u_load_kernel(args->kernel_filename,
+ args->initrd_filename,
ram_size, &initrd_size, &initrd_addr,
&kernel_addr, &kernel_entry);
- sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
+ sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", args->ram_size,
+ args->boot_device,
kernel_addr, kernel_size,
- kernel_cmdline,
+ args->kernel_cmdline,
initrd_addr, initrd_size,
/* XXX: need an option to load a NVRAM image */
0,
@@ -889,16 +897,16 @@
fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id);
fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry);
fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
- if (kernel_cmdline) {
+ if (args->kernel_cmdline) {
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
- strlen(kernel_cmdline) + 1);
- fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
+ strlen(args->kernel_cmdline) + 1);
+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, args->kernel_cmdline);
} else {
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0);
}
fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
fw_cfg_add_i64(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
- fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, boot_devices[0]);
+ fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, args->boot_device[0]);
fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_WIDTH, graphic_width);
fw_cfg_add_i16(fw_cfg, FW_CFG_SPARC64_HEIGHT, graphic_height);
@@ -940,40 +948,19 @@
/* Sun4u hardware initialisation */
static void sun4u_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_devices = args->boot_device;
- sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model, &hwdefs[0]);
+ sun4uv_init(get_system_memory(), args, &hwdefs[0]);
}
/* Sun4v hardware initialisation */
static void sun4v_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_devices = args->boot_device;
- sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]);
+ sun4uv_init(get_system_memory(), args, &hwdefs[1]);
}
/* Niagara hardware initialisation */
static void niagara_init(QEMUMachineInitArgs *args)
{
- ram_addr_t RAM_size = args->ram_size;
- const char *cpu_model = args->cpu_model;
- const char *kernel_filename = args->kernel_filename;
- const char *kernel_cmdline = args->kernel_cmdline;
- const char *initrd_filename = args->initrd_filename;
- const char *boot_devices = args->boot_device;
- sun4uv_init(get_system_memory(), RAM_size, boot_devices, kernel_filename,
- kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]);
+ sun4uv_init(get_system_memory(), args, &hwdefs[2]);
}
static QEMUMachine sun4u_machine = {
diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c
index 711a0c1..fd479ef 100644
--- a/hw/ssi/pl022.c
+++ b/hw/ssi/pl022.c
@@ -39,8 +39,12 @@
#define PL022_INT_RX 0x04
#define PL022_INT_TX 0x08
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PL022 "pl022"
+#define PL022(obj) OBJECT_CHECK(PL022State, (obj), TYPE_PL022)
+
+typedef struct PL022State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t cr0;
uint32_t cr1;
@@ -58,12 +62,12 @@
uint16_t rx_fifo[8];
qemu_irq irq;
SSIBus *ssi;
-} pl022_state;
+} PL022State;
static const unsigned char pl022_id[8] =
{ 0x22, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
-static void pl022_update(pl022_state *s)
+static void pl022_update(PL022State *s)
{
s->sr = 0;
if (s->tx_fifo_len == 0)
@@ -85,7 +89,7 @@
qemu_set_irq(s->irq, (s->is & s->im) != 0);
}
-static void pl022_xfer(pl022_state *s)
+static void pl022_xfer(PL022State *s)
{
int i;
int o;
@@ -133,7 +137,7 @@
static uint64_t pl022_read(void *opaque, hwaddr offset,
unsigned size)
{
- pl022_state *s = (pl022_state *)opaque;
+ PL022State *s = (PL022State *)opaque;
int val;
if (offset >= 0xfe0 && offset < 0x1000) {
@@ -177,7 +181,7 @@
static void pl022_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
- pl022_state *s = (pl022_state *)opaque;
+ PL022State *s = (PL022State *)opaque;
switch (offset) {
case 0x00: /* CR0 */
@@ -221,7 +225,7 @@
}
}
-static void pl022_reset(pl022_state *s)
+static void pl022_reset(PL022State *s)
{
s->rx_fifo_len = 0;
s->tx_fifo_len = 0;
@@ -242,47 +246,48 @@
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(cr0, pl022_state),
- VMSTATE_UINT32(cr1, pl022_state),
- VMSTATE_UINT32(bitmask, pl022_state),
- VMSTATE_UINT32(sr, pl022_state),
- VMSTATE_UINT32(cpsr, pl022_state),
- VMSTATE_UINT32(is, pl022_state),
- VMSTATE_UINT32(im, pl022_state),
- VMSTATE_INT32(tx_fifo_head, pl022_state),
- VMSTATE_INT32(rx_fifo_head, pl022_state),
- VMSTATE_INT32(tx_fifo_len, pl022_state),
- VMSTATE_INT32(rx_fifo_len, pl022_state),
- VMSTATE_UINT16(tx_fifo[0], pl022_state),
- VMSTATE_UINT16(rx_fifo[0], pl022_state),
- VMSTATE_UINT16(tx_fifo[1], pl022_state),
- VMSTATE_UINT16(rx_fifo[1], pl022_state),
- VMSTATE_UINT16(tx_fifo[2], pl022_state),
- VMSTATE_UINT16(rx_fifo[2], pl022_state),
- VMSTATE_UINT16(tx_fifo[3], pl022_state),
- VMSTATE_UINT16(rx_fifo[3], pl022_state),
- VMSTATE_UINT16(tx_fifo[4], pl022_state),
- VMSTATE_UINT16(rx_fifo[4], pl022_state),
- VMSTATE_UINT16(tx_fifo[5], pl022_state),
- VMSTATE_UINT16(rx_fifo[5], pl022_state),
- VMSTATE_UINT16(tx_fifo[6], pl022_state),
- VMSTATE_UINT16(rx_fifo[6], pl022_state),
- VMSTATE_UINT16(tx_fifo[7], pl022_state),
- VMSTATE_UINT16(rx_fifo[7], pl022_state),
+ VMSTATE_UINT32(cr0, PL022State),
+ VMSTATE_UINT32(cr1, PL022State),
+ VMSTATE_UINT32(bitmask, PL022State),
+ VMSTATE_UINT32(sr, PL022State),
+ VMSTATE_UINT32(cpsr, PL022State),
+ VMSTATE_UINT32(is, PL022State),
+ VMSTATE_UINT32(im, PL022State),
+ VMSTATE_INT32(tx_fifo_head, PL022State),
+ VMSTATE_INT32(rx_fifo_head, PL022State),
+ VMSTATE_INT32(tx_fifo_len, PL022State),
+ VMSTATE_INT32(rx_fifo_len, PL022State),
+ VMSTATE_UINT16(tx_fifo[0], PL022State),
+ VMSTATE_UINT16(rx_fifo[0], PL022State),
+ VMSTATE_UINT16(tx_fifo[1], PL022State),
+ VMSTATE_UINT16(rx_fifo[1], PL022State),
+ VMSTATE_UINT16(tx_fifo[2], PL022State),
+ VMSTATE_UINT16(rx_fifo[2], PL022State),
+ VMSTATE_UINT16(tx_fifo[3], PL022State),
+ VMSTATE_UINT16(rx_fifo[3], PL022State),
+ VMSTATE_UINT16(tx_fifo[4], PL022State),
+ VMSTATE_UINT16(rx_fifo[4], PL022State),
+ VMSTATE_UINT16(tx_fifo[5], PL022State),
+ VMSTATE_UINT16(rx_fifo[5], PL022State),
+ VMSTATE_UINT16(tx_fifo[6], PL022State),
+ VMSTATE_UINT16(rx_fifo[6], PL022State),
+ VMSTATE_UINT16(tx_fifo[7], PL022State),
+ VMSTATE_UINT16(rx_fifo[7], PL022State),
VMSTATE_END_OF_LIST()
}
};
-static int pl022_init(SysBusDevice *dev)
+static int pl022_init(SysBusDevice *sbd)
{
- pl022_state *s = FROM_SYSBUS(pl022_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ PL022State *s = PL022(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &pl022_ops, s, "pl022", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
- s->ssi = ssi_create_bus(&dev->qdev, "ssi");
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+ s->ssi = ssi_create_bus(dev, "ssi");
pl022_reset(s);
- vmstate_register(&dev->qdev, -1, &vmstate_pl022, s);
+ vmstate_register(dev, -1, &vmstate_pl022, s);
return 0;
}
@@ -294,9 +299,9 @@
}
static const TypeInfo pl022_info = {
- .name = "pl022",
+ .name = TYPE_PL022,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl022_state),
+ .instance_size = sizeof(PL022State),
.class_init = pl022_class_init,
};
diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c
index 7a9fd81..d44caae 100644
--- a/hw/ssi/xilinx_spi.c
+++ b/hw/ssi/xilinx_spi.c
@@ -73,8 +73,12 @@
#define FIFO_CAPACITY 256
+#define TYPE_XILINX_SPI "xlnx.xps-spi"
+#define XILINX_SPI(obj) OBJECT_CHECK(XilinxSPI, (obj), TYPE_XILINX_SPI)
+
typedef struct XilinxSPI {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion mmio;
qemu_irq irq;
@@ -109,7 +113,7 @@
static void xlx_spi_update_cs(XilinxSPI *s)
{
- int i;
+ int i;
for (i = 0; i < s->num_cs; ++i) {
qemu_set_irq(s->cs_lines[i], !(~s->regs[R_SPISSR] & 1 << i));
@@ -154,7 +158,7 @@
static void xlx_spi_reset(DeviceState *d)
{
- xlx_spi_do_reset(DO_UPCAST(XilinxSPI, busdev.qdev, d));
+ xlx_spi_do_reset(XILINX_SPI(d));
}
static inline int spi_master_enabled(XilinxSPI *s)
@@ -314,25 +318,26 @@
}
};
-static int xilinx_spi_init(SysBusDevice *dev)
+static int xilinx_spi_init(SysBusDevice *sbd)
{
+ DeviceState *dev = DEVICE(sbd);
+ XilinxSPI *s = XILINX_SPI(dev);
int i;
- XilinxSPI *s = FROM_SYSBUS(typeof(*s), dev);
DB_PRINT("\n");
- s->spi = ssi_create_bus(&dev->qdev, "spi");
+ s->spi = ssi_create_bus(dev, "spi");
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
s->cs_lines = g_new(qemu_irq, s->num_cs);
- ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi);
+ ssi_auto_connect_slaves(dev, s->cs_lines, s->spi);
for (i = 0; i < s->num_cs; ++i) {
- sysbus_init_irq(dev, &s->cs_lines[i]);
+ sysbus_init_irq(sbd, &s->cs_lines[i]);
}
memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s,
"xilinx-spi", R_MAX * 4);
- sysbus_init_mmio(dev, &s->mmio);
+ sysbus_init_mmio(sbd, &s->mmio);
s->irqline = -1;
@@ -372,7 +377,7 @@
}
static const TypeInfo xilinx_spi_info = {
- .name = "xlnx.xps-spi",
+ .name = TYPE_XILINX_SPI,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(XilinxSPI),
.class_init = xilinx_spi_class_init,
diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index 0ceb240..8020c9f 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -41,8 +41,15 @@
MemoryRegion iomem;
} TimerBlock;
+#define TYPE_ARM_MPTIMER "arm_mptimer"
+#define ARM_MPTIMER(obj) \
+ OBJECT_CHECK(ARMMPTimerState, (obj), TYPE_ARM_MPTIMER)
+
typedef struct {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
uint32_t num_cpu;
TimerBlock timerblock[MAX_CPUS];
MemoryRegion iomem;
@@ -74,10 +81,10 @@
return;
}
if (restart) {
- tb->tick = qemu_get_clock_ns(vm_clock);
+ tb->tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
tb->tick += (int64_t)tb->count * timerblock_scale(tb);
- qemu_mod_timer(tb->timer, tb->tick);
+ timer_mod(tb->timer, tb->tick);
}
static void timerblock_tick(void *opaque)
@@ -106,7 +113,7 @@
return 0;
}
/* Slow and ugly, but hopefully won't happen too often. */
- val = tb->tick - qemu_get_clock_ns(vm_clock);
+ val = tb->tick - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
val /= timerblock_scale(tb);
if (val < 0) {
val = 0;
@@ -133,7 +140,7 @@
case 4: /* Counter. */
if ((tb->control & 1) && tb->count) {
/* Cancel the previous timer. */
- qemu_del_timer(tb->timer);
+ timer_del(tb->timer);
}
tb->count = value;
if (tb->control & 1) {
@@ -204,15 +211,15 @@
tb->status = 0;
tb->tick = 0;
if (tb->timer) {
- qemu_del_timer(tb->timer);
+ timer_del(tb->timer);
}
}
static void arm_mptimer_reset(DeviceState *dev)
{
- ARMMPTimerState *s =
- FROM_SYSBUS(ARMMPTimerState, SYS_BUS_DEVICE(dev));
+ ARMMPTimerState *s = ARM_MPTIMER(dev);
int i;
+
for (i = 0; i < ARRAY_SIZE(s->timerblock); i++) {
timerblock_reset(&s->timerblock[i]);
}
@@ -220,8 +227,9 @@
static int arm_mptimer_init(SysBusDevice *dev)
{
- ARMMPTimerState *s = FROM_SYSBUS(ARMMPTimerState, dev);
+ ARMMPTimerState *s = ARM_MPTIMER(dev);
int i;
+
if (s->num_cpu < 1 || s->num_cpu > MAX_CPUS) {
hw_error("%s: num-cpu must be between 1 and %d\n", __func__, MAX_CPUS);
}
@@ -240,7 +248,7 @@
sysbus_init_mmio(dev, &s->iomem);
for (i = 0; i < s->num_cpu; i++) {
TimerBlock *tb = &s->timerblock[i];
- tb->timer = qemu_new_timer_ns(vm_clock, timerblock_tick, tb);
+ tb->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, timerblock_tick, tb);
sysbus_init_irq(dev, &tb->irq);
memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
"arm_mptimer_timerblock", 0x20);
@@ -294,7 +302,7 @@
}
static const TypeInfo arm_mptimer_info = {
- .name = "arm_mptimer",
+ .name = TYPE_ARM_MPTIMER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(ARMMPTimerState),
.class_init = arm_mptimer_class_init,
diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index 798a8da..a47afde 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -12,6 +12,7 @@
#include "qemu-common.h"
#include "hw/qdev.h"
#include "hw/ptimer.h"
+#include "qemu/main-loop.h"
/* Common timer implementation. */
@@ -179,14 +180,18 @@
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html
*/
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_SP804 "sp804"
+#define SP804(obj) OBJECT_CHECK(SP804State, (obj), TYPE_SP804)
+
+typedef struct SP804State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
arm_timer_state *timer[2];
uint32_t freq0, freq1;
int level[2];
qemu_irq irq;
-} sp804_state;
+} SP804State;
static const uint8_t sp804_ids[] = {
/* Timer ID */
@@ -198,7 +203,7 @@
/* Merge the IRQs from the two component devices. */
static void sp804_set_irq(void *opaque, int irq, int level)
{
- sp804_state *s = (sp804_state *)opaque;
+ SP804State *s = (SP804State *)opaque;
s->level[irq] = level;
qemu_set_irq(s->irq, s->level[0] || s->level[1]);
@@ -207,7 +212,7 @@
static uint64_t sp804_read(void *opaque, hwaddr offset,
unsigned size)
{
- sp804_state *s = (sp804_state *)opaque;
+ SP804State *s = (SP804State *)opaque;
if (offset < 0x20) {
return arm_timer_read(s->timer[0], offset);
@@ -239,7 +244,7 @@
static void sp804_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
- sp804_state *s = (sp804_state *)opaque;
+ SP804State *s = (SP804State *)opaque;
if (offset < 0x20) {
arm_timer_write(s->timer[0], offset, value);
@@ -268,33 +273,39 @@
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
- VMSTATE_INT32_ARRAY(level, sp804_state, 2),
+ VMSTATE_INT32_ARRAY(level, SP804State, 2),
VMSTATE_END_OF_LIST()
}
};
-static int sp804_init(SysBusDevice *dev)
+static int sp804_init(SysBusDevice *sbd)
{
- sp804_state *s = FROM_SYSBUS(sp804_state, dev);
+ DeviceState *dev = DEVICE(sbd);
+ SP804State *s = SP804(dev);
qemu_irq *qi;
qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
- sysbus_init_irq(dev, &s->irq);
+ sysbus_init_irq(sbd, &s->irq);
s->timer[0] = arm_timer_init(s->freq0);
s->timer[1] = arm_timer_init(s->freq1);
s->timer[0]->irq = qi[0];
s->timer[1]->irq = qi[1];
memory_region_init_io(&s->iomem, OBJECT(s), &sp804_ops, s,
"sp804", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
+ sysbus_init_mmio(sbd, &s->iomem);
+ vmstate_register(dev, -1, &vmstate_sp804, s);
return 0;
}
/* Integrator/CP timer module. */
+#define TYPE_INTEGRATOR_PIT "integrator_pit"
+#define INTEGRATOR_PIT(obj) \
+ OBJECT_CHECK(icp_pit_state, (obj), TYPE_INTEGRATOR_PIT)
+
typedef struct {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
arm_timer_state *timer[3];
} icp_pit_state;
@@ -336,7 +347,7 @@
static int icp_pit_init(SysBusDevice *dev)
{
- icp_pit_state *s = FROM_SYSBUS(icp_pit_state, dev);
+ icp_pit_state *s = INTEGRATOR_PIT(dev);
/* Timer 0 runs at the system clock speed (40MHz). */
s->timer[0] = arm_timer_init(40000000);
@@ -364,15 +375,15 @@
}
static const TypeInfo icp_pit_info = {
- .name = "integrator_pit",
+ .name = TYPE_INTEGRATOR_PIT,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(icp_pit_state),
.class_init = icp_pit_class_init,
};
static Property sp804_properties[] = {
- DEFINE_PROP_UINT32("freq0", sp804_state, freq0, 1000000),
- DEFINE_PROP_UINT32("freq1", sp804_state, freq1, 1000000),
+ DEFINE_PROP_UINT32("freq0", SP804State, freq0, 1000000),
+ DEFINE_PROP_UINT32("freq1", SP804State, freq1, 1000000),
DEFINE_PROP_END_OF_LIST(),
};
@@ -386,9 +397,9 @@
}
static const TypeInfo sp804_info = {
- .name = "sp804",
+ .name = TYPE_SP804,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(sp804_state),
+ .instance_size = sizeof(SP804State),
.class_init = sp804_class_init,
};
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
index a861049..a279bce 100644
--- a/hw/timer/cadence_ttc.c
+++ b/hw/timer/cadence_ttc.c
@@ -64,8 +64,13 @@
qemu_irq irq;
} CadenceTimerState;
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_CADENCE_TTC "cadence_ttc"
+#define CADENCE_TTC(obj) \
+ OBJECT_CHECK(CadenceTTCState, (obj), TYPE_CADENCE_TTC)
+
+typedef struct CadenceTTCState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
CadenceTimerState timer[3];
} CadenceTTCState;
@@ -167,7 +172,7 @@
event_interval = next_value - (int64_t)s->reg_value;
event_interval = (event_interval < 0) ? -event_interval : event_interval;
- qemu_mod_timer(s->timer, s->cpu_time +
+ timer_mod(s->timer, s->cpu_time +
cadence_timer_get_ns(s, event_interval));
}
@@ -179,7 +184,7 @@
(int64_t)s->reg_interval + 1 : 0x10000ULL) << 16;
uint64_t old_time = s->cpu_time;
- s->cpu_time = qemu_get_clock_ns(vm_clock);
+ s->cpu_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
DB_PRINT("cpu time: %lld ns\n", (long long)old_time);
if (!s->cpu_time_valid || old_time == s->cpu_time) {
@@ -396,12 +401,12 @@
cadence_timer_reset(s);
- s->timer = qemu_new_timer_ns(vm_clock, cadence_timer_tick, s);
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cadence_timer_tick, s);
}
static int cadence_ttc_init(SysBusDevice *dev)
{
- CadenceTTCState *s = FROM_SYSBUS(CadenceTTCState, dev);
+ CadenceTTCState *s = CADENCE_TTC(dev);
int i;
for (i = 0; i < 3; ++i) {
@@ -476,7 +481,7 @@
}
static const TypeInfo cadence_ttc_info = {
- .name = "cadence_ttc",
+ .name = TYPE_CADENCE_TTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(CadenceTTCState),
.class_init = cadence_ttc_class_init,
diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
index 6dd1072..aee4990 100644
--- a/hw/timer/etraxfs_timer.c
+++ b/hw/timer/etraxfs_timer.c
@@ -42,8 +42,13 @@
#define R_INTR 0x50
#define R_MASKED_INTR 0x54
-struct etrax_timer {
- SysBusDevice busdev;
+#define TYPE_ETRAX_FS_TIMER "etraxfs,timer"
+#define ETRAX_TIMER(obj) \
+ OBJECT_CHECK(ETRAXTimerState, (obj), TYPE_ETRAX_FS_TIMER)
+
+typedef struct ETRAXTimerState {
+ SysBusDevice parent_obj;
+
MemoryRegion mmio;
qemu_irq irq;
qemu_irq nmi;
@@ -72,12 +77,12 @@
uint32_t rw_ack_intr;
uint32_t r_intr;
uint32_t r_masked_intr;
-};
+} ETRAXTimerState;
static uint64_t
timer_read(void *opaque, hwaddr addr, unsigned int size)
{
- struct etrax_timer *t = opaque;
+ ETRAXTimerState *t = opaque;
uint32_t r = 0;
switch (addr) {
@@ -88,7 +93,7 @@
r = ptimer_get_count(t->ptimer_t1);
break;
case R_TIME:
- r = qemu_get_clock_ns(vm_clock) / 10;
+ r = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 10;
break;
case RW_INTR_MASK:
r = t->rw_intr_mask;
@@ -103,7 +108,7 @@
return r;
}
-static void update_ctrl(struct etrax_timer *t, int tnum)
+static void update_ctrl(ETRAXTimerState *t, int tnum)
{
unsigned int op;
unsigned int freq;
@@ -167,7 +172,7 @@
}
}
-static void timer_update_irq(struct etrax_timer *t)
+static void timer_update_irq(ETRAXTimerState *t)
{
t->r_intr &= ~(t->rw_ack_intr);
t->r_masked_intr = t->r_intr & t->rw_intr_mask;
@@ -178,21 +183,21 @@
static void timer0_hit(void *opaque)
{
- struct etrax_timer *t = opaque;
+ ETRAXTimerState *t = opaque;
t->r_intr |= 1;
timer_update_irq(t);
}
static void timer1_hit(void *opaque)
{
- struct etrax_timer *t = opaque;
+ ETRAXTimerState *t = opaque;
t->r_intr |= 2;
timer_update_irq(t);
}
static void watchdog_hit(void *opaque)
{
- struct etrax_timer *t = opaque;
+ ETRAXTimerState *t = opaque;
if (t->wd_hits == 0) {
/* real hw gives a single tick before reseting but we are
a bit friendlier to compensate for our slower execution. */
@@ -206,7 +211,7 @@
t->wd_hits++;
}
-static inline void timer_watchdog_update(struct etrax_timer *t, uint32_t value)
+static inline void timer_watchdog_update(ETRAXTimerState *t, uint32_t value)
{
unsigned int wd_en = t->rw_wd_ctrl & (1 << 8);
unsigned int wd_key = t->rw_wd_ctrl >> 9;
@@ -245,7 +250,7 @@
timer_write(void *opaque, hwaddr addr,
uint64_t val64, unsigned int size)
{
- struct etrax_timer *t = opaque;
+ ETRAXTimerState *t = opaque;
uint32_t value = val64;
switch (addr)
@@ -298,7 +303,7 @@
static void etraxfs_timer_reset(void *opaque)
{
- struct etrax_timer *t = opaque;
+ ETRAXTimerState *t = opaque;
ptimer_stop(t->ptimer_t0);
ptimer_stop(t->ptimer_t1);
@@ -311,7 +316,7 @@
static int etraxfs_timer_init(SysBusDevice *dev)
{
- struct etrax_timer *t = FROM_SYSBUS(typeof (*t), dev);
+ ETRAXTimerState *t = ETRAX_TIMER(dev);
t->bh_t0 = qemu_bh_new(timer0_hit, t);
t->bh_t1 = qemu_bh_new(timer1_hit, t);
@@ -338,9 +343,9 @@
}
static const TypeInfo etraxfs_timer_info = {
- .name = "etraxfs,timer",
+ .name = TYPE_ETRAX_FS_TIMER,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof (struct etrax_timer),
+ .instance_size = sizeof(ETRAXTimerState),
.class_init = etraxfs_timer_class_init,
};
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 28ebe5d..86f4fcd 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -54,6 +54,7 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
+#include "qemu/main-loop.h"
#include "qemu-common.h"
#include "hw/ptimer.h"
@@ -240,8 +241,13 @@
} Exynos4210MCTLT;
+#define TYPE_EXYNOS4210_MCT "exynos4210.mct"
+#define EXYNOS4210_MCT(obj) \
+ OBJECT_CHECK(Exynos4210MCTState, (obj), TYPE_EXYNOS4210_MCT)
+
typedef struct Exynos4210MCTState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
/* Registers */
@@ -900,7 +906,7 @@
/* raise interrupt if enabled */
if (s->reg.int_enb & L_INT_INTENB_ICNTEIE) {
#ifdef DEBUG_MCT
- time2[s->id] = qemu_get_clock_ns(vm_clock);
+ time2[s->id] = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
DPRINTF("local timer[%d] IRQ: %llx\n", s->id,
time2[s->id] - time1[s->id]);
time1[s->id] = time2[s->id];
@@ -955,7 +961,7 @@
/* set defaul_timer values for all fields */
static void exynos4210_mct_reset(DeviceState *d)
{
- Exynos4210MCTState *s = (Exynos4210MCTState *)d;
+ Exynos4210MCTState *s = EXYNOS4210_MCT(d);
uint32_t i;
s->reg_mct_cfg = 0;
@@ -1424,7 +1430,7 @@
static int exynos4210_mct_init(SysBusDevice *dev)
{
int i;
- Exynos4210MCTState *s = FROM_SYSBUS(Exynos4210MCTState, dev);
+ Exynos4210MCTState *s = EXYNOS4210_MCT(dev);
QEMUBH *bh[2];
/* Global timer */
@@ -1467,7 +1473,7 @@
}
static const TypeInfo exynos4210_mct_info = {
- .name = "exynos4210.mct",
+ .name = TYPE_EXYNOS4210_MCT,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210MCTState),
.class_init = exynos4210_mct_class_init,
diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
index 8fa0bb2..1aa8f4d 100644
--- a/hw/timer/exynos4210_pwm.c
+++ b/hw/timer/exynos4210_pwm.c
@@ -23,6 +23,7 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
#include "qemu-common.h"
+#include "qemu/main-loop.h"
#include "hw/ptimer.h"
#include "hw/arm/exynos4210.h"
@@ -97,9 +98,13 @@
} Exynos4210PWM;
+#define TYPE_EXYNOS4210_PWM "exynos4210.pwm"
+#define EXYNOS4210_PWM(obj) \
+ OBJECT_CHECK(Exynos4210PWMState, (obj), TYPE_EXYNOS4210_PWM)
typedef struct Exynos4210PWMState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t reg_tcfg[2];
@@ -352,7 +357,7 @@
*/
static void exynos4210_pwm_reset(DeviceState *d)
{
- Exynos4210PWMState *s = (Exynos4210PWMState *)d;
+ Exynos4210PWMState *s = EXYNOS4210_PWM(d);
int i;
s->reg_tcfg[0] = 0x0101;
s->reg_tcfg[1] = 0x0;
@@ -378,7 +383,7 @@
*/
static int exynos4210_pwm_init(SysBusDevice *dev)
{
- Exynos4210PWMState *s = FROM_SYSBUS(Exynos4210PWMState, dev);
+ Exynos4210PWMState *s = EXYNOS4210_PWM(dev);
int i;
QEMUBH *bh;
@@ -408,7 +413,7 @@
}
static const TypeInfo exynos4210_pwm_info = {
- .name = "exynos4210.pwm",
+ .name = TYPE_EXYNOS4210_PWM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210PWMState),
.class_init = exynos4210_pwm_class_init,
diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c
index 7fca071..3f2c8c5 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/timer/exynos4210_rtc.c
@@ -79,8 +79,13 @@
#define RTC_BASE_FREQ 32768
+#define TYPE_EXYNOS4210_RTC "exynos4210.rtc"
+#define EXYNOS4210_RTC(obj) \
+ OBJECT_CHECK(Exynos4210RTCState, (obj), TYPE_EXYNOS4210_RTC)
+
typedef struct Exynos4210RTCState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
/* registers */
@@ -507,7 +512,7 @@
*/
static void exynos4210_rtc_reset(DeviceState *d)
{
- Exynos4210RTCState *s = (Exynos4210RTCState *)d;
+ Exynos4210RTCState *s = EXYNOS4210_RTC(d);
qemu_get_timedate(&s->current_tm, 0);
@@ -544,7 +549,7 @@
*/
static int exynos4210_rtc_init(SysBusDevice *dev)
{
- Exynos4210RTCState *s = FROM_SYSBUS(Exynos4210RTCState, dev);
+ Exynos4210RTCState *s = EXYNOS4210_RTC(dev);
QEMUBH *bh;
bh = qemu_bh_new(exynos4210_rtc_tick, s);
@@ -577,7 +582,7 @@
}
static const TypeInfo exynos4210_rtc_info = {
- .name = "exynos4210.rtc",
+ .name = TYPE_EXYNOS4210_RTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(Exynos4210RTCState),
.class_init = exynos4210_rtc_class_init,
diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c
index 37ba47d..74c16d6 100644
--- a/hw/timer/grlib_gptimer.c
+++ b/hw/timer/grlib_gptimer.c
@@ -25,6 +25,8 @@
#include "hw/sysbus.h"
#include "qemu/timer.h"
#include "hw/ptimer.h"
+#include "qemu/timer.h"
+#include "qemu/main-loop.h"
#include "trace.h"
@@ -50,6 +52,10 @@
#define COUNTER_RELOAD_OFFSET 0x04
#define TIMER_BASE 0x10
+#define TYPE_GRLIB_GPTIMER "grlib,gptimer"
+#define GRLIB_GPTIMER(obj) \
+ OBJECT_CHECK(GPTimerUnit, (obj), TYPE_GRLIB_GPTIMER)
+
typedef struct GPTimer GPTimer;
typedef struct GPTimerUnit GPTimerUnit;
@@ -68,7 +74,8 @@
};
struct GPTimerUnit {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t nr_timers; /* Number of timers available */
@@ -314,7 +321,7 @@
static void grlib_gptimer_reset(DeviceState *d)
{
- GPTimerUnit *unit = container_of(d, GPTimerUnit, busdev.qdev);
+ GPTimerUnit *unit = GRLIB_GPTIMER(d);
int i = 0;
assert(unit != NULL);
@@ -343,7 +350,7 @@
static int grlib_gptimer_init(SysBusDevice *dev)
{
- GPTimerUnit *unit = FROM_SYSBUS(typeof(*unit), dev);
+ GPTimerUnit *unit = GRLIB_GPTIMER(dev);
unsigned int i;
assert(unit->nr_timers > 0);
@@ -391,7 +398,7 @@
}
static const TypeInfo grlib_gptimer_info = {
- .name = "grlib,gptimer",
+ .name = TYPE_GRLIB_GPTIMER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(GPTimerUnit),
.class_init = grlib_gptimer_class_init,
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index 648b383..fcd22ae 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -152,7 +152,7 @@
static uint64_t hpet_get_ticks(HPETState *s)
{
- return ns_to_ticks(qemu_get_clock_ns(vm_clock) + s->hpet_offset);
+ return ns_to_ticks(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->hpet_offset);
}
/*
@@ -233,7 +233,7 @@
HPETState *s = opaque;
/* Recalculate the offset between the main counter and guest time */
- s->hpet_offset = ticks_to_ns(s->hpet_counter) - qemu_get_clock_ns(vm_clock);
+ s->hpet_offset = ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
/* Push number of timers into capability returned via HPET_ID */
s->capability &= ~HPET_ID_NUM_TIM_MASK;
@@ -332,12 +332,12 @@
}
}
diff = hpet_calculate_diff(t, cur_tick);
- qemu_mod_timer(t->qemu_timer,
- qemu_get_clock_ns(vm_clock) + (int64_t)ticks_to_ns(diff));
+ timer_mod(t->qemu_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (int64_t)ticks_to_ns(diff));
} else if (t->config & HPET_TN_32BIT && !timer_is_periodic(t)) {
if (t->wrap_flag) {
diff = hpet_calculate_diff(t, cur_tick);
- qemu_mod_timer(t->qemu_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(t->qemu_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
(int64_t)ticks_to_ns(diff));
t->wrap_flag = 0;
}
@@ -365,13 +365,13 @@
t->wrap_flag = 1;
}
}
- qemu_mod_timer(t->qemu_timer,
- qemu_get_clock_ns(vm_clock) + (int64_t)ticks_to_ns(diff));
+ timer_mod(t->qemu_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + (int64_t)ticks_to_ns(diff));
}
static void hpet_del_timer(HPETTimer *t)
{
- qemu_del_timer(t->qemu_timer);
+ timer_del(t->qemu_timer);
update_irq(t, 0);
}
@@ -567,7 +567,7 @@
if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
/* Enable main counter and interrupt generation. */
s->hpet_offset =
- ticks_to_ns(s->hpet_counter) - qemu_get_clock_ns(vm_clock);
+ ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
for (i = 0; i < s->num_timers; i++) {
if ((&s->timer[i])->cmp != ~0ULL) {
hpet_set_timer(&s->timer[i]);
@@ -726,7 +726,7 @@
}
for (i = 0; i < HPET_MAX_TIMERS; i++) {
timer = &s->timer[i];
- timer->qemu_timer = qemu_new_timer_ns(vm_clock, hpet_timer, timer);
+ timer->qemu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, hpet_timer, timer);
timer->tn = i;
timer->state = s;
}
diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c
index cd52140..cdbf481 100644
--- a/hw/timer/i8254.c
+++ b/hw/timer/i8254.c
@@ -51,7 +51,7 @@
uint64_t d;
int counter;
- d = muldiv64(qemu_get_clock_ns(vm_clock) - s->count_load_time, PIT_FREQ,
+ d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->count_load_time, PIT_FREQ,
get_ticks_per_sec());
switch(s->mode) {
case 0:
@@ -85,7 +85,7 @@
case 5:
if (sc->gate < val) {
/* restart counting on rising edge */
- sc->count_load_time = qemu_get_clock_ns(vm_clock);
+ sc->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
pit_irq_timer_update(sc, sc->count_load_time);
}
break;
@@ -93,7 +93,7 @@
case 3:
if (sc->gate < val) {
/* restart counting on rising edge */
- sc->count_load_time = qemu_get_clock_ns(vm_clock);
+ sc->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
pit_irq_timer_update(sc, sc->count_load_time);
}
/* XXX: disable/enable counting */
@@ -106,7 +106,7 @@
{
if (val == 0)
val = 0x10000;
- s->count_load_time = qemu_get_clock_ns(vm_clock);
+ s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->count = val;
pit_irq_timer_update(s, s->count_load_time);
}
@@ -143,7 +143,7 @@
/* XXX: add BCD and null count */
s->status =
(pit_get_out(s,
- qemu_get_clock_ns(vm_clock)) << 7) |
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) << 7) |
(s->rw_mode << 4) |
(s->mode << 1) |
s->bcd;
@@ -260,9 +260,9 @@
#endif
s->next_transition_time = expire_time;
if (expire_time != -1)
- qemu_mod_timer(s->irq_timer, expire_time);
+ timer_mod(s->irq_timer, expire_time);
else
- qemu_del_timer(s->irq_timer);
+ timer_del(s->irq_timer);
}
static void pit_irq_timer(void *opaque)
@@ -281,7 +281,7 @@
s = &pit->channels[0];
if (!s->irq_disabled) {
- qemu_mod_timer(s->irq_timer, s->next_transition_time);
+ timer_mod(s->irq_timer, s->next_transition_time);
}
}
@@ -294,10 +294,10 @@
if (enable) {
s->irq_disabled = 0;
- pit_irq_timer_update(s, qemu_get_clock_ns(vm_clock));
+ pit_irq_timer_update(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
} else {
s->irq_disabled = 1;
- qemu_del_timer(s->irq_timer);
+ timer_del(s->irq_timer);
}
}
@@ -316,9 +316,9 @@
PITChannelState *sc = &s->channels[0];
if (sc->next_transition_time != -1) {
- qemu_mod_timer(sc->irq_timer, sc->next_transition_time);
+ timer_mod(sc->irq_timer, sc->next_transition_time);
} else {
- qemu_del_timer(sc->irq_timer);
+ timer_del(sc->irq_timer);
}
}
@@ -330,7 +330,7 @@
s = &pit->channels[0];
/* the timer 0 is connected to an IRQ */
- s->irq_timer = qemu_new_timer_ns(vm_clock, pit_irq_timer, s);
+ s->irq_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pit_irq_timer, s);
qdev_init_gpio_out(dev, &s->irq, 1);
memory_region_init_io(&pit->ioports, OBJECT(pit), &pit_ioport_ops,
diff --git a/hw/timer/i8254_common.c b/hw/timer/i8254_common.c
index 4e5bf0b..e8fb971 100644
--- a/hw/timer/i8254_common.c
+++ b/hw/timer/i8254_common.c
@@ -136,7 +136,7 @@
info->gate = sc->gate;
info->mode = sc->mode;
info->initial_count = sc->count;
- info->out = pit_get_out(sc, qemu_get_clock_ns(vm_clock));
+ info->out = pit_get_out(sc, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
}
void pit_get_channel_info(ISADevice *dev, int channel, PITChannelInfo *info)
@@ -157,7 +157,7 @@
s = &pit->channels[i];
s->mode = 3;
s->gate = (i != 2);
- s->count_load_time = qemu_get_clock_ns(vm_clock);
+ s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->count = 0x10000;
if (i == 0 && !s->irq_disabled) {
s->next_transition_time =
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index 117dc7b..0dbe15c 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -18,6 +18,7 @@
#include "hw/ptimer.h"
#include "hw/sysbus.h"
#include "hw/arm/imx.h"
+#include "qemu/main-loop.h"
#define TYPE_IMX_EPIT "imx.epit"
@@ -43,7 +44,7 @@
}
# define DPRINTF(fmt, args...) \
- do { printf("%s: " fmt , __func__, ##args); } while (0)
+ do { fprintf(stderr, "%s: " fmt , __func__, ##args); } while (0)
#else
# define DPRINTF(fmt, args...) do {} while (0)
#endif
@@ -152,7 +153,7 @@
/*
* Soft reset doesn't touch some bits; hard reset clears them
*/
- s->cr &= ~(CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN);
+ s->cr &= (CR_EN|CR_ENMOD|CR_STOPEN|CR_DOZEN|CR_WAITEN|CR_DBGEN);
s->sr = 0;
s->lr = TIMER_MAX;
s->cmp = 0;
@@ -167,7 +168,7 @@
ptimer_set_limit(s->timer_reload, TIMER_MAX, 1);
if (s->freq && (s->cr & CR_EN)) {
/* if the timer is still enabled, restart it */
- ptimer_run(s->timer_reload, 1);
+ ptimer_run(s->timer_reload, 0);
}
}
@@ -218,17 +219,17 @@
static void imx_epit_reload_compare_timer(IMXEPITState *s)
{
- if ((s->cr & CR_OCIEN) && s->cmp) {
- /* if the compare feature is on */
+ if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN)) {
+ /* if the compare feature is on and timers are running */
uint32_t tmp = imx_epit_update_count(s);
+ uint64_t next;
if (tmp > s->cmp) {
- /* reinit the cmp timer if required */
- ptimer_set_count(s->timer_cmp, tmp - s->cmp);
- if ((s->cr & CR_EN)) {
- /* Restart the cmp timer if required */
- ptimer_run(s->timer_cmp, 0);
- }
+ /* It'll fire in this round of the timer */
+ next = tmp - s->cmp;
+ } else { /* catch it next time around */
+ next = tmp - s->cmp + ((s->cr & CR_RLD) ? TIMER_MAX : s->lr);
}
+ ptimer_set_count(s->timer_cmp, next);
}
}
@@ -237,11 +238,14 @@
{
IMXEPITState *s = IMX_EPIT(opaque);
uint32_t reg = offset >> 2;
+ uint64_t oldcr;
DPRINTF("(%s, value = 0x%08x)\n", imx_epit_reg_name(reg), (uint32_t)value);
switch (reg) {
case 0: /* CR */
+
+ oldcr = s->cr;
s->cr = value & 0x03ffffff;
if (s->cr & CR_SWR) {
/* handle the reset */
@@ -250,22 +254,35 @@
imx_epit_set_freq(s);
}
- if (s->freq && (s->cr & CR_EN)) {
+ if (s->freq && (s->cr & CR_EN) && !(oldcr & CR_EN)) {
if (s->cr & CR_ENMOD) {
if (s->cr & CR_RLD) {
ptimer_set_limit(s->timer_reload, s->lr, 1);
+ ptimer_set_limit(s->timer_cmp, s->lr, 1);
} else {
ptimer_set_limit(s->timer_reload, TIMER_MAX, 1);
+ ptimer_set_limit(s->timer_cmp, TIMER_MAX, 1);
}
}
imx_epit_reload_compare_timer(s);
-
- ptimer_run(s->timer_reload, 1);
- } else {
+ ptimer_run(s->timer_reload, 0);
+ if (s->cr & CR_OCIEN) {
+ ptimer_run(s->timer_cmp, 0);
+ } else {
+ ptimer_stop(s->timer_cmp);
+ }
+ } else if (!(s->cr & CR_EN)) {
/* stop both timers */
ptimer_stop(s->timer_reload);
ptimer_stop(s->timer_cmp);
+ } else if (s->cr & CR_OCIEN) {
+ if (!(oldcr & CR_OCIEN)) {
+ imx_epit_reload_compare_timer(s);
+ ptimer_run(s->timer_cmp, 0);
+ }
+ } else {
+ ptimer_stop(s->timer_cmp);
}
break;
@@ -284,13 +301,13 @@
/* Also set the limit if the LRD bit is set */
/* If IOVW bit is set then set the timer value */
ptimer_set_limit(s->timer_reload, s->lr, s->cr & CR_IOVW);
+ ptimer_set_limit(s->timer_cmp, s->lr, 0);
} else if (s->cr & CR_IOVW) {
/* If IOVW bit is set then set the timer value */
ptimer_set_count(s->timer_reload, s->lr);
}
imx_epit_reload_compare_timer(s);
-
break;
case 3: /* CMP */
@@ -306,51 +323,14 @@
break;
}
}
-
-static void imx_epit_timeout(void *opaque)
-{
- IMXEPITState *s = IMX_EPIT(opaque);
-
- DPRINTF("\n");
-
- if (!(s->cr & CR_EN)) {
- return;
- }
-
- if (s->cr & CR_RLD) {
- ptimer_set_limit(s->timer_reload, s->lr, 1);
- } else {
- ptimer_set_limit(s->timer_reload, TIMER_MAX, 1);
- }
-
- if (s->cr & CR_OCIEN) {
- /* if compare register is 0 then we handle the interrupt here */
- if (s->cmp == 0) {
- s->sr = 1;
- imx_epit_update_int(s);
- } else if (s->cmp <= s->lr) {
- /* We should launch the compare register */
- ptimer_set_count(s->timer_cmp, s->lr - s->cmp);
- ptimer_run(s->timer_cmp, 0);
- } else {
- IPRINTF("s->lr < s->cmp\n");
- }
- }
-}
-
static void imx_epit_cmp(void *opaque)
{
IMXEPITState *s = IMX_EPIT(opaque);
- DPRINTF("\n");
+ DPRINTF("sr was %d\n", s->sr);
- ptimer_stop(s->timer_cmp);
-
- /* compare register is not 0 */
- if (s->cmp) {
- s->sr = 1;
- imx_epit_update_int(s);
- }
+ s->sr = 1;
+ imx_epit_update_int(s);
}
void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm)
@@ -400,8 +380,7 @@
0x00001000);
sysbus_init_mmio(sbd, &s->iomem);
- bh = qemu_bh_new(imx_epit_timeout, s);
- s->timer_reload = ptimer_init(bh);
+ s->timer_reload = ptimer_init(NULL);
bh = qemu_bh_new(imx_epit_cmp, s);
s->timer_cmp = ptimer_init(bh);
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 87db0e1..f2d1975 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -18,6 +18,7 @@
#include "hw/ptimer.h"
#include "hw/sysbus.h"
#include "hw/arm/imx.h"
+#include "qemu/main-loop.h"
#define TYPE_IMX_GPT "imx.gpt"
diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c
index 016dade..8ed138c 100644
--- a/hw/timer/lm32_timer.c
+++ b/hw/timer/lm32_timer.c
@@ -27,6 +27,7 @@
#include "qemu/timer.h"
#include "hw/ptimer.h"
#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
#define DEFAULT_FREQUENCY (50*1000000)
@@ -50,8 +51,12 @@
CR_STOP = (1 << 3),
};
+#define TYPE_LM32_TIMER "lm32-timer"
+#define LM32_TIMER(obj) OBJECT_CHECK(LM32TimerState, (obj), TYPE_LM32_TIMER)
+
struct LM32TimerState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
QEMUBH *bh;
@@ -161,7 +166,7 @@
static void timer_reset(DeviceState *d)
{
- LM32TimerState *s = container_of(d, LM32TimerState, busdev.qdev);
+ LM32TimerState *s = LM32_TIMER(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -172,7 +177,7 @@
static int lm32_timer_init(SysBusDevice *dev)
{
- LM32TimerState *s = FROM_SYSBUS(typeof(*s), dev);
+ LM32TimerState *s = LM32_TIMER(dev);
sysbus_init_irq(dev, &s->irq);
@@ -217,7 +222,7 @@
}
static const TypeInfo lm32_timer_info = {
- .name = "lm32-timer",
+ .name = TYPE_LM32_TIMER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(LM32TimerState),
.class_init = lm32_timer_class_init,
diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index be3490b..d3d78ec 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -83,8 +83,12 @@
MemoryRegion io;
} M48t59ISAState;
+#define SYSBUS_M48T59(obj) \
+ OBJECT_CHECK(M48t59SysBusState, (obj), TYPE_SYSBUS_M48T59)
+
typedef struct M48t59SysBusState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
M48t59State state;
MemoryRegion io;
} M48t59SysBusState;
@@ -133,7 +137,7 @@
/* Repeat once a second */
next_time = 1;
}
- qemu_mod_timer(NVRAM->alrm_timer, qemu_get_clock_ns(rtc_clock) +
+ timer_mod(NVRAM->alrm_timer, qemu_clock_get_ns(rtc_clock) +
next_time * 1000);
qemu_set_irq(NVRAM->IRQ, 0);
}
@@ -142,10 +146,10 @@
{
int diff;
if (NVRAM->alrm_timer != NULL) {
- qemu_del_timer(NVRAM->alrm_timer);
+ timer_del(NVRAM->alrm_timer);
diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset;
if (diff > 0)
- qemu_mod_timer(NVRAM->alrm_timer, diff * 1000);
+ timer_mod(NVRAM->alrm_timer, diff * 1000);
}
}
@@ -184,10 +188,10 @@
NVRAM->buffer[0x1FF0] &= ~0x80;
if (NVRAM->wd_timer != NULL) {
- qemu_del_timer(NVRAM->wd_timer);
+ timer_del(NVRAM->wd_timer);
if (value != 0) {
interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
- qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
+ timer_mod(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
((interval * 1000) >> 4));
}
}
@@ -605,10 +609,10 @@
NVRAM->addr = 0;
NVRAM->lock = 0;
if (NVRAM->alrm_timer != NULL)
- qemu_del_timer(NVRAM->alrm_timer);
+ timer_del(NVRAM->alrm_timer);
if (NVRAM->wd_timer != NULL)
- qemu_del_timer(NVRAM->wd_timer);
+ timer_del(NVRAM->wd_timer);
}
static void m48t59_reset_isa(DeviceState *d)
@@ -621,7 +625,7 @@
static void m48t59_reset_sysbus(DeviceState *d)
{
- M48t59SysBusState *sys = container_of(d, M48t59SysBusState, busdev.qdev);
+ M48t59SysBusState *sys = SYSBUS_M48T59(d);
M48t59State *NVRAM = &sys->state;
m48t59_reset_common(NVRAM);
@@ -646,13 +650,13 @@
M48t59SysBusState *d;
M48t59State *state;
- dev = qdev_create(NULL, "m48t59");
+ dev = qdev_create(NULL, TYPE_SYSBUS_M48T59);
qdev_prop_set_uint32(dev, "model", model);
qdev_prop_set_uint32(dev, "size", size);
qdev_prop_set_uint32(dev, "io_base", io_base);
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
- d = FROM_SYSBUS(M48t59SysBusState, s);
+ d = SYSBUS_M48T59(dev);
state = &d->state;
sysbus_connect_irq(s, 0, IRQ);
memory_region_init_io(&d->io, OBJECT(d), &m48t59_io_ops, state,
@@ -696,8 +700,8 @@
{
s->buffer = g_malloc0(s->size);
if (s->model == 59) {
- s->alrm_timer = qemu_new_timer_ns(rtc_clock, &alarm_cb, s);
- s->wd_timer = qemu_new_timer_ns(vm_clock, &watchdog_cb, s);
+ s->alrm_timer = timer_new_ns(rtc_clock, &alarm_cb, s);
+ s->wd_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &watchdog_cb, s);
}
qemu_get_timedate(&s->alarm, 0);
@@ -716,7 +720,7 @@
static int m48t59_init1(SysBusDevice *dev)
{
- M48t59SysBusState *d = FROM_SYSBUS(M48t59SysBusState, dev);
+ M48t59SysBusState *d = SYSBUS_M48T59(dev);
M48t59State *s = &d->state;
Error *err = NULL;
@@ -776,7 +780,7 @@
}
static const TypeInfo m48t59_info = {
- .name = "m48t59",
+ .name = TYPE_SYSBUS_M48T59,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(M48t59SysBusState),
.class_init = m48t59_class_init,
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 3c3baac..7230a6e 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -102,7 +102,7 @@
static uint64_t get_guest_rtc_ns(RTCState *s)
{
uint64_t guest_rtc;
- uint64_t guest_clock = qemu_get_clock_ns(rtc_clock);
+ uint64_t guest_clock = qemu_clock_get_ns(rtc_clock);
guest_rtc = s->base_rtc * NSEC_PER_SEC
+ guest_clock - s->last_update + s->offset;
@@ -113,13 +113,13 @@
static void rtc_coalesced_timer_update(RTCState *s)
{
if (s->irq_coalesced == 0) {
- qemu_del_timer(s->coalesced_timer);
+ timer_del(s->coalesced_timer);
} else {
/* divide each RTC interval to 2 - 8 smaller intervals */
int c = MIN(s->irq_coalesced, 7) + 1;
- int64_t next_clock = qemu_get_clock_ns(rtc_clock) +
+ int64_t next_clock = qemu_clock_get_ns(rtc_clock) +
muldiv64(s->period / c, get_ticks_per_sec(), RTC_CLOCK_RATE);
- qemu_mod_timer(s->coalesced_timer, next_clock);
+ timer_mod(s->coalesced_timer, next_clock);
}
}
@@ -169,12 +169,12 @@
next_irq_clock = (cur_clock & ~(period - 1)) + period;
s->next_periodic_time =
muldiv64(next_irq_clock, get_ticks_per_sec(), RTC_CLOCK_RATE) + 1;
- qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
+ timer_mod(s->periodic_timer, s->next_periodic_time);
} else {
#ifdef TARGET_I386
s->irq_coalesced = 0;
#endif
- qemu_del_timer(s->periodic_timer);
+ timer_del(s->periodic_timer);
}
}
@@ -222,23 +222,23 @@
* from occurring, because the time of day is not updated.
*/
if ((s->cmos_data[RTC_REG_A] & 0x60) == 0x60) {
- qemu_del_timer(s->update_timer);
+ timer_del(s->update_timer);
return;
}
if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
- qemu_del_timer(s->update_timer);
+ timer_del(s->update_timer);
return;
}
if ((s->cmos_data[RTC_REG_C] & REG_C_UF) &&
(s->cmos_data[RTC_REG_C] & REG_C_AF)) {
- qemu_del_timer(s->update_timer);
+ timer_del(s->update_timer);
return;
}
guest_nsec = get_guest_rtc_ns(s) % NSEC_PER_SEC;
/* if UF is clear, reprogram to next second */
- next_update_time = qemu_get_clock_ns(rtc_clock)
+ next_update_time = qemu_clock_get_ns(rtc_clock)
+ NSEC_PER_SEC - guest_nsec;
/* Compute time of next alarm. One second is already accounted
@@ -252,8 +252,8 @@
* the alarm time. */
next_update_time = s->next_alarm_time;
}
- if (next_update_time != qemu_timer_expire_time_ns(s->update_timer)) {
- qemu_mod_timer(s->update_timer, next_update_time);
+ if (next_update_time != timer_expire_time_ns(s->update_timer)) {
+ timer_mod(s->update_timer, next_update_time);
}
}
@@ -371,7 +371,7 @@
rtc_update_time(s);
s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
- if (qemu_get_clock_ns(rtc_clock) >= s->next_alarm_time) {
+ if (qemu_clock_get_ns(rtc_clock) >= s->next_alarm_time) {
irqs |= REG_C_AF;
if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_RTC);
@@ -445,7 +445,7 @@
/* UIP bit is read only */
s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
(s->cmos_data[RTC_REG_A] & REG_A_UIP);
- periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
+ periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
check_update_timer(s);
break;
case RTC_REG_B:
@@ -475,7 +475,7 @@
qemu_irq_lower(s->irq);
}
s->cmos_data[RTC_REG_B] = data;
- periodic_timer_update(s, qemu_get_clock_ns(rtc_clock));
+ periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
check_update_timer(s);
break;
case RTC_REG_C:
@@ -535,7 +535,7 @@
rtc_get_time(s, &tm);
s->base_rtc = mktimegm(&tm);
- s->last_update = qemu_get_clock_ns(rtc_clock);
+ s->last_update = qemu_clock_get_ns(rtc_clock);
rtc_change_mon_event(&tm);
}
@@ -587,10 +587,11 @@
if (!rtc_running(s)) {
return 0;
}
- if (qemu_timer_pending(s->update_timer)) {
- int64_t next_update_time = qemu_timer_expire_time_ns(s->update_timer);
+ if (timer_pending(s->update_timer)) {
+ int64_t next_update_time = timer_expire_time_ns(s->update_timer);
/* Latch UIP until the timer expires. */
- if (qemu_get_clock_ns(rtc_clock) >= (next_update_time - UIP_HOLD_LENGTH)) {
+ if (qemu_clock_get_ns(rtc_clock) >=
+ (next_update_time - UIP_HOLD_LENGTH)) {
s->cmos_data[RTC_REG_A] |= REG_A_UIP;
return 1;
}
@@ -695,7 +696,7 @@
qemu_get_timedate(&tm, 0);
s->base_rtc = mktimegm(&tm);
- s->last_update = qemu_get_clock_ns(rtc_clock);
+ s->last_update = qemu_clock_get_ns(rtc_clock);
s->offset = 0;
/* set the CMOS date */
@@ -843,7 +844,7 @@
switch (s->lost_tick_policy) {
case LOST_TICK_SLEW:
s->coalesced_timer =
- qemu_new_timer_ns(rtc_clock, rtc_coalesced_timer, s);
+ timer_new_ns(rtc_clock, rtc_coalesced_timer, s);
break;
case LOST_TICK_DISCARD:
break;
@@ -853,12 +854,13 @@
}
#endif
- s->periodic_timer = qemu_new_timer_ns(rtc_clock, rtc_periodic_timer, s);
- s->update_timer = qemu_new_timer_ns(rtc_clock, rtc_update_timer, s);
+ s->periodic_timer = timer_new_ns(rtc_clock, rtc_periodic_timer, s);
+ s->update_timer = timer_new_ns(rtc_clock, rtc_update_timer, s);
check_update_timer(s);
s->clock_reset_notifier.notify = rtc_notify_clock_reset;
- qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);
+ qemu_clock_register_reset_notifier(QEMU_CLOCK_REALTIME,
+ &s->clock_reset_notifier);
s->suspend_notifier.notify = rtc_notify_suspend;
qemu_register_suspend_notifier(&s->suspend_notifier);
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
index 5009394..94246e5 100644
--- a/hw/timer/milkymist-sysctl.c
+++ b/hw/timer/milkymist-sysctl.c
@@ -57,8 +57,13 @@
R_MAX
};
+#define TYPE_MILKYMIST_SYSCTL "milkymist-sysctl"
+#define MILKYMIST_SYSCTL(obj) \
+ OBJECT_CHECK(MilkymistSysctlState, (obj), TYPE_MILKYMIST_SYSCTL)
+
struct MilkymistSysctlState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion regs_region;
QEMUBH *bh0;
@@ -246,8 +251,7 @@
static void milkymist_sysctl_reset(DeviceState *d)
{
- MilkymistSysctlState *s =
- container_of(d, MilkymistSysctlState, busdev.qdev);
+ MilkymistSysctlState *s = MILKYMIST_SYSCTL(d);
int i;
for (i = 0; i < R_MAX; i++) {
@@ -267,7 +271,7 @@
static int milkymist_sysctl_init(SysBusDevice *dev)
{
- MilkymistSysctlState *s = FROM_SYSBUS(typeof(*s), dev);
+ MilkymistSysctlState *s = MILKYMIST_SYSCTL(dev);
sysbus_init_irq(dev, &s->gpio_irq);
sysbus_init_irq(dev, &s->timer0_irq);
@@ -324,7 +328,7 @@
}
static const TypeInfo milkymist_sysctl_info = {
- .name = "milkymist-sysctl",
+ .name = TYPE_MILKYMIST_SYSCTL,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MilkymistSysctlState),
.class_init = milkymist_sysctl_class_init,
diff --git a/hw/timer/omap_gptimer.c b/hw/timer/omap_gptimer.c
index ac389d8..016207f 100644
--- a/hw/timer/omap_gptimer.c
+++ b/hw/timer/omap_gptimer.c
@@ -103,7 +103,7 @@
uint64_t distance;
if (timer->st && timer->rate) {
- distance = qemu_get_clock_ns(vm_clock) - timer->time;
+ distance = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - timer->time;
distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);
if (distance >= 0xffffffff - timer->val)
@@ -118,7 +118,7 @@
{
if (timer->st) {
timer->val = omap_gp_timer_read(timer);
- timer->time = qemu_get_clock_ns(vm_clock);
+ timer->time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
}
@@ -129,17 +129,17 @@
if (timer->st && timer->rate) {
expires = muldiv64(0x100000000ll - timer->val,
timer->ticks_per_sec, timer->rate);
- qemu_mod_timer(timer->timer, timer->time + expires);
+ timer_mod(timer->timer, timer->time + expires);
if (timer->ce && timer->match_val >= timer->val) {
matches = muldiv64(timer->match_val - timer->val,
timer->ticks_per_sec, timer->rate);
- qemu_mod_timer(timer->match, timer->time + matches);
+ timer_mod(timer->match, timer->time + matches);
} else
- qemu_del_timer(timer->match);
+ timer_del(timer->match);
} else {
- qemu_del_timer(timer->timer);
- qemu_del_timer(timer->match);
+ timer_del(timer->timer);
+ timer_del(timer->match);
omap_gp_timer_out(timer, timer->scpwm);
}
}
@@ -164,7 +164,7 @@
timer->val = 0;
} else {
timer->val = timer->load_val;
- timer->time = qemu_get_clock_ns(vm_clock);
+ timer->time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
if (timer->trigger == gpt_trigger_overflow ||
@@ -406,7 +406,7 @@
break;
case 0x28: /* TCRR */
- s->time = qemu_get_clock_ns(vm_clock);
+ s->time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->val = value;
omap_gp_timer_update(s);
break;
@@ -416,7 +416,7 @@
break;
case 0x30: /* TTGR */
- s->time = qemu_get_clock_ns(vm_clock);
+ s->time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->val = s->load_val;
omap_gp_timer_update(s);
break;
@@ -474,8 +474,8 @@
s->ta = ta;
s->irq = irq;
s->clk = fclk;
- s->timer = qemu_new_timer_ns(vm_clock, omap_gp_timer_tick, s);
- s->match = qemu_new_timer_ns(vm_clock, omap_gp_timer_match, s);
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_gp_timer_tick, s);
+ s->match = timer_new_ns(QEMU_CLOCK_VIRTUAL, omap_gp_timer_match, s);
s->in = qemu_allocate_irqs(omap_gp_timer_input, s, 1)[0];
omap_gp_timer_reset(s);
omap_gp_timer_clk_setup(s);
diff --git a/hw/timer/omap_synctimer.c b/hw/timer/omap_synctimer.c
index a12aca2..8e50488 100644
--- a/hw/timer/omap_synctimer.c
+++ b/hw/timer/omap_synctimer.c
@@ -28,7 +28,7 @@
/* 32-kHz Sync Timer of the OMAP2 */
static uint32_t omap_synctimer_read(struct omap_synctimer_s *s) {
- return muldiv64(qemu_get_clock_ns(vm_clock), 0x8000, get_ticks_per_sec());
+ return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 0x8000, get_ticks_per_sec());
}
void omap_synctimer_reset(struct omap_synctimer_s *s)
diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c
index 3ce6ed8..65928a4 100644
--- a/hw/timer/pl031.c
+++ b/hw/timer/pl031.c
@@ -33,8 +33,12 @@
#define RTC_MIS 0x18 /* Masked interrupt status register */
#define RTC_ICR 0x1c /* Interrupt clear register */
-typedef struct {
- SysBusDevice busdev;
+#define TYPE_PL031 "pl031"
+#define PL031(obj) OBJECT_CHECK(PL031State, (obj), TYPE_PL031)
+
+typedef struct PL031State {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
QEMUTimer *timer;
qemu_irq irq;
@@ -51,34 +55,34 @@
uint32_t cr;
uint32_t im;
uint32_t is;
-} pl031_state;
+} PL031State;
static const unsigned char pl031_id[] = {
0x31, 0x10, 0x14, 0x00, /* Device ID */
0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
};
-static void pl031_update(pl031_state *s)
+static void pl031_update(PL031State *s)
{
qemu_set_irq(s->irq, s->is & s->im);
}
static void pl031_interrupt(void * opaque)
{
- pl031_state *s = (pl031_state *)opaque;
+ PL031State *s = (PL031State *)opaque;
s->is = 1;
DPRINTF("Alarm raised\n");
pl031_update(s);
}
-static uint32_t pl031_get_count(pl031_state *s)
+static uint32_t pl031_get_count(PL031State *s)
{
- int64_t now = qemu_get_clock_ns(rtc_clock);
+ int64_t now = qemu_clock_get_ns(rtc_clock);
return s->tick_offset + now / get_ticks_per_sec();
}
-static void pl031_set_alarm(pl031_state *s)
+static void pl031_set_alarm(PL031State *s)
{
uint32_t ticks;
@@ -87,18 +91,18 @@
ticks = s->mr - pl031_get_count(s);
DPRINTF("Alarm set in %ud ticks\n", ticks);
if (ticks == 0) {
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
pl031_interrupt(s);
} else {
- int64_t now = qemu_get_clock_ns(rtc_clock);
- qemu_mod_timer(s->timer, now + (int64_t)ticks * get_ticks_per_sec());
+ int64_t now = qemu_clock_get_ns(rtc_clock);
+ timer_mod(s->timer, now + (int64_t)ticks * get_ticks_per_sec());
}
}
static uint64_t pl031_read(void *opaque, hwaddr offset,
unsigned size)
{
- pl031_state *s = (pl031_state *)opaque;
+ PL031State *s = (PL031State *)opaque;
if (offset >= 0xfe0 && offset < 0x1000)
return pl031_id[(offset - 0xfe0) >> 2];
@@ -136,7 +140,7 @@
static void pl031_write(void * opaque, hwaddr offset,
uint64_t value, unsigned size)
{
- pl031_state *s = (pl031_state *)opaque;
+ PL031State *s = (PL031State *)opaque;
switch (offset) {
@@ -189,7 +193,7 @@
static int pl031_init(SysBusDevice *dev)
{
- pl031_state *s = FROM_SYSBUS(pl031_state, dev);
+ PL031State *s = PL031(dev);
struct tm tm;
memory_region_init_io(&s->iomem, OBJECT(s), &pl031_ops, s, "pl031", 0x1000);
@@ -197,27 +201,28 @@
sysbus_init_irq(dev, &s->irq);
qemu_get_timedate(&tm, 0);
- s->tick_offset = mktimegm(&tm) - qemu_get_clock_ns(rtc_clock) / get_ticks_per_sec();
+ s->tick_offset = mktimegm(&tm) -
+ qemu_clock_get_ns(rtc_clock) / get_ticks_per_sec();
- s->timer = qemu_new_timer_ns(rtc_clock, pl031_interrupt, s);
+ s->timer = timer_new_ns(rtc_clock, pl031_interrupt, s);
return 0;
}
static void pl031_pre_save(void *opaque)
{
- pl031_state *s = opaque;
+ PL031State *s = opaque;
/* tick_offset is base_time - rtc_clock base time. Instead, we want to
- * store the base time relative to the vm_clock for backwards-compatibility. */
- int64_t delta = qemu_get_clock_ns(rtc_clock) - qemu_get_clock_ns(vm_clock);
+ * store the base time relative to the QEMU_CLOCK_VIRTUAL for backwards-compatibility. */
+ int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->tick_offset_vmstate = s->tick_offset + delta / get_ticks_per_sec();
}
static int pl031_post_load(void *opaque, int version_id)
{
- pl031_state *s = opaque;
+ PL031State *s = opaque;
- int64_t delta = qemu_get_clock_ns(rtc_clock) - qemu_get_clock_ns(vm_clock);
+ int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->tick_offset = s->tick_offset_vmstate - delta / get_ticks_per_sec();
pl031_set_alarm(s);
return 0;
@@ -230,12 +235,12 @@
.pre_save = pl031_pre_save,
.post_load = pl031_post_load,
.fields = (VMStateField[]) {
- VMSTATE_UINT32(tick_offset_vmstate, pl031_state),
- VMSTATE_UINT32(mr, pl031_state),
- VMSTATE_UINT32(lr, pl031_state),
- VMSTATE_UINT32(cr, pl031_state),
- VMSTATE_UINT32(im, pl031_state),
- VMSTATE_UINT32(is, pl031_state),
+ VMSTATE_UINT32(tick_offset_vmstate, PL031State),
+ VMSTATE_UINT32(mr, PL031State),
+ VMSTATE_UINT32(lr, PL031State),
+ VMSTATE_UINT32(cr, PL031State),
+ VMSTATE_UINT32(im, PL031State),
+ VMSTATE_UINT32(is, PL031State),
VMSTATE_END_OF_LIST()
}
};
@@ -251,9 +256,9 @@
}
static const TypeInfo pl031_info = {
- .name = "pl031",
+ .name = TYPE_PL031,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(pl031_state),
+ .instance_size = sizeof(PL031State),
.class_init = pl031_class_init,
};
diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c
index 63f2c9f..fa9eefd 100644
--- a/hw/timer/puv3_ost.c
+++ b/hw/timer/puv3_ost.c
@@ -10,13 +10,18 @@
*/
#include "hw/sysbus.h"
#include "hw/ptimer.h"
+#include "qemu/main-loop.h"
#undef DEBUG_PUV3
#include "hw/unicore32/puv3.h"
+#define TYPE_PUV3_OST "puv3_ost"
+#define PUV3_OST(obj) OBJECT_CHECK(PUV3OSTState, (obj), TYPE_PUV3_OST)
+
/* puv3 ostimer implementation. */
-typedef struct {
- SysBusDevice busdev;
+typedef struct PUV3OSTState {
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
QEMUBH *bh;
qemu_irq irq;
@@ -109,7 +114,7 @@
static int puv3_ost_init(SysBusDevice *dev)
{
- PUV3OSTState *s = FROM_SYSBUS(PUV3OSTState, dev);
+ PUV3OSTState *s = PUV3_OST(dev);
s->reg_OIER = 0;
s->reg_OSSR = 0;
@@ -137,7 +142,7 @@
}
static const TypeInfo puv3_ost_info = {
- .name = "puv3_ost",
+ .name = TYPE_PUV3_OST,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(PUV3OSTState),
.class_init = puv3_ost_class_init,
diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c
index 4d28719..0f546c4 100644
--- a/hw/timer/pxa2xx_timer.c
+++ b/hw/timer/pxa2xx_timer.c
@@ -60,6 +60,10 @@
[5 ... 7] = 0,
};
+#define TYPE_PXA2XX_TIMER "pxa2xx-timer"
+#define PXA2XX_TIMER(obj) \
+ OBJECT_CHECK(PXA2xxTimerInfo, (obj), TYPE_PXA2XX_TIMER)
+
typedef struct PXA2xxTimerInfo PXA2xxTimerInfo;
typedef struct {
@@ -80,7 +84,8 @@
} PXA2xxTimer4;
struct PXA2xxTimerInfo {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem;
uint32_t flags;
@@ -118,7 +123,7 @@
for (i = 0; i < 4; i ++) {
new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
get_ticks_per_sec(), s->freq);
- qemu_mod_timer(s->timer[i].qtimer, new_qemu);
+ timer_mod(s->timer[i].qtimer, new_qemu);
}
}
@@ -136,7 +141,7 @@
counter = counters[n];
if (!s->tm4[counter].freq) {
- qemu_del_timer(s->tm4[n].tm.qtimer);
+ timer_del(s->tm4[n].tm.qtimer);
return;
}
@@ -146,7 +151,7 @@
new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
get_ticks_per_sec(), s->tm4[counter].freq);
- qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
+ timer_mod(s->tm4[n].tm.qtimer, new_qemu);
}
static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset,
@@ -183,7 +188,7 @@
goto badreg;
return s->tm4[tm].tm.value;
case OSCR:
- return s->clock + muldiv64(qemu_get_clock_ns(vm_clock) -
+ return s->clock + muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
s->lastload, s->freq, get_ticks_per_sec());
case OSCR11: tm ++;
/* fall through */
@@ -206,7 +211,7 @@
if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
if (s->tm4[tm - 1].freq)
s->snapshot = s->tm4[tm - 1].clock + muldiv64(
- qemu_get_clock_ns(vm_clock) -
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
s->tm4[tm - 1].lastload,
s->tm4[tm - 1].freq, get_ticks_per_sec());
else
@@ -215,7 +220,7 @@
if (!s->tm4[tm].freq)
return s->tm4[tm].clock;
- return s->tm4[tm].clock + muldiv64(qemu_get_clock_ns(vm_clock) -
+ return s->tm4[tm].clock + muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
case OIER:
return s->irq_enabled;
@@ -266,7 +271,7 @@
/* fall through */
case OSMR0:
s->timer[tm].value = value;
- pxa2xx_timer_update(s, qemu_get_clock_ns(vm_clock));
+ pxa2xx_timer_update(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
break;
case OSMR11: tm ++;
/* fall through */
@@ -286,11 +291,11 @@
if (!pxa2xx_timer_has_tm4(s))
goto badreg;
s->tm4[tm].tm.value = value;
- pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
+ pxa2xx_timer_update4(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tm);
break;
case OSCR:
s->oldclock = s->clock;
- s->lastload = qemu_get_clock_ns(vm_clock);
+ s->lastload = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->clock = value;
pxa2xx_timer_update(s, s->lastload);
break;
@@ -312,7 +317,7 @@
if (!pxa2xx_timer_has_tm4(s))
goto badreg;
s->tm4[tm].oldclock = s->tm4[tm].clock;
- s->tm4[tm].lastload = qemu_get_clock_ns(vm_clock);
+ s->tm4[tm].lastload = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->tm4[tm].clock = value;
pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
break;
@@ -346,7 +351,7 @@
s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
else {
s->tm4[tm].freq = 0;
- pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
+ pxa2xx_timer_update4(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tm);
}
break;
case OMCR11: tm ++;
@@ -365,7 +370,7 @@
pxa2xx_timer4_freq[(value & (1 << 8)) ? 0 : (value & 7)];
else {
s->tm4[tm].freq = 0;
- pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
+ pxa2xx_timer_update4(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tm);
}
break;
default:
@@ -406,7 +411,7 @@
if (t->control & (1 << 3))
t->clock = 0;
if (t->control & (1 << 6))
- pxa2xx_timer_update4(i, qemu_get_clock_ns(vm_clock), t->tm.num - 4);
+ pxa2xx_timer_update4(i, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), t->tm.num - 4);
if (i->events & 0xff0)
qemu_irq_raise(i->irq4);
}
@@ -417,7 +422,7 @@
int64_t now;
int i;
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
pxa2xx_timer_update(s, now);
if (pxa2xx_timer_has_tm4(s))
@@ -429,14 +434,13 @@
static int pxa2xx_timer_init(SysBusDevice *dev)
{
+ PXA2xxTimerInfo *s = PXA2XX_TIMER(dev);
int i;
- PXA2xxTimerInfo *s;
- s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
s->irq_enabled = 0;
s->oldclock = 0;
s->clock = 0;
- s->lastload = qemu_get_clock_ns(vm_clock);
+ s->lastload = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
s->reset3 = 0;
for (i = 0; i < 4; i ++) {
@@ -444,7 +448,7 @@
sysbus_init_irq(dev, &s->timer[i].irq);
s->timer[i].info = s;
s->timer[i].num = i;
- s->timer[i].qtimer = qemu_new_timer_ns(vm_clock,
+ s->timer[i].qtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
pxa2xx_timer_tick, &s->timer[i]);
}
if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
@@ -456,7 +460,7 @@
s->tm4[i].tm.num = i + 4;
s->tm4[i].freq = 0;
s->tm4[i].control = 0x0;
- s->tm4[i].tm.qtimer = qemu_new_timer_ns(vm_clock,
+ s->tm4[i].tm.qtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
pxa2xx_timer_tick4, &s->tm4[i]);
}
}
@@ -527,24 +531,21 @@
static Property pxa25x_timer_dev_properties[] = {
DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
- PXA2XX_TIMER_HAVE_TM4, false),
+ PXA2XX_TIMER_HAVE_TM4, false),
DEFINE_PROP_END_OF_LIST(),
};
static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = pxa2xx_timer_init;
dc->desc = "PXA25x timer";
- dc->vmsd = &vmstate_pxa2xx_timer_regs;
dc->props = pxa25x_timer_dev_properties;
}
static const TypeInfo pxa25x_timer_dev_info = {
.name = "pxa25x-timer",
- .parent = TYPE_SYS_BUS_DEVICE,
+ .parent = TYPE_PXA2XX_TIMER,
.instance_size = sizeof(PXA2xxTimerInfo),
.class_init = pxa25x_timer_dev_class_init,
};
@@ -552,30 +553,45 @@
static Property pxa27x_timer_dev_properties[] = {
DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
- PXA2XX_TIMER_HAVE_TM4, true),
+ PXA2XX_TIMER_HAVE_TM4, true),
DEFINE_PROP_END_OF_LIST(),
};
static void pxa27x_timer_dev_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = pxa2xx_timer_init;
dc->desc = "PXA27x timer";
- dc->vmsd = &vmstate_pxa2xx_timer_regs;
dc->props = pxa27x_timer_dev_properties;
}
static const TypeInfo pxa27x_timer_dev_info = {
.name = "pxa27x-timer",
- .parent = TYPE_SYS_BUS_DEVICE,
+ .parent = TYPE_PXA2XX_TIMER,
.instance_size = sizeof(PXA2xxTimerInfo),
.class_init = pxa27x_timer_dev_class_init,
};
+static void pxa2xx_timer_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(oc);
+
+ sdc->init = pxa2xx_timer_init;
+ dc->vmsd = &vmstate_pxa2xx_timer_regs;
+}
+
+static const TypeInfo pxa2xx_timer_type_info = {
+ .name = TYPE_PXA2XX_TIMER,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PXA2xxTimerInfo),
+ .abstract = true,
+ .class_init = pxa2xx_timer_class_init,
+};
+
static void pxa2xx_timer_register_types(void)
{
+ type_register_static(&pxa2xx_timer_type_info);
type_register_static(&pxa25x_timer_dev_info);
type_register_static(&pxa27x_timer_dev_info);
}
diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c
index 251a10d..07f0670 100644
--- a/hw/timer/sh_timer.c
+++ b/hw/timer/sh_timer.c
@@ -11,6 +11,7 @@
#include "hw/hw.h"
#include "hw/sh4/sh.h"
#include "qemu/timer.h"
+#include "qemu/main-loop.h"
#include "exec/address-spaces.h"
#include "hw/ptimer.h"
diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c
index 7f844d7..f75b914 100644
--- a/hw/timer/slavio_timer.c
+++ b/hw/timer/slavio_timer.c
@@ -27,6 +27,7 @@
#include "hw/ptimer.h"
#include "hw/sysbus.h"
#include "trace.h"
+#include "qemu/main-loop.h"
/*
* Registers of hardware timer in sun4m.
@@ -54,8 +55,13 @@
uint64_t limit;
} CPUTimerState;
+#define TYPE_SLAVIO_TIMER "slavio_timer"
+#define SLAVIO_TIMER(obj) \
+ OBJECT_CHECK(SLAVIO_TIMERState, (obj), TYPE_SLAVIO_TIMER)
+
typedef struct SLAVIO_TIMERState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
uint32_t num_cpus;
uint32_t cputimer_mode;
CPUTimerState cputimer[MAX_CPUS + 1];
@@ -354,7 +360,7 @@
static void slavio_timer_reset(DeviceState *d)
{
- SLAVIO_TIMERState *s = container_of(d, SLAVIO_TIMERState, busdev.qdev);
+ SLAVIO_TIMERState *s = SLAVIO_TIMER(d);
unsigned int i;
CPUTimerState *curr_timer;
@@ -375,7 +381,7 @@
static int slavio_timer_init1(SysBusDevice *dev)
{
- SLAVIO_TIMERState *s = FROM_SYSBUS(SLAVIO_TIMERState, dev);
+ SLAVIO_TIMERState *s = SLAVIO_TIMER(dev);
QEMUBH *bh;
unsigned int i;
TimerContext *tc;
@@ -421,7 +427,7 @@
}
static const TypeInfo slavio_timer_info = {
- .name = "slavio_timer",
+ .name = TYPE_SLAVIO_TIMER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SLAVIO_TIMERState),
.class_init = slavio_timer_class_init,
diff --git a/hw/timer/tusb6010.c b/hw/timer/tusb6010.c
index 47b6809..bd2a89e 100644
--- a/hw/timer/tusb6010.c
+++ b/hw/timer/tusb6010.c
@@ -26,8 +26,12 @@
#include "hw/devices.h"
#include "hw/sysbus.h"
+#define TYPE_TUSB6010 "tusb6010"
+#define TUSB(obj) OBJECT_CHECK(TUSBState, (obj), TYPE_TUSB6010)
+
typedef struct TUSBState {
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion iomem[2];
qemu_irq irq;
MUSBState *musb;
@@ -512,11 +516,11 @@
case TUSB_DEV_OTG_TIMER:
s->otg_timer_val = value;
if (value & TUSB_DEV_OTG_TIMER_ENABLE)
- qemu_mod_timer(s->otg_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(s->otg_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
muldiv64(TUSB_DEV_OTG_TIMER_VAL(value),
get_ticks_per_sec(), TUSB_DEVCLOCK));
else
- qemu_del_timer(s->otg_timer);
+ timer_del(s->otg_timer);
break;
case TUSB_PRCM_CONF:
@@ -724,8 +728,8 @@
/* Pull the interrupt down after TUSB6010 comes up. */
s->intr_ok = 0;
tusb_intr_update(s);
- qemu_mod_timer(s->pwr_timer,
- qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 2);
+ timer_mod(s->pwr_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + get_ticks_per_sec() / 2);
}
}
@@ -740,7 +744,7 @@
static void tusb6010_reset(DeviceState *dev)
{
- TUSBState *s = FROM_SYSBUS(TUSBState, SYS_BUS_DEVICE(dev));
+ TUSBState *s = TUSB(dev);
int i;
s->test_reset = TUSB_PROD_TEST_RESET_VAL;
@@ -774,18 +778,20 @@
musb_reset(s->musb);
}
-static int tusb6010_init(SysBusDevice *dev)
+static int tusb6010_init(SysBusDevice *sbd)
{
- TUSBState *s = FROM_SYSBUS(TUSBState, dev);
- s->otg_timer = qemu_new_timer_ns(vm_clock, tusb_otg_tick, s);
- s->pwr_timer = qemu_new_timer_ns(vm_clock, tusb_power_tick, s);
+ DeviceState *dev = DEVICE(sbd);
+ TUSBState *s = TUSB(dev);
+
+ s->otg_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tusb_otg_tick, s);
+ s->pwr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tusb_power_tick, s);
memory_region_init_io(&s->iomem[1], OBJECT(s), &tusb_async_ops, s,
"tusb-async", UINT32_MAX);
- sysbus_init_mmio(dev, &s->iomem[0]);
- sysbus_init_mmio(dev, &s->iomem[1]);
- sysbus_init_irq(dev, &s->irq);
- qdev_init_gpio_in(&dev->qdev, tusb6010_irq, musb_irq_max + 1);
- s->musb = musb_init(&dev->qdev, 1);
+ sysbus_init_mmio(sbd, &s->iomem[0]);
+ sysbus_init_mmio(sbd, &s->iomem[1]);
+ sysbus_init_irq(sbd, &s->irq);
+ qdev_init_gpio_in(dev, tusb6010_irq, musb_irq_max + 1);
+ s->musb = musb_init(dev, 1);
return 0;
}
@@ -799,7 +805,7 @@
}
static const TypeInfo tusb6010_info = {
- .name = "tusb6010",
+ .name = TYPE_TUSB6010,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(TUSBState),
.class_init = tusb6010_class_init,
diff --git a/hw/timer/twl92230.c b/hw/timer/twl92230.c
index b730d85..f3ea365 100644
--- a/hw/timer/twl92230.c
+++ b/hw/timer/twl92230.c
@@ -72,14 +72,14 @@
static inline void menelaus_rtc_start(MenelausState *s)
{
- s->rtc.next += qemu_get_clock_ms(rtc_clock);
- qemu_mod_timer(s->rtc.hz_tm, s->rtc.next);
+ s->rtc.next += qemu_clock_get_ms(rtc_clock);
+ timer_mod(s->rtc.hz_tm, s->rtc.next);
}
static inline void menelaus_rtc_stop(MenelausState *s)
{
- qemu_del_timer(s->rtc.hz_tm);
- s->rtc.next -= qemu_get_clock_ms(rtc_clock);
+ timer_del(s->rtc.hz_tm);
+ s->rtc.next -= qemu_clock_get_ms(rtc_clock);
if (s->rtc.next < 1)
s->rtc.next = 1;
}
@@ -102,7 +102,7 @@
s->rtc.next_comp --;
s->rtc.alm_sec --;
s->rtc.next += 1000;
- qemu_mod_timer(s->rtc.hz_tm, s->rtc.next);
+ timer_mod(s->rtc.hz_tm, s->rtc.next);
if ((s->rtc.ctrl >> 3) & 3) { /* EVERY */
menelaus_rtc_update(s);
if (((s->rtc.ctrl >> 3) & 3) == 1 && !s->rtc.tm.tm_sec)
@@ -782,7 +782,7 @@
{
MenelausState *s = opaque;
/* Should be <= 1000 */
- s->rtc_next_vmstate = s->rtc.next - qemu_get_clock_ms(rtc_clock);
+ s->rtc_next_vmstate = s->rtc.next - qemu_clock_get_ms(rtc_clock);
}
static int menelaus_post_load(void *opaque, int version_id)
@@ -843,7 +843,7 @@
{
MenelausState *s = FROM_I2C_SLAVE(MenelausState, i2c);
- s->rtc.hz_tm = qemu_new_timer_ms(rtc_clock, menelaus_rtc_hz, s);
+ s->rtc.hz_tm = timer_new_ms(rtc_clock, menelaus_rtc_hz, s);
/* Three output pins plus one interrupt pin. */
qdev_init_gpio_out(&i2c->qdev, s->out, 4);
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
index ee53834..6113b97 100644
--- a/hw/timer/xilinx_timer.c
+++ b/hw/timer/xilinx_timer.c
@@ -25,6 +25,7 @@
#include "hw/sysbus.h"
#include "hw/ptimer.h"
#include "qemu/log.h"
+#include "qemu/main-loop.h"
#define D(x)
@@ -57,9 +58,14 @@
uint32_t regs[R_MAX];
};
+#define TYPE_XILINX_TIMER "xlnx.xps-timer"
+#define XILINX_TIMER(obj) \
+ OBJECT_CHECK(struct timerblock, (obj), TYPE_XILINX_TIMER)
+
struct timerblock
{
- SysBusDevice busdev;
+ SysBusDevice parent_obj;
+
MemoryRegion mmio;
qemu_irq irq;
uint8_t one_timer_only;
@@ -200,7 +206,7 @@
static int xilinx_timer_init(SysBusDevice *dev)
{
- struct timerblock *t = FROM_SYSBUS(typeof (*t), dev);
+ struct timerblock *t = XILINX_TIMER(dev);
unsigned int i;
/* All timers share a single irq line. */
@@ -241,7 +247,7 @@
}
static const TypeInfo xilinx_timer_info = {
- .name = "xlnx.xps-timer",
+ .name = TYPE_XILINX_TIMER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct timerblock),
.class_init = xilinx_timer_class_init,
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index abe384b..6f0a4d2 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -28,6 +28,7 @@
#include "hw/pci/pci_ids.h"
#include "tpm_tis.h"
#include "qemu-common.h"
+#include "qemu/main-loop.h"
/*#define DEBUG_TIS */
diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c
index deb6d47..aa913df 100644
--- a/hw/usb/ccid-card-emulated.c
+++ b/hw/usb/ccid-card-emulated.c
@@ -592,6 +592,7 @@
cc->exitfn = emulated_exitfn;
cc->get_atr = emulated_get_atr;
cc->apdu_from_guest = emulated_apdu_from_guest;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->desc = "emulated smartcard";
dc->props = emulated_card_properties;
}
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 5f01ff1..10f1d30 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -392,6 +392,7 @@
cc->exitfn = passthru_exitfn;
cc->get_atr = passthru_get_atr;
cc->apdu_from_guest = passthru_apdu_from_guest;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->desc = "passthrough smartcard";
dc->vmsd = &passthru_vmstate;
dc->props = passthru_card_properties;
diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index 04933a9..c5420eb 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -673,6 +673,7 @@
dc->vmsd = &vmstate_usb_audio;
dc->props = usb_audio_properties;
+ set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
k->product_desc = "QEMU USB Audio Interface";
k->usb_desc = &desc_audio;
k->init = usb_audio_initfn;
diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
index 68cc1d4..f2fc2a8 100644
--- a/hw/usb/dev-bluetooth.c
+++ b/hw/usb/dev-bluetooth.c
@@ -553,6 +553,7 @@
uc->handle_data = usb_bt_handle_data;
uc->handle_destroy = usb_bt_handle_destroy;
dc->vmsd = &vmstate_usb_bt;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
}
static const TypeInfo bt_info = {
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index 31f3cde..66c6331 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -658,6 +658,7 @@
uc->product_desc = "QEMU USB Tablet";
dc->vmsd = &vmstate_usb_ptr;
dc->props = usb_tablet_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo usb_tablet_info = {
@@ -677,6 +678,7 @@
uc->product_desc = "QEMU USB Mouse";
uc->usb_desc = &desc_mouse;
dc->vmsd = &vmstate_usb_ptr;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo usb_mouse_info = {
@@ -696,6 +698,7 @@
uc->product_desc = "QEMU USB Keyboard";
uc->usb_desc = &desc_keyboard;
dc->vmsd = &vmstate_usb_kbd;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo usb_keyboard_info = {
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 0b71abd..e865a98 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -574,6 +574,7 @@
uc->handle_control = usb_hub_handle_control;
uc->handle_data = usb_hub_handle_data;
uc->handle_destroy = usb_hub_handle_destroy;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->fw_name = "hub";
dc->vmsd = &vmstate_usb_hub;
}
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 5473ac2..660d774 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1429,6 +1429,7 @@
uc->handle_control = usb_net_handle_control;
uc->handle_data = usb_net_handle_data;
uc->handle_destroy = usb_net_handle_destroy;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
dc->fw_name = "network";
dc->vmsd = &vmstate_usb_net;
dc->props = net_properties;
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 2fc8a3b..0b150d4 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -590,6 +590,7 @@
uc->handle_data = usb_serial_handle_data;
dc->vmsd = &vmstate_usb_serial;
dc->props = serial_properties;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo serial_info = {
@@ -617,6 +618,7 @@
uc->handle_data = usb_serial_handle_data;
dc->vmsd = &vmstate_usb_serial;
dc->props = braille_properties;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo braille_info = {
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index b33eb25..2233c54 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1449,6 +1449,7 @@
dc->desc = "CCID Rev 1.1 smartcard reader";
dc->vmsd = &ccid_vmstate;
dc->props = ccid_properties;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo ccid_info = {
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 1954811..a8dc2fa 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -746,6 +746,7 @@
uc->handle_reset = usb_msd_handle_reset;
uc->handle_control = usb_msd_handle_control;
uc->handle_data = usb_msd_handle_data;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->fw_name = "storage";
dc->vmsd = &vmstate_usb_msd;
}
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 6efab62..63ad12e 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -916,6 +916,7 @@
uc->handle_control = usb_uas_handle_control;
uc->handle_data = usb_uas_handle_data;
uc->handle_destroy = usb_uas_handle_destroy;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->fw_name = "storage";
dc->vmsd = &vmstate_usb_uas;
}
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index 3be5cde..1b09235 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -362,6 +362,7 @@
uc->handle_control = usb_wacom_handle_control;
uc->handle_data = usb_wacom_handle_data;
uc->handle_destroy = usb_wacom_handle_destroy;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->desc = "QEMU PenPartner Tablet";
dc->vmsd = &vmstate_usb_wacom;
}
diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index 5d229bc..4d21a0b 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -140,11 +140,13 @@
static void ehci_data_class_init(ObjectClass *klass, void *data)
{
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
EHCIPCIInfo *i = data;
k->vendor_id = i->vendor_id;
k->device_id = i->device_id;
k->revision = i->revision;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
}
static struct EHCIPCIInfo ehci_pci_info[] = {
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
index 54147b5..fe6eea5 100644
--- a/hw/usb/hcd-ehci-sysbus.c
+++ b/hw/usb/hcd-ehci-sysbus.c
@@ -70,6 +70,7 @@
dc->realize = usb_ehci_sysbus_realize;
dc->vmsd = &vmstate_ehci_sysbus;
dc->props = ehci_sysbus_properties;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
}
static const TypeInfo ehci_type_info = {
@@ -85,7 +86,9 @@
static void ehci_xlnx_class_init(ObjectClass *oc, void *data)
{
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
sec->capsbase = 0x100;
sec->opregbase = 0x140;
}
@@ -99,9 +102,11 @@
static void ehci_exynos4210_class_init(ObjectClass *oc, void *data)
{
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
sec->capsbase = 0x0;
sec->opregbase = 0x10;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
}
static const TypeInfo ehci_exynos4210_type_info = {
@@ -113,9 +118,11 @@
static void ehci_tegra2_class_init(ObjectClass *oc, void *data)
{
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
sec->capsbase = 0x100;
sec->opregbase = 0x140;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
}
static const TypeInfo ehci_tegra2_type_info = {
@@ -183,11 +190,13 @@
static void fusbh200_ehci_class_init(ObjectClass *oc, void *data)
{
SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
sec->capsbase = 0x0;
sec->opregbase = 0x10;
sec->portscbase = 0x20;
sec->portnr = 1;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
}
static const TypeInfo ehci_fusbh200_type_info = {
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 67e4b24..e5523d5 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -150,7 +150,7 @@
#define NLPTR_TYPE_FSTN 3 // frame span traversal node
#define SET_LAST_RUN_CLOCK(s) \
- (s)->last_run_ns = qemu_get_clock_ns(vm_clock);
+ (s)->last_run_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
/* nifty macros from Arnon's EHCI version */
#define get_field(data, field) \
@@ -958,7 +958,7 @@
}
ehci_queues_rip_all(s, 0);
ehci_queues_rip_all(s, 1);
- qemu_del_timer(s->frame_timer);
+ timer_del(s->frame_timer);
qemu_bh_cancel(s->async_bh);
}
@@ -1357,7 +1357,7 @@
default:
/* should not be triggerable */
fprintf(stderr, "USB invalid response %d\n", p->packet.status);
- assert(0);
+ g_assert_not_reached();
break;
}
@@ -2142,7 +2142,7 @@
default:
fprintf(stderr, "Bad state!\n");
again = -1;
- assert(0);
+ g_assert_not_reached();
break;
}
@@ -2206,7 +2206,7 @@
/* this should only be due to a developer mistake */
fprintf(stderr, "ehci: Bad asynchronous state %d. "
"Resetting to active\n", ehci->astate);
- assert(0);
+ g_assert_not_reached();
}
}
@@ -2256,7 +2256,7 @@
/* this should only be due to a developer mistake */
fprintf(stderr, "ehci: Bad periodic state %d. "
"Resetting to active\n", ehci->pstate);
- assert(0);
+ g_assert_not_reached();
}
}
@@ -2296,7 +2296,7 @@
int uframes, skipped_uframes;
int i;
- t_now = qemu_get_clock_ns(vm_clock);
+ t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ns_elapsed = t_now - ehci->last_run_ns;
uframes = ns_elapsed / UFRAME_TIMER_NS;
@@ -2374,7 +2374,7 @@
expire_time = t_now + (get_ticks_per_sec()
* (ehci->async_stepdown+1) / FRAME_TIMER_FREQ);
}
- qemu_mod_timer(ehci->frame_timer, expire_time);
+ timer_mod(ehci->frame_timer, expire_time);
}
}
@@ -2527,7 +2527,7 @@
s->ports[i].dev = 0;
}
- s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
+ s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ehci_frame_timer, s);
s->async_bh = qemu_bh_new(ehci_frame_timer, s);
qemu_register_reset(ehci_reset, s);
diff --git a/hw/usb/hcd-musb.c b/hw/usb/hcd-musb.c
index 7968e17..f91aa55 100644
--- a/hw/usb/hcd-musb.c
+++ b/hw/usb/hcd-musb.c
@@ -558,9 +558,9 @@
return musb_cb_tick(ep);
if (!ep->intv_timer[dir])
- ep->intv_timer[dir] = qemu_new_timer_ns(vm_clock, musb_cb_tick, ep);
+ ep->intv_timer[dir] = timer_new_ns(QEMU_CLOCK_VIRTUAL, musb_cb_tick, ep);
- qemu_mod_timer(ep->intv_timer[dir], qemu_get_clock_ns(vm_clock) +
+ timer_mod(ep->intv_timer[dir], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
muldiv64(timeout, get_ticks_per_sec(), 8000));
}
@@ -962,7 +962,7 @@
static void musb_ep_frame_cancel(MUSBEndPoint *ep, int dir)
{
if (ep->intv_timer[dir])
- qemu_del_timer(ep->intv_timer[dir]);
+ timer_del(ep->intv_timer[dir]);
}
/* Bus control */
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 2bab8ff..39a25a7 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -22,7 +22,6 @@
* o Allocate bandwidth in frames properly
* o Disable timers when nothing needs to be done, or remove timer usage
* all together.
- * o Handle unrecoverable errors properly
* o BIOS work to boot from USB storage
*/
@@ -308,6 +307,8 @@
#define OHCI_HRESET_FSBIR (1 << 0)
+static void ohci_die(OHCIState *ohci);
+
/* Update IRQ levels */
static inline void ohci_intr_update(OHCIState *ohci)
{
@@ -508,11 +509,13 @@
addr += ohci->localmem_base;
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
- dma_memory_read(ohci->as, addr, buf, sizeof(*buf));
+ if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) {
+ return -1;
+ }
*buf = le32_to_cpu(*buf);
}
- return 1;
+ return 0;
}
/* Put an array of dwords in to main memory */
@@ -525,10 +528,12 @@
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
uint32_t tmp = cpu_to_le32(*buf);
- dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp));
+ if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) {
+ return -1;
+ }
}
- return 1;
+ return 0;
}
/* Get an array of words from main memory */
@@ -540,11 +545,13 @@
addr += ohci->localmem_base;
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
- dma_memory_read(ohci->as, addr, buf, sizeof(*buf));
+ if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) {
+ return -1;
+ }
*buf = le16_to_cpu(*buf);
}
- return 1;
+ return 0;
}
/* Put an array of words in to main memory */
@@ -557,10 +564,12 @@
for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) {
uint16_t tmp = cpu_to_le16(*buf);
- dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp));
+ if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) {
+ return -1;
+ }
}
- return 1;
+ return 0;
}
static inline int ohci_read_ed(OHCIState *ohci,
@@ -578,15 +587,15 @@
static inline int ohci_read_iso_td(OHCIState *ohci,
dma_addr_t addr, struct ohci_iso_td *td)
{
- return (get_dwords(ohci, addr, (uint32_t *)td, 4) &&
- get_words(ohci, addr + 16, td->offset, 8));
+ return get_dwords(ohci, addr, (uint32_t *)td, 4) ||
+ get_words(ohci, addr + 16, td->offset, 8);
}
static inline int ohci_read_hcca(OHCIState *ohci,
dma_addr_t addr, struct ohci_hcca *hcca)
{
- dma_memory_read(ohci->as, addr + ohci->localmem_base, hcca, sizeof(*hcca));
- return 1;
+ return dma_memory_read(ohci->as, addr + ohci->localmem_base,
+ hcca, sizeof(*hcca));
}
static inline int ohci_put_ed(OHCIState *ohci,
@@ -610,23 +619,22 @@
static inline int ohci_put_iso_td(OHCIState *ohci,
dma_addr_t addr, struct ohci_iso_td *td)
{
- return (put_dwords(ohci, addr, (uint32_t *)td, 4) &&
- put_words(ohci, addr + 16, td->offset, 8));
+ return put_dwords(ohci, addr, (uint32_t *)td, 4 ||
+ put_words(ohci, addr + 16, td->offset, 8));
}
static inline int ohci_put_hcca(OHCIState *ohci,
dma_addr_t addr, struct ohci_hcca *hcca)
{
- dma_memory_write(ohci->as,
- addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
- (char *)hcca + HCCA_WRITEBACK_OFFSET,
- HCCA_WRITEBACK_SIZE);
- return 1;
+ return dma_memory_write(ohci->as,
+ addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET,
+ (char *)hcca + HCCA_WRITEBACK_OFFSET,
+ HCCA_WRITEBACK_SIZE);
}
/* Read/Write the contents of a TD from/to main memory. */
-static void ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
- uint8_t *buf, int len, DMADirection dir)
+static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td,
+ uint8_t *buf, int len, DMADirection dir)
{
dma_addr_t ptr, n;
@@ -634,18 +642,26 @@
n = 0x1000 - (ptr & 0xfff);
if (n > len)
n = len;
- dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir);
- if (n == len)
- return;
+
+ if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) {
+ return -1;
+ }
+ if (n == len) {
+ return 0;
+ }
ptr = td->be & ~0xfffu;
buf += n;
- dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, len - n, dir);
+ if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
+ len - n, dir)) {
+ return -1;
+ }
+ return 0;
}
/* Read/Write the contents of an ISO TD from/to main memory. */
-static void ohci_copy_iso_td(OHCIState *ohci,
- uint32_t start_addr, uint32_t end_addr,
- uint8_t *buf, int len, DMADirection dir)
+static int ohci_copy_iso_td(OHCIState *ohci,
+ uint32_t start_addr, uint32_t end_addr,
+ uint8_t *buf, int len, DMADirection dir)
{
dma_addr_t ptr, n;
@@ -653,12 +669,20 @@
n = 0x1000 - (ptr & 0xfff);
if (n > len)
n = len;
- dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir);
- if (n == len)
- return;
+
+ if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) {
+ return -1;
+ }
+ if (n == len) {
+ return 0;
+ }
ptr = end_addr & ~0xfffu;
buf += n;
- dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, len - n, dir);
+ if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf,
+ len - n, dir)) {
+ return -1;
+ }
+ return 0;
}
static void ohci_process_lists(OHCIState *ohci, int completion);
@@ -698,8 +722,9 @@
addr = ed->head & OHCI_DPTR_MASK;
- if (!ohci_read_iso_td(ohci, addr, &iso_td)) {
+ if (ohci_read_iso_td(ohci, addr, &iso_td)) {
printf("usb-ohci: ISO_TD read error at %x\n", addr);
+ ohci_die(ohci);
return 0;
}
@@ -740,7 +765,10 @@
i = OHCI_BM(iso_td.flags, TD_DI);
if (i < ohci->done_count)
ohci->done_count = i;
- ohci_put_iso_td(ohci, addr, &iso_td);
+ if (ohci_put_iso_td(ohci, addr, &iso_td)) {
+ ohci_die(ohci);
+ return 1;
+ }
return 0;
}
@@ -821,8 +849,11 @@
}
if (len && dir != OHCI_TD_DIR_IN) {
- ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len,
- DMA_DIRECTION_TO_DEVICE);
+ if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, len,
+ DMA_DIRECTION_TO_DEVICE)) {
+ ohci_die(ohci);
+ return 1;
+ }
}
if (!completion) {
@@ -852,8 +883,11 @@
/* Writeback */
if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) {
/* IN transfer succeeded */
- ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret,
- DMA_DIRECTION_FROM_DEVICE);
+ if (ohci_copy_iso_td(ohci, start_addr, end_addr, ohci->usb_buf, ret,
+ DMA_DIRECTION_FROM_DEVICE)) {
+ ohci_die(ohci);
+ return 1;
+ }
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC,
OHCI_CC_NOERROR);
OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret);
@@ -910,7 +944,9 @@
if (i < ohci->done_count)
ohci->done_count = i;
}
- ohci_put_iso_td(ohci, addr, &iso_td);
+ if (ohci_put_iso_td(ohci, addr, &iso_td)) {
+ ohci_die(ohci);
+ }
return 1;
}
@@ -943,8 +979,9 @@
#endif
return 1;
}
- if (!ohci_read_td(ohci, addr, &td)) {
+ if (ohci_read_td(ohci, addr, &td)) {
fprintf(stderr, "usb-ohci: TD read error at %x\n", addr);
+ ohci_die(ohci);
return 0;
}
@@ -997,8 +1034,10 @@
pktlen = len;
}
if (!completion) {
- ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen,
- DMA_DIRECTION_TO_DEVICE);
+ if (ohci_copy_td(ohci, &td, ohci->usb_buf, pktlen,
+ DMA_DIRECTION_TO_DEVICE)) {
+ ohci_die(ohci);
+ }
}
}
}
@@ -1055,8 +1094,10 @@
if (ret >= 0) {
if (dir == OHCI_TD_DIR_IN) {
- ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
- DMA_DIRECTION_FROM_DEVICE);
+ if (ohci_copy_td(ohci, &td, ohci->usb_buf, ret,
+ DMA_DIRECTION_FROM_DEVICE)) {
+ ohci_die(ohci);
+ }
#ifdef DEBUG_PACKET
DPRINTF(" data:");
for (i = 0; i < ret; i++)
@@ -1133,7 +1174,10 @@
if (i < ohci->done_count)
ohci->done_count = i;
exit_no_retire:
- ohci_put_td(ohci, addr, &td);
+ if (ohci_put_td(ohci, addr, &td)) {
+ ohci_die(ohci);
+ return 1;
+ }
return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR;
}
@@ -1151,8 +1195,9 @@
return 0;
for (cur = head; cur; cur = next_ed) {
- if (!ohci_read_ed(ohci, cur, &ed)) {
+ if (ohci_read_ed(ohci, cur, &ed)) {
fprintf(stderr, "usb-ohci: ED read error at %x\n", cur);
+ ohci_die(ohci);
return 0;
}
@@ -1194,7 +1239,10 @@
}
}
- ohci_put_ed(ohci, cur, &ed);
+ if (ohci_put_ed(ohci, cur, &ed)) {
+ ohci_die(ohci);
+ return 0;
+ }
}
return active;
@@ -1203,8 +1251,8 @@
/* Generate a SOF event, and set a timer for EOF */
static void ohci_sof(OHCIState *ohci)
{
- ohci->sof_time = qemu_get_clock_ns(vm_clock);
- qemu_mod_timer(ohci->eof_timer, ohci->sof_time + usb_frame_time);
+ ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time);
ohci_set_interrupt(ohci, OHCI_INTR_SF);
}
@@ -1236,7 +1284,11 @@
OHCIState *ohci = opaque;
struct ohci_hcca hcca;
- ohci_read_hcca(ohci, ohci->hcca, &hcca);
+ if (ohci_read_hcca(ohci, ohci->hcca, &hcca)) {
+ fprintf(stderr, "usb-ohci: HCCA read error at %x\n", ohci->hcca);
+ ohci_die(ohci);
+ return;
+ }
/* Process all the lists at the end of the frame */
if (ohci->ctl & OHCI_CTL_PLE) {
@@ -1257,6 +1309,11 @@
ohci->old_ctl = ohci->ctl;
ohci_process_lists(ohci, 0);
+ /* Stop if UnrecoverableError happened or ohci_sof will crash */
+ if (ohci->intr_status & OHCI_INTR_UE) {
+ return;
+ }
+
/* Frame boundary, so do EOF stuf here */
ohci->frt = ohci->fit;
@@ -1282,7 +1339,9 @@
ohci_sof(ohci);
/* Writeback HCCA */
- ohci_put_hcca(ohci, ohci->hcca, &hcca);
+ if (ohci_put_hcca(ohci, ohci->hcca, &hcca)) {
+ ohci_die(ohci);
+ }
}
/* Start sending SOF tokens across the USB bus, lists are processed in
@@ -1290,13 +1349,13 @@
*/
static int ohci_bus_start(OHCIState *ohci)
{
- ohci->eof_timer = qemu_new_timer_ns(vm_clock,
+ ohci->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
ohci_frame_boundary,
ohci);
if (ohci->eof_timer == NULL) {
- fprintf(stderr, "usb-ohci: %s: qemu_new_timer_ns failed\n", ohci->name);
- /* TODO: Signal unrecoverable error */
+ fprintf(stderr, "usb-ohci: %s: timer_new_ns failed\n", ohci->name);
+ ohci_die(ohci);
return 0;
}
@@ -1311,7 +1370,7 @@
static void ohci_bus_stop(OHCIState *ohci)
{
if (ohci->eof_timer)
- qemu_del_timer(ohci->eof_timer);
+ timer_del(ohci->eof_timer);
ohci->eof_timer = NULL;
}
@@ -1415,7 +1474,7 @@
/* Being in USB operational state guarnatees sof_time was
* set already.
*/
- tks = qemu_get_clock_ns(vm_clock) - ohci->sof_time;
+ tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time;
/* avoid muldiv if possible */
if (tks >= usb_frame_time)
@@ -1857,6 +1916,22 @@
uint32_t firstport;
} OHCIPCIState;
+/** A typical O/EHCI will stop operating, set itself into error state
+ * (which can be queried by MMIO) and will set PERR in its config
+ * space to signal that it got an error
+ */
+static void ohci_die(OHCIState *ohci)
+{
+ OHCIPCIState *dev = container_of(ohci, OHCIPCIState, state);
+
+ fprintf(stderr, "%s: DMA error\n", __func__);
+
+ ohci_set_interrupt(ohci, OHCI_INTR_UE);
+ ohci_bus_stop(ohci);
+ pci_set_word(dev->parent_obj.config + PCI_STATUS,
+ PCI_STATUS_DETECTED_PARITY);
+}
+
static int usb_ohci_initfn_pci(PCIDevice *dev)
{
OHCIPCIState *ohci = PCI_OHCI(dev);
@@ -1917,6 +1992,7 @@
k->device_id = PCI_DEVICE_ID_APPLE_IPID_USB;
k->class_id = PCI_CLASS_SERIAL_USB;
k->no_hotplug = 1;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
dc->desc = "Apple USB Controller";
dc->props = ohci_pci_properties;
}
@@ -1939,6 +2015,7 @@
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = ohci_realize_pxa;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
dc->desc = "OHCI USB Controller";
dc->props = ohci_sysbus_properties;
}
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 066072e..578b949 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -32,6 +32,7 @@
#include "qemu/iov.h"
#include "sysemu/dma.h"
#include "trace.h"
+#include "qemu/main-loop.h"
//#define DEBUG
//#define DEBUG_DUMP_DATA
@@ -189,6 +190,7 @@
static void uhci_async_cancel(UHCIAsync *async);
static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td);
+static void uhci_resume(void *opaque);
static inline int32_t uhci_queue_token(UHCI_TD *td)
{
@@ -431,7 +433,7 @@
UHCIState *s = opaque;
if (version_id < 2) {
- s->expire_time = qemu_get_clock_ns(vm_clock) +
+ s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
(get_ticks_per_sec() / FRAME_TIMER_FREQ);
}
return 0;
@@ -474,9 +476,9 @@
if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) {
/* start frame processing */
trace_usb_uhci_schedule_start();
- s->expire_time = qemu_get_clock_ns(vm_clock) +
+ s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
(get_ticks_per_sec() / FRAME_TIMER_FREQ);
- qemu_mod_timer(s->frame_timer, s->expire_time);
+ timer_mod(s->frame_timer, s->expire_time);
s->status &= ~UHCI_STS_HCHALTED;
} else if (!(val & UHCI_CMD_RS)) {
s->status |= UHCI_STS_HCHALTED;
@@ -498,6 +500,12 @@
return;
}
s->cmd = val;
+ if (val & UHCI_CMD_EGSM) {
+ if ((s->ports[0].ctrl & UHCI_PORT_RD) ||
+ (s->ports[1].ctrl & UHCI_PORT_RD)) {
+ uhci_resume(s);
+ }
+ }
break;
case 0x02:
s->status &= ~val;
@@ -1153,7 +1161,7 @@
if (!(s->cmd & UHCI_CMD_RS)) {
/* Full stop */
trace_usb_uhci_schedule_stop();
- qemu_del_timer(s->frame_timer);
+ timer_del(s->frame_timer);
uhci_async_cancel_all(s);
/* set hchalted bit in status - UHCI11D 2.1.2 */
s->status |= UHCI_STS_HCHALTED;
@@ -1162,7 +1170,7 @@
/* We still store expire_time in our state, for migration */
t_last_run = s->expire_time - frame_t;
- t_now = qemu_get_clock_ns(vm_clock);
+ t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
/* Process up to MAX_FRAMES_PER_TICK frames */
frames = (t_now - t_last_run) / frame_t;
@@ -1196,7 +1204,7 @@
}
s->pending_int_mask = 0;
- qemu_mod_timer(s->frame_timer, t_now + frame_t);
+ timer_mod(s->frame_timer, t_now + frame_t);
}
static const MemoryRegionOps uhci_ioport_ops = {
@@ -1253,7 +1261,7 @@
}
}
s->bh = qemu_bh_new(uhci_bh, s);
- s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
+ s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uhci_frame_timer, s);
s->num_ports_vmstate = NB_PORTS;
QTAILQ_INIT(&s->queues);
@@ -1315,6 +1323,7 @@
k->no_hotplug = 1;
dc->vmsd = &vmstate_uhci;
dc->props = uhci_properties;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
u->info = *info;
}
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 9ba3e3e..be6b86e 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -608,7 +608,7 @@
static uint64_t xhci_mfindex_get(XHCIState *xhci)
{
- int64_t now = qemu_get_clock_ns(vm_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
return (now - xhci->mfindex_start) / 125000;
}
@@ -619,12 +619,12 @@
int64_t now;
if ((xhci->usbcmd & bits) == bits) {
- now = qemu_get_clock_ns(vm_clock);
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
mfindex = ((now - xhci->mfindex_start) / 125000) & 0x3fff;
left = 0x4000 - mfindex;
- qemu_mod_timer(xhci->mfwrap_timer, now + left * 125000);
+ timer_mod(xhci->mfwrap_timer, now + left * 125000);
} else {
- qemu_del_timer(xhci->mfwrap_timer);
+ timer_del(xhci->mfwrap_timer);
}
}
@@ -1086,7 +1086,7 @@
{
trace_usb_xhci_run();
xhci->usbsts &= ~USBSTS_HCH;
- xhci->mfindex_start = qemu_get_clock_ns(vm_clock);
+ xhci->mfindex_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
static void xhci_stop(XHCIState *xhci)
@@ -1229,7 +1229,7 @@
for (i = 0; i < ARRAY_SIZE(epctx->transfers); i++) {
usb_packet_init(&epctx->transfers[i].packet);
}
- epctx->kick_timer = qemu_new_timer_ns(vm_clock, xhci_ep_kick_timer, epctx);
+ epctx->kick_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_ep_kick_timer, epctx);
return epctx;
}
@@ -1304,7 +1304,7 @@
XHCIEPContext *epctx = t->xhci->slots[t->slotid-1].eps[t->epid-1];
if (epctx) {
epctx->retry = NULL;
- qemu_del_timer(epctx->kick_timer);
+ timer_del(epctx->kick_timer);
}
t->running_retry = 0;
}
@@ -1380,7 +1380,7 @@
xhci_set_ep_state(xhci, epctx, NULL, EP_DISABLED);
- qemu_free_timer(epctx->kick_timer);
+ timer_free(epctx->kick_timer);
g_free(epctx);
slot->eps[epid-1] = NULL;
@@ -1429,7 +1429,6 @@
{
XHCISlot *slot;
XHCIEPContext *epctx;
- USBDevice *dev;
trace_usb_xhci_ep_reset(slotid, epid);
assert(slotid >= 1 && slotid <= xhci->numslots);
@@ -1465,8 +1464,8 @@
ep |= 0x80;
}
- dev = xhci->slots[slotid-1].uport->dev;
- if (!dev) {
+ if (!xhci->slots[slotid-1].uport ||
+ !xhci->slots[slotid-1].uport->dev) {
return CC_USB_TRANSACTION_ERROR;
}
@@ -1741,6 +1740,7 @@
trace_usb_xhci_xfer_error(xfer, xfer->packet.status);
switch (xfer->packet.status) {
case USB_RET_NODEV:
+ case USB_RET_IOERROR:
xfer->status = CC_USB_TRANSACTION_ERROR;
xhci_xfer_report(xfer);
xhci_stall_ep(xfer);
@@ -1844,12 +1844,12 @@
XHCIEPContext *epctx, uint64_t mfindex)
{
if (xfer->mfindex_kick > mfindex) {
- qemu_mod_timer(epctx->kick_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(epctx->kick_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
(xfer->mfindex_kick - mfindex) * 125000);
xfer->running_retry = 1;
} else {
epctx->mfindex_last = xfer->mfindex_kick;
- qemu_del_timer(epctx->kick_timer);
+ timer_del(epctx->kick_timer);
xfer->running_retry = 0;
}
}
@@ -2672,7 +2672,7 @@
xhci_port_notify(port, PORTSC_CSC);
}
-static void xhci_port_reset(XHCIPort *port)
+static void xhci_port_reset(XHCIPort *port, bool warm_reset)
{
trace_usb_xhci_port_reset(port->portnr);
@@ -2683,6 +2683,11 @@
usb_device_reset(port->uport->dev);
switch (port->uport->dev->speed) {
+ case USB_SPEED_SUPER:
+ if (warm_reset) {
+ port->portsc |= PORTSC_WRC;
+ }
+ /* fall through */
case USB_SPEED_LOW:
case USB_SPEED_FULL:
case USB_SPEED_HIGH:
@@ -2740,7 +2745,7 @@
xhci->intr[i].ev_buffer_get = 0;
}
- xhci->mfindex_start = qemu_get_clock_ns(vm_clock);
+ xhci->mfindex_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
xhci_mfwrap_update(xhci);
}
@@ -2845,8 +2850,12 @@
switch (reg) {
case 0x00: /* PORTSC */
/* write-1-to-start bits */
+ if (val & PORTSC_WPR) {
+ xhci_port_reset(port, true);
+ break;
+ }
if (val & PORTSC_PR) {
- xhci_port_reset(port);
+ xhci_port_reset(port, false);
break;
}
@@ -3357,7 +3366,7 @@
xhci->numslots = 1;
}
- xhci->mfwrap_timer = qemu_new_timer_ns(vm_clock, xhci_mfwrap_timer, xhci);
+ xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci);
xhci->irq = dev->irq[0];
@@ -3442,7 +3451,7 @@
epctx->state = state;
if (state == EP_RUNNING) {
/* kick endpoint after vmload is finished */
- qemu_mod_timer(epctx->kick_timer, qemu_get_clock_ns(vm_clock));
+ timer_mod(epctx->kick_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
}
}
}
@@ -3591,6 +3600,7 @@
dc->vmsd = &vmstate_xhci;
dc->props = xhci_properties;
dc->reset = xhci_reset;
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
k->init = usb_xhci_initfn;
k->vendor_id = PCI_VENDOR_ID_NEC;
k->device_id = PCI_DEVICE_ID_NEC_UPD720200;
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index e2f3cc8..128955d 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -1351,6 +1351,7 @@
uc->flush_ep_queue = usb_host_flush_ep_queue;
dc->vmsd = &vmstate_usb_host;
dc->props = usb_host_dev_properties;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
static TypeInfo usb_host_dev_info = {
@@ -1461,7 +1462,7 @@
if (unconnected == 0) {
/* nothing to watch */
if (usb_auto_timer) {
- qemu_del_timer(usb_auto_timer);
+ timer_del(usb_auto_timer);
trace_usb_host_auto_scan_disabled();
}
return;
@@ -1473,13 +1474,13 @@
usb_vmstate = qemu_add_vm_change_state_handler(usb_host_vm_state, NULL);
}
if (!usb_auto_timer) {
- usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL);
+ usb_auto_timer = timer_new_ms(QEMU_CLOCK_REALTIME, usb_host_auto_check, NULL);
if (!usb_auto_timer) {
return;
}
trace_usb_host_auto_scan_enabled();
}
- qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000);
+ timer_mod(usb_auto_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 2000);
}
void usb_host_info(Monitor *mon, const QDict *qdict)
diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c
index ca09a89..65cd3b4 100644
--- a/hw/usb/host-linux.c
+++ b/hw/usb/host-linux.c
@@ -1530,6 +1530,7 @@
uc->handle_destroy = usb_host_handle_destroy;
dc->vmsd = &vmstate_usb_host;
dc->props = usb_host_dev_properties;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
static const TypeInfo usb_host_dev_info = {
@@ -1753,7 +1754,7 @@
if (unconnected == 0) {
/* nothing to watch */
if (usb_auto_timer) {
- qemu_del_timer(usb_auto_timer);
+ timer_del(usb_auto_timer);
trace_usb_host_auto_scan_disabled();
}
return;
@@ -1764,13 +1765,13 @@
usb_vmstate = qemu_add_vm_change_state_handler(usb_host_vm_state, NULL);
}
if (!usb_auto_timer) {
- usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL);
+ usb_auto_timer = timer_new_ms(QEMU_CLOCK_REALTIME, usb_host_auto_check, NULL);
if (!usb_auto_timer) {
return;
}
trace_usb_host_auto_scan_enabled();
}
- qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000);
+ timer_mod(usb_auto_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 2000);
}
#ifndef CONFIG_USB_LIBUSB
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index a594e95..287a505 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1297,7 +1297,7 @@
}
dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev);
- dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
+ dev->attach_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, usbredir_do_attach, dev);
packet_id_queue_init(&dev->cancelled, dev, "cancelled");
packet_id_queue_init(&dev->already_in_flight, dev, "already-in-flight");
@@ -1334,11 +1334,12 @@
USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
qemu_chr_delete(dev->cs);
+ dev->cs = NULL;
/* Note must be done after qemu_chr_close, as that causes a close event */
qemu_bh_delete(dev->chardev_close_bh);
- qemu_del_timer(dev->attach_timer);
- qemu_free_timer(dev->attach_timer);
+ timer_del(dev->attach_timer);
+ timer_free(dev->attach_timer);
usbredir_cleanup_device_queues(dev);
@@ -1492,7 +1493,7 @@
USBRedirDevice *dev = priv;
const char *speed;
- if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
+ if (timer_pending(dev->attach_timer) || dev->dev.attached) {
ERROR("Received device connect while already connected\n");
return;
}
@@ -1547,7 +1548,7 @@
}
usbredir_check_bulk_receiving(dev);
- qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
+ timer_mod(dev->attach_timer, dev->next_attach_time);
}
static void usbredir_device_disconnect(void *priv)
@@ -1555,7 +1556,7 @@
USBRedirDevice *dev = priv;
/* Stop any pending attaches */
- qemu_del_timer(dev->attach_timer);
+ timer_del(dev->attach_timer);
if (dev->dev.attached) {
DPRINTF("detaching device\n");
@@ -1564,7 +1565,7 @@
* Delay next usb device attach to give the guest a chance to see
* see the detach / attach in case of quick close / open succession
*/
- dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200;
+ dev->next_attach_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 200;
}
/* Reset state so that the next dev connected starts with a clean slate */
@@ -1587,7 +1588,7 @@
* If we receive interface info after the device has already been
* connected (ie on a set_config), re-check interface dependent things.
*/
- if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
+ if (timer_pending(dev->attach_timer) || dev->dev.attached) {
usbredir_check_bulk_receiving(dev);
if (usbredir_check_filter(dev)) {
ERROR("Device no longer matches filter after interface info "
@@ -2362,6 +2363,7 @@
uc->ep_stopped = usbredir_ep_stopped;
dc->vmsd = &usbredir_vmstate;
dc->props = usbredir_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo usbredir_dev_info = {
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
index 82cc151..351a343 100644
--- a/hw/virtio/dataplane/vring.c
+++ b/hw/virtio/dataplane/vring.c
@@ -52,6 +52,7 @@
void vring_teardown(Vring *vring, VirtIODevice *vdev, int n)
{
virtio_queue_set_last_avail_idx(vdev, n, vring->last_avail_idx);
+ virtio_queue_invalidate_signalled_used(vdev, n);
hostmem_finalize(&vring->hostmem);
}
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 8f6ab13..9e336ad 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -762,6 +762,7 @@
fflush(stderr);
}
virtio_queue_set_last_avail_idx(vdev, idx, state.num);
+ virtio_queue_invalidate_signalled_used(vdev, idx);
assert (r >= 0);
cpu_physical_memory_unmap(vq->ring, virtio_queue_get_ring_size(vdev, idx),
0, virtio_queue_get_ring_size(vdev, idx));
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 3fa72a9..9504877 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -53,8 +53,8 @@
/*
* reset_stats - Mark all items in the stats array as unset
*
- * This function needs to be called at device intialization and before
- * before updating to a set of newly-generated stats. This will ensure that no
+ * This function needs to be called at device initialization and before
+ * updating to a set of newly-generated stats. This will ensure that no
* stale values stick around in case the guest reports a subset of the supported
* statistics.
*/
@@ -78,8 +78,8 @@
static void balloon_stats_destroy_timer(VirtIOBalloon *s)
{
if (balloon_stats_enabled(s)) {
- qemu_del_timer(s->stats_timer);
- qemu_free_timer(s->stats_timer);
+ timer_del(s->stats_timer);
+ timer_free(s->stats_timer);
s->stats_timer = NULL;
s->stats_poll_interval = 0;
}
@@ -87,7 +87,7 @@
static void balloon_stats_change_timer(VirtIOBalloon *s, int secs)
{
- qemu_mod_timer(s->stats_timer, qemu_get_clock_ms(vm_clock) + secs * 1000);
+ timer_mod(s->stats_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + secs * 1000);
}
static void balloon_stats_poll_cb(void *opaque)
@@ -173,7 +173,7 @@
/* create a new timer */
g_assert(s->stats_timer == NULL);
- s->stats_timer = qemu_new_timer_ms(vm_clock, balloon_stats_poll_cb, s);
+ s->stats_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, balloon_stats_poll_cb, s);
s->stats_poll_interval = value;
balloon_stats_change_timer(s, 0);
}
@@ -392,6 +392,7 @@
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->exit = virtio_balloon_device_exit;
dc->props = virtio_balloon_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
vdc->init = virtio_balloon_device_init;
vdc->get_config = virtio_balloon_get_config;
vdc->set_config = virtio_balloon_set_config;
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 54d6679..4bd2953 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -151,6 +151,9 @@
}
return proxy->host_features;
case VIRTIO_MMIO_QUEUENUMMAX:
+ if (!virtio_queue_get_num(vdev, vdev->queue_sel)) {
+ return 0;
+ }
return VIRTQUEUE_MAX_SIZE;
case VIRTIO_MMIO_QUEUEPFN:
return virtio_queue_get_addr(vdev, vdev->queue_sel)
@@ -370,6 +373,7 @@
dc->realize = virtio_mmio_realizefn;
dc->reset = virtio_mmio_reset;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo virtio_mmio_info = {
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index c4db407..f2c489b 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -911,6 +911,7 @@
pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_9P;
pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
pcidev_k->class_id = 0x2;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->props = virtio_9p_pci_properties;
}
@@ -1065,6 +1066,7 @@
VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->props = virtio_blk_pci_properties;
k->init = virtio_blk_pci_init;
pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
@@ -1135,6 +1137,7 @@
VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
k->init = virtio_scsi_pci_init_pci;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->props = virtio_scsi_pci_properties;
pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
@@ -1191,6 +1194,7 @@
VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
k->init = vhost_scsi_pci_init_pci;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
dc->props = vhost_scsi_pci_properties;
pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_SCSI;
@@ -1271,6 +1275,7 @@
VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
k->init = virtio_balloon_pci_init;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->props = virtio_balloon_pci_properties;
pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_BALLOON;
@@ -1356,6 +1361,7 @@
VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
k->init = virtio_serial_pci_init;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->props = virtio_serial_pci_properties;
pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_CONSOLE;
@@ -1417,6 +1423,7 @@
k->device_id = PCI_DEVICE_ID_VIRTIO_NET;
k->revision = VIRTIO_PCI_ABI_VERSION;
k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
dc->props = virtio_net_properties;
vpciklass->init = virtio_net_pci_init;
}
@@ -1468,6 +1475,7 @@
PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
k->init = virtio_rng_pci_init;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->props = virtio_rng_pci_properties;
pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index cb787c7..314e393 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -129,8 +129,8 @@
vrng->quota_remaining = vrng->conf.max_bytes;
virtio_rng_process(vrng);
- qemu_mod_timer(vrng->rate_limit_timer,
- qemu_get_clock_ms(vm_clock) + vrng->conf.period_ms);
+ timer_mod(vrng->rate_limit_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + vrng->conf.period_ms);
}
static int virtio_rng_device_init(VirtIODevice *vdev)
@@ -172,11 +172,11 @@
assert(vrng->conf.max_bytes <= INT64_MAX);
vrng->quota_remaining = vrng->conf.max_bytes;
- vrng->rate_limit_timer = qemu_new_timer_ms(vm_clock,
+ vrng->rate_limit_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
check_rate_limit, vrng);
- qemu_mod_timer(vrng->rate_limit_timer,
- qemu_get_clock_ms(vm_clock) + vrng->conf.period_ms);
+ timer_mod(vrng->rate_limit_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + vrng->conf.period_ms);
register_savevm(qdev, "virtio-rng", -1, 1, virtio_rng_save,
virtio_rng_load, vrng);
@@ -189,8 +189,8 @@
VirtIORNG *vrng = VIRTIO_RNG(qdev);
VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
- qemu_del_timer(vrng->rate_limit_timer);
- qemu_free_timer(vrng->rate_limit_timer);
+ timer_del(vrng->rate_limit_timer);
+ timer_free(vrng->rate_limit_timer);
unregister_savevm(qdev, "virtio-rng", vrng);
virtio_cleanup(vdev);
return 0;
@@ -207,6 +207,7 @@
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->exit = virtio_rng_device_exit;
dc->props = virtio_rng_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
vdc->init = virtio_rng_device_init;
vdc->get_features = get_features;
}
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 09f62c6..2f1e73b 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -377,8 +377,8 @@
/* loop over the indirect descriptor table */
indirect = 1;
max = vring_desc_len(desc_pa, i) / sizeof(VRingDesc);
- num_bufs = i = 0;
desc_pa = vring_desc_addr(desc_pa, i);
+ num_bufs = i = 0;
}
do {
@@ -673,10 +673,16 @@
void virtio_queue_set_num(VirtIODevice *vdev, int n, int num)
{
- if (num <= VIRTQUEUE_MAX_SIZE) {
- vdev->vq[n].vring.num = num;
- virtqueue_init(&vdev->vq[n]);
+ /* Don't allow guest to flip queue between existent and
+ * nonexistent states, or to set it to an invalid size.
+ */
+ if (!!num != !!vdev->vq[n].vring.num ||
+ num > VIRTQUEUE_MAX_SIZE ||
+ num < 0) {
+ return;
}
+ vdev->vq[n].vring.num = num;
+ virtqueue_init(&vdev->vq[n]);
}
int virtio_queue_get_num(VirtIODevice *vdev, int n)
@@ -1059,6 +1065,11 @@
vdev->vq[n].last_avail_idx = idx;
}
+void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n)
+{
+ vdev->vq[n].signalled_used_valid = false;
+}
+
VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n)
{
return vdev->vq + n;
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index cb4e1f9..387962e 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -128,7 +128,6 @@
case WDT_POWEROFF: /* same as 'quit' command in monitor */
watchdog_mon_event("poweroff");
exit(0);
- break;
case WDT_PAUSE: /* same as 'stop' command in monitor */
watchdog_mon_event("pause");
diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c
index 85aebc2..36d3887 100644
--- a/hw/watchdog/wdt_i6300esb.c
+++ b/hw/watchdog/wdt_i6300esb.c
@@ -130,7 +130,7 @@
i6300esb_debug("stage %d, timeout %" PRIi64 "\n", d->stage, timeout);
- qemu_mod_timer(d->timer, qemu_get_clock_ns(vm_clock) + timeout);
+ timer_mod(d->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + timeout);
}
/* This is called when the guest disables the watchdog. */
@@ -138,7 +138,7 @@
{
i6300esb_debug("timer disabled\n");
- qemu_del_timer(d->timer);
+ timer_del(d->timer);
}
static void i6300esb_reset(DeviceState *dev)
@@ -414,7 +414,7 @@
i6300esb_debug("I6300State = %p\n", d);
- d->timer = qemu_new_timer_ns(vm_clock, i6300esb_timer_expired, d);
+ d->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, i6300esb_timer_expired, d);
d->previous_reboot_flag = 0;
memory_region_init_io(&d->io_mem, OBJECT(d), &i6300esb_ops, d,
@@ -451,6 +451,7 @@
k->class_id = PCI_CLASS_SYSTEM_OTHER;
dc->reset = i6300esb_reset;
dc->vmsd = &vmstate_i6300esb;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo i6300esb_info = {
diff --git a/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c
index c788554..bc994a4 100644
--- a/hw/watchdog/wdt_ib700.c
+++ b/hw/watchdog/wdt_ib700.c
@@ -62,7 +62,7 @@
ib700_debug("addr = %x, data = %x\n", addr, data);
timeout = (int64_t) time_map[data & 0xF] * get_ticks_per_sec();
- qemu_mod_timer(s->timer, qemu_get_clock_ns (vm_clock) + timeout);
+ timer_mod(s->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + timeout);
}
/* A write (of any value) to this register disables the timer. */
@@ -72,7 +72,7 @@
ib700_debug("addr = %x, data = %x\n", addr, data);
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
}
/* This is called when the watchdog expires. */
@@ -83,7 +83,7 @@
ib700_debug("watchdog expired\n");
watchdog_perform_action();
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
}
static const VMStateDescription vmstate_ib700 = {
@@ -110,7 +110,7 @@
ib700_debug("watchdog init\n");
- s->timer = qemu_new_timer_ns(vm_clock, ib700_timer_expired, s);
+ s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ib700_timer_expired, s);
portio_list_init(port_list, OBJECT(s), wdt_portio_list, s, "ib700");
portio_list_add(port_list, isa_address_space_io(&s->parent_obj), 0);
@@ -122,7 +122,7 @@
ib700_debug("watchdog reset\n");
- qemu_del_timer(s->timer);
+ timer_del(s->timer);
}
static WatchdogTimerModel model = {
@@ -137,6 +137,7 @@
dc->realize = wdt_ib700_realize;
dc->reset = wdt_ib700_reset;
dc->vmsd = &vmstate_ib700;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo wdt_ib700_info = {
diff --git a/hw/xen/Makefile.objs b/hw/xen/Makefile.objs
index 2017560..ce640c6 100644
--- a/hw/xen/Makefile.objs
+++ b/hw/xen/Makefile.objs
@@ -1,6 +1,6 @@
# xen backend driver support
common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
-obj-$(CONFIG_XEN_I386) += xen_platform.o xen_apic.o
+obj-$(CONFIG_XEN_I386) += xen_platform.o xen_apic.o xen_pvdevice.o
obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
diff --git a/hw/xen/xen_platform.c b/hw/xen/xen_platform.c
index 6a8ba7e..79bf0b3 100644
--- a/hw/xen/xen_platform.c
+++ b/hw/xen/xen_platform.c
@@ -428,6 +428,7 @@
k->subsystem_vendor_id = PCI_VENDOR_ID_XEN;
k->subsystem_id = PCI_DEVICE_ID_XEN_PLATFORM;
k->revision = 1;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->desc = "XEN platform pci device";
dc->reset = platform_reset;
dc->vmsd = &vmstate_xen_platform;
diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
index d7ee774..ca2d460 100644
--- a/hw/xen/xen_pt.c
+++ b/hw/xen/xen_pt.c
@@ -756,7 +756,8 @@
out:
memory_listener_register(&s->memory_listener, &address_space_memory);
memory_listener_register(&s->io_listener, &address_space_io);
- XEN_PT_LOG(d, "Real physical device %02x:%02x.%d registered successfuly!\n",
+ XEN_PT_LOG(d,
+ "Real physical device %02x:%02x.%d registered successfully!\n",
s->hostaddr.bus, s->hostaddr.slot, s->hostaddr.function);
return 0;
@@ -829,6 +830,7 @@
k->exit = xen_pt_unregister_device;
k->config_read = xen_pt_pci_read_config;
k->config_write = xen_pt_pci_write_config;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->desc = "Assign an host PCI device with Xen";
dc->props = xen_pci_passthrough_properties;
};
diff --git a/hw/xen/xen_pvdevice.c b/hw/xen/xen_pvdevice.c
new file mode 100644
index 0000000..1132c89
--- /dev/null
+++ b/hw/xen/xen_pvdevice.c
@@ -0,0 +1,131 @@
+/* Copyright (c) Citrix Systems Inc.
+ * 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.
+ *
+ * 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 COPYRIGHT HOLDER OR
+ * CONTRIBUTORS 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 "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "trace.h"
+
+#define TYPE_XEN_PV_DEVICE "xen-pvdevice"
+
+#define XEN_PV_DEVICE(obj) \
+ OBJECT_CHECK(XenPVDevice, (obj), TYPE_XEN_PV_DEVICE)
+
+typedef struct XenPVDevice {
+ /*< private >*/
+ PCIDevice parent_obj;
+ /*< public >*/
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint8_t revision;
+ uint32_t size;
+ MemoryRegion mmio;
+} XenPVDevice;
+
+static uint64_t xen_pv_mmio_read(void *opaque, hwaddr addr,
+ unsigned size)
+{
+ trace_xen_pv_mmio_read(addr);
+
+ return ~(uint64_t)0;
+}
+
+static void xen_pv_mmio_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+ trace_xen_pv_mmio_write(addr);
+}
+
+static const MemoryRegionOps xen_pv_mmio_ops = {
+ .read = &xen_pv_mmio_read,
+ .write = &xen_pv_mmio_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int xen_pv_init(PCIDevice *pci_dev)
+{
+ XenPVDevice *d = XEN_PV_DEVICE(pci_dev);
+ uint8_t *pci_conf;
+
+ pci_conf = pci_dev->config;
+
+ pci_set_word(pci_conf + PCI_VENDOR_ID, d->vendor_id);
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, d->vendor_id);
+ pci_set_word(pci_conf + PCI_DEVICE_ID, d->device_id);
+ pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, d->device_id);
+ pci_set_byte(pci_conf + PCI_REVISION_ID, d->revision);
+
+ pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_MEMORY);
+
+ pci_config_set_prog_interface(pci_conf, 0);
+
+ pci_conf[PCI_INTERRUPT_PIN] = 1;
+
+ memory_region_init_io(&d->mmio, NULL, &xen_pv_mmio_ops, d,
+ "mmio", d->size);
+
+ pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
+ &d->mmio);
+
+ return 0;
+}
+
+static Property xen_pv_props[] = {
+ DEFINE_PROP_UINT16("vendor-id", XenPVDevice, vendor_id, PCI_VENDOR_ID_XEN),
+ DEFINE_PROP_UINT16("device-id", XenPVDevice, device_id, PCI_DEVICE_ID_XEN_PVDEVICE),
+ DEFINE_PROP_UINT8("revision", XenPVDevice, revision, 0x01),
+ DEFINE_PROP_UINT32("size", XenPVDevice, size, 0x400000),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void xen_pv_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = xen_pv_init;
+ k->class_id = PCI_CLASS_SYSTEM_OTHER;
+ dc->desc = "Xen PV Device";
+ dc->props = xen_pv_props;
+}
+
+static const TypeInfo xen_pv_type_info = {
+ .name = TYPE_XEN_PV_DEVICE,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(XenPVDevice),
+ .class_init = xen_pv_class_init,
+};
+
+static void xen_pv_register_types(void)
+{
+ type_register_static(&xen_pv_type_info);
+}
+
+type_init(xen_pv_register_types)
diff --git a/hw/xtensa/pic_cpu.c b/hw/xtensa/pic_cpu.c
index 7f015ff..e2005bd 100644
--- a/hw/xtensa/pic_cpu.c
+++ b/hw/xtensa/pic_cpu.c
@@ -52,11 +52,11 @@
uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
int level;
- /* If the CPU is halted advance CCOUNT according to the vm_clock time
+ /* If the CPU is halted advance CCOUNT according to the QEMU_CLOCK_VIRTUAL time
* elapsed since the moment when it was advanced last time.
*/
if (cs->halted) {
- int64_t now = qemu_get_clock_ns(vm_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
xtensa_advance_ccount(env,
muldiv64(now - env->halt_clock,
@@ -119,7 +119,7 @@
}
}
env->wake_ccount = wake_ccount;
- qemu_mod_timer(env->ccompare_timer, env->halt_clock +
+ timer_mod(env->ccompare_timer, env->halt_clock +
muldiv64(wake_ccount - env->sregs[CCOUNT],
1000000, env->config->clock_freq_khz));
}
@@ -131,7 +131,7 @@
CPUState *cs = CPU(cpu);
if (cs->halted) {
- env->halt_clock = qemu_get_clock_ns(vm_clock);
+ env->halt_clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
xtensa_advance_ccount(env, env->wake_ccount - env->sregs[CCOUNT]);
if (!cpu_has_work(cs)) {
env->sregs[CCOUNT] = env->wake_ccount + 1;
@@ -149,7 +149,7 @@
if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT) &&
env->config->nccompare > 0) {
env->ccompare_timer =
- qemu_new_timer_ns(vm_clock, &xtensa_ccompare_cb, cpu);
+ timer_new_ns(QEMU_CLOCK_VIRTUAL, &xtensa_ccompare_cb, cpu);
}
}
diff --git a/include/block/aio.h b/include/block/aio.h
index cc77771..2efdf41 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 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 @@
/* 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_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 @@
int fd,
IOHandler *io_read,
IOHandler *io_write,
- AioFlushHandler *io_flush,
void *opaque);
#endif
@@ -225,8 +223,7 @@
*/
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 @@
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 c6ac871..8012e25 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 @@
/* 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 @@
* @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 @@
* 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 c290d07..d530409 100644
--- a/include/block/blockjob.h
+++ b/include/block/blockjob.h
@@ -141,7 +141,7 @@
* 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 377805a..4232569 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 @@
*
* 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 @@
* 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 cf0d3e2..58bfbf8 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -1348,11 +1348,17 @@
/* 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 f2800ec..a407b50 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -210,11 +210,15 @@
})
#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 b5b93db..a5c028c 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -154,8 +154,6 @@
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 b2162a4..ffb69a4 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -326,18 +326,7 @@
(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 @@
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 1bd00ae..a608a26 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -32,13 +32,50 @@
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(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 2341a75..a4b1eca 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 1f25e33..e55e717 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 8584902..eaca9e1 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,124 +74,87 @@
}
/* handle all cases except unaligned access which span two pages */
+#ifdef SOFTMMU_CODE_ACCESS
+static
+#endif
+DATA_TYPE
+glue(glue(helper_ret_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env,
+ target_ulong addr, int mmu_idx,
+ 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;
+
+ /* 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
+ tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr);
+ tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+ }
+
+ /* 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);
+ }
+
+ /* 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));
+#else
+ res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift));
+#endif
+ 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);
+ }
+#endif
+
+ haddr = addr + env->tlb_table[mmu_idx][index].addend;
+ return glue(glue(ld, USUFFIX), _raw)((uint8_t *)haddr);
+}
+
DATA_TYPE
glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
int mmu_idx)
{
- DATA_TYPE res;
- int index;
- target_ulong tlb_addr;
- hwaddr ioaddr;
- 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 */
- 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();
-#ifdef ALIGNED_ONLY
- 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;
- }
- 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;
-
- 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;
-#ifdef TARGET_WORDS_BIGENDIAN
- res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift));
-#else
- 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;
+ return glue(glue(helper_ret_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx,
+ GETPC_EXT());
}
#ifndef SOFTMMU_CODE_ACCESS
-static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(CPUArchState *env,
- target_ulong addr,
- DATA_TYPE val,
- int mmu_idx,
- uintptr_t retaddr);
-
static inline void glue(io_write, SUFFIX)(CPUArchState *env,
hwaddr physaddr,
DATA_TYPE val,
@@ -214,107 +173,79 @@
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;
}
+
+ /* 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;
+ }
+
+ /* 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
+ uint8_t val8 = val >> (((DATA_SIZE - 1) * 8) - (i * 8));
+#else
+ uint8_t val8 = val >> (i * 8);
+#endif
+ glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8,
+ mmu_idx, retaddr);
+ }
+ 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);
}
-/* 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)
+void
+glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr,
+ DATA_TYPE val, int mmu_idx)
{
- hwaddr ioaddr;
- target_ulong tlb_addr;
- int index, i;
-
- 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--) {
-#ifdef TARGET_WORDS_BIGENDIAN
- glue(slow_stb, MMUSUFFIX)(env, addr + i,
- val >> (((DATA_SIZE - 1) * 8) - (i * 8)),
- mmu_idx, retaddr);
-#else
- glue(slow_stb, MMUSUFFIX)(env, addr + i,
- val >> (i * 8),
- mmu_idx, retaddr);
-#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);
- }
- } else {
- /* the page is not in the TLB : fill it */
- tlb_fill(env, addr, 1, mmu_idx, retaddr);
- goto redo;
- }
+ 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 635be7b..51733d3 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -136,7 +136,7 @@
#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 bae87c6..ecbbba8 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 bda3213..2742d70 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
similarity index 65%
rename from include/hw/lm32/lm32_juart.h
rename to include/hw/char/lm32_juart.h
index 67fc586..70dc416 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 86e63da..6245388 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 7fb97b0..f79d478 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -18,8 +18,8 @@
} PcPciInfo;
struct PcGuestInfo {
- PcPciInfo pci_info;
bool has_pci_info;
+ bool isapc_ram_fw;
FWCfgState *fw_cfg;
};
@@ -101,6 +101,16 @@
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 @@
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 @@
}
/* 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 @@
.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 e1bf96c..495bcf3 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -92,9 +92,6 @@
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 eb9c9a3..6145736 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -36,6 +36,7 @@
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 291e85f..2a7a9c9 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 3cb631e..6eb7ab6 100644
--- a/include/hw/pci-host/q35.h
+++ b/include/hw/pci-host/q35.h
@@ -55,9 +55,11 @@
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 1e23dbf..93f9511 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -52,14 +52,14 @@
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 66762f6..9df1788 100644
--- a/include/hw/pci/pci_bus.h
+++ b/include/hw/pci/pci_bus.h
@@ -53,8 +53,13 @@
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 d7933bf..3ddaf6a 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 d89aa61..e167bf7 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 @@
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 de95480..9fc1972 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 @@
#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 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 3609327..46edc2a 100644
--- a/include/hw/ppc/spapr_vio.h
+++ b/include/hw/ppc/spapr_vio.h
@@ -134,4 +134,9 @@
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 6bce042..66364c5 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)
-struct icp_state;
+/*
+ * 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;
-qemu_irq xics_get_qirq(struct icp_state *icp, int irq);
-void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi);
+struct XICSState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+ uint32_t nr_servers;
+ uint32_t nr_irqs;
+ ICPState *ss;
+ ICSState *ics;
+};
-struct icp_state *xics_system_init(int nr_servers, int nr_irqs);
-void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu);
+#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 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(XICSState *icp, int irq);
+void xics_set_irq_type(XICSState *icp, int irq, bool lsi);
+
+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 7fbffcb..46972f4 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 @@
#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 @@
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 39448b7..692f82e 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -15,6 +15,7 @@
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 @@
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 8c17165..bb50a87 100644
--- a/include/hw/sysbus.h
+++ b/include/hw/sysbus.h
@@ -42,7 +42,10 @@
} 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 @@
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 59337fa..8217522 100644
--- a/include/hw/timer/m48t59.h
+++ b/include/hw/timer/m48t59.h
@@ -21,6 +21,9 @@
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 fc71853..b87cf49 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -125,6 +125,7 @@
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 d7e9e0f..a90522d 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -237,6 +237,7 @@
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 08c772d..140e6b4 100644
--- a/include/migration/migration.h
+++ b/include/migration/migration.h
@@ -90,7 +90,7 @@
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 5939eee..fd48c14 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 685b2e3..d6855d1 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -65,5 +65,6 @@
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 9124649..d0bbc7c 100644
--- a/include/qapi/qmp/qobject.h
+++ b/include/qapi/qmp/qobject.h
@@ -44,6 +44,7 @@
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 5159964..f3fa420 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -22,12 +22,18 @@
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 28c21d8..48a2a2e 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_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 a83c700..7a58e47 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -73,6 +73,8 @@
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_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 d1610f1..d413a4a 100644
--- a/include/qemu/ratelimit.h
+++ b/include/qemu/ratelimit.h
@@ -23,7 +23,7 @@
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 0f30dcc..361566a 100644
--- a/include/qemu/thread-posix.h
+++ b/include/qemu/thread-posix.h
@@ -15,7 +15,7 @@
#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 9dd206c..e4934dd 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);
-/* 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;
+struct QEMUTimer {
+ int64_t expire_time; /* in nanoseconds */
+ QEMUTimerList *timer_list;
+ QEMUTimerCB *cb;
+ void *opaque;
+ QEMUTimer *next;
+ int scale;
+};
-/* 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;
+extern QEMUTimerListGroup main_loop_tlg;
-/* 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;
+/*
+ * QEMUClockType
+ */
-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);
+/*
+ * 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);
-void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier);
-void qemu_unregister_clock_reset_notifier(QEMUClock *clock,
+/**
+ * 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);
+
+/**
+ * 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);
+/**
+ * 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);
-void qemu_run_timers(QEMUClock *clock);
-void qemu_run_all_timers(void);
-void configure_alarms(char const *opt);
+/**
+ * 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;
+}
+
+/**
+ * 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 timer_new_tl(main_loop_tlg.tl[type], scale, cb, 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 timer_new(type, SCALE_NS, cb, opaque);
+}
+
+/**
+ * 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 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);
-int init_timer_alarm(void);
int64_t cpu_get_ticks(void);
void cpu_enable_ticks(void);
void cpu_disable_ticks(void);
-static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb,
- void *opaque)
-{
- return qemu_new_timer(clock, SCALE_NS, cb, opaque);
-}
-
-static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock, QEMUTimerCB *cb,
- void *opaque)
-{
- return qemu_new_timer(clock, SCALE_MS, cb, opaque);
-}
-
-static inline int64_t qemu_get_clock_ms(QEMUClock *clock)
-{
- return qemu_get_clock_ns(clock) / SCALE_MS;
-}
-
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 @@
}
#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 ac9f8d4..3205540 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 daf1835..3e49936 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -80,7 +80,11 @@
* @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 @@
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 @@
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 @@
* @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 @@
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 23fc048..9b69065 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -398,6 +398,8 @@
* @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 @@
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 e65e4a4..8053130 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -77,6 +77,7 @@
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 b8c770f..19fafb2 100644
--- a/include/sysemu/dump.h
+++ b/include/sysemu/dump.h
@@ -20,7 +20,9 @@
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 ce3efaf..8e76685 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -174,7 +174,7 @@
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 6dfb68d..a75d59a 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_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 3caeb66..b1aa059 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -103,7 +103,6 @@
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 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 eba6d77..c6c756b 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 @@
#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)
diff --git a/ioport.c b/ioport.c
index 89b17d6..79b7f1a 100644
--- a/ioport.c
+++ b/ioport.c
@@ -183,6 +183,7 @@
static const MemoryRegionOps portio_ops = {
.read = portio_read,
.write = portio_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
.valid.unaligned = true,
.impl.unaligned = true,
};
diff --git a/kvm-all.c b/kvm-all.c
index a2d4978..875e32e 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1875,9 +1875,8 @@
&dbg_data->dbg);
}
-int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
+int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap)
{
- CPUState *cpu = ENV_GET_CPU(env);
struct kvm_set_guest_debug_data data;
data.dbg.control = reinject_trap;
@@ -1927,9 +1926,7 @@
}
for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
- CPUArchState *env = cpu->env_ptr;
-
- err = kvm_update_guest_debug(env, 0);
+ err = kvm_update_guest_debug(cpu, 0);
if (err) {
return err;
}
@@ -1969,9 +1966,7 @@
}
for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
- CPUArchState *env = cpu->env_ptr;
-
- err = kvm_update_guest_debug(env, 0);
+ err = kvm_update_guest_debug(cpu, 0);
if (err) {
return err;
}
@@ -1999,15 +1994,13 @@
kvm_arch_remove_all_hw_breakpoints();
for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
- CPUArchState *env = cpu->env_ptr;
-
- kvm_update_guest_debug(env, 0);
+ kvm_update_guest_debug(cpu, 0);
}
}
#else /* !KVM_CAP_SET_GUEST_DEBUG */
-int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
+int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap)
{
return -EINVAL;
}
diff --git a/kvm-stub.c b/kvm-stub.c
index 806b044..548f471 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -78,7 +78,7 @@
{
}
-int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap)
+int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap)
{
return -ENOSYS;
}
diff --git a/linux-user/arm/syscall.h b/linux-user/arm/syscall.h
index 003d424..73f2931 100644
--- a/linux-user/arm/syscall.h
+++ b/linux-user/arm/syscall.h
@@ -40,3 +40,5 @@
#else
#define UNAME_MACHINE "armv5tel"
#endif
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h
index 50e50b4..832ee64 100644
--- a/linux-user/cris/syscall.h
+++ b/linux-user/cris/syscall.h
@@ -38,4 +38,6 @@
unsigned long eda;
};
+#define TARGET_CLONE_BACKWARDS2
+
#endif
diff --git a/linux-user/i386/syscall.h b/linux-user/i386/syscall.h
index 266e2c4..12b8c3b 100644
--- a/linux-user/i386/syscall.h
+++ b/linux-user/i386/syscall.h
@@ -144,3 +144,5 @@
};
#define UNAME_MACHINE "i686"
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h
index abcac79..58f8645 100644
--- a/linux-user/i386/target_cpu.h
+++ b/linux-user/i386/target_cpu.h
@@ -28,6 +28,21 @@
env->regs[R_EAX] = 0;
}
-/* TODO: need to implement cpu_set_tls() */
+#if defined(TARGET_ABI32)
+abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr);
-#endif
+static inline void cpu_set_tls(CPUX86State *env, target_ulong newtls)
+{
+ do_set_thread_area(env, newtls);
+ cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector);
+}
+#else
+abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr);
+
+static inline void cpu_set_tls(CPUX86State *env, target_ulong newtls)
+{
+ do_arch_prctl(env, TARGET_ARCH_SET_FS, newtls);
+}
+#endif /* defined(TARGET_ABI32) */
+
+#endif /* !defined(TARGET_CPU_H) */
diff --git a/linux-user/m68k/target_cpu.h b/linux-user/m68k/target_cpu.h
index 8a2a305..cad9c90 100644
--- a/linux-user/m68k/target_cpu.h
+++ b/linux-user/m68k/target_cpu.h
@@ -29,6 +29,10 @@
env->dregs[0] = 0;
}
-/* TODO: need to implement cpu_set_tls() */
+static inline void cpu_set_tls(CPUM68KState *env, target_ulong newtls)
+{
+ TaskState *ts = env->opaque;
+ ts->tp_value = newtls;
+}
#endif
diff --git a/linux-user/main.c b/linux-user/main.c
index f6a3aad..03859bc 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -92,7 +92,6 @@
}
#endif
-#if defined(CONFIG_USE_NPTL)
/***********************************************************/
/* Helper routines for implementing atomic operations. */
@@ -207,43 +206,6 @@
{
pthread_mutex_unlock(&cpu_list_mutex);
}
-#else /* if !CONFIG_USE_NPTL */
-/* These are no-ops because we are not threadsafe. */
-static inline void cpu_exec_start(CPUState *cpu)
-{
-}
-
-static inline void cpu_exec_end(CPUState *cpu)
-{
-}
-
-static inline void start_exclusive(void)
-{
-}
-
-static inline void end_exclusive(void)
-{
-}
-
-void fork_start(void)
-{
-}
-
-void fork_end(int child)
-{
- if (child) {
- gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
- }
-}
-
-void cpu_list_lock(void)
-{
-}
-
-void cpu_list_unlock(void)
-{
-}
-#endif
#ifdef TARGET_I386
@@ -1958,7 +1920,7 @@
MIPS_SYS(sys_sched_get_priority_min, 1)
MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */
MIPS_SYS(sys_nanosleep, 2)
- MIPS_SYS(sys_mremap , 4)
+ MIPS_SYS(sys_mremap , 5)
MIPS_SYS(sys_accept , 3)
MIPS_SYS(sys_bind , 3)
MIPS_SYS(sys_connect , 3) /* 4170 */
@@ -2095,7 +2057,7 @@
MIPS_SYS(sys_pselect6, 6)
MIPS_SYS(sys_ppoll, 5)
MIPS_SYS(sys_unshare, 1)
- MIPS_SYS(sys_splice, 4)
+ MIPS_SYS(sys_splice, 6)
MIPS_SYS(sys_sync_file_range, 7) /* 4305 */
MIPS_SYS(sys_tee, 4)
MIPS_SYS(sys_vmsplice, 4)
@@ -2349,7 +2311,31 @@
abi_ulong trap_instr;
unsigned int code;
- ret = get_user_ual(trap_instr, env->active_tc.PC);
+ if (env->hflags & MIPS_HFLAG_M16) {
+ if (env->insn_flags & ASE_MICROMIPS) {
+ /* microMIPS mode */
+ abi_ulong instr[2];
+
+ ret = get_user_u16(instr[0], env->active_tc.PC) ||
+ get_user_u16(instr[1], env->active_tc.PC + 2);
+
+ trap_instr = (instr[0] << 16) | instr[1];
+ } else {
+ /* MIPS16e mode */
+ ret = get_user_u16(trap_instr, env->active_tc.PC);
+ if (ret != 0) {
+ goto error;
+ }
+ code = (trap_instr >> 6) & 0x3f;
+ if (do_break(env, &info, code) != 0) {
+ goto error;
+ }
+ break;
+ }
+ } else {
+ ret = get_user_ual(trap_instr, env->active_tc.PC);
+ }
+
if (ret != 0) {
goto error;
}
@@ -2373,14 +2359,30 @@
abi_ulong trap_instr;
unsigned int code = 0;
- ret = get_user_ual(trap_instr, env->active_tc.PC);
+ if (env->hflags & MIPS_HFLAG_M16) {
+ /* microMIPS mode */
+ abi_ulong instr[2];
+
+ ret = get_user_u16(instr[0], env->active_tc.PC) ||
+ get_user_u16(instr[1], env->active_tc.PC + 2);
+
+ trap_instr = (instr[0] << 16) | instr[1];
+ } else {
+ ret = get_user_ual(trap_instr, env->active_tc.PC);
+ }
+
if (ret != 0) {
goto error;
}
/* The immediate versions don't provide a code. */
if (!(trap_instr & 0xFC000000)) {
- code = ((trap_instr >> 6) & ((1 << 10) - 1));
+ if (env->hflags & MIPS_HFLAG_M16) {
+ /* microMIPS mode */
+ code = ((trap_instr >> 12) & ((1 << 4) - 1));
+ } else {
+ code = ((trap_instr >> 6) & ((1 << 10) - 1));
+ }
}
if (do_break(env, &info, code) != 0) {
@@ -3157,12 +3159,7 @@
void task_settid(TaskState *ts)
{
if (ts->ts_tid == 0) {
-#ifdef CONFIG_USE_NPTL
ts->ts_tid = (pid_t)syscall(SYS_gettid);
-#else
- /* when no threads are used, tid becomes pid */
- ts->ts_tid = getpid();
-#endif
}
}
@@ -3640,9 +3637,7 @@
exit(1);
}
cpu = ENV_GET_CPU(env);
-#if defined(TARGET_SPARC) || defined(TARGET_PPC)
cpu_reset(cpu);
-#endif
thread_cpu = cpu;
diff --git a/linux-user/microblaze/syscall.h b/linux-user/microblaze/syscall.h
index c3e5c55..d550989 100644
--- a/linux-user/microblaze/syscall.h
+++ b/linux-user/microblaze/syscall.h
@@ -48,4 +48,6 @@
uint32_t kernel_mode;
};
+#define TARGET_CLONE_BACKWARDS
+
#endif
diff --git a/linux-user/mips/syscall.h b/linux-user/mips/syscall.h
index 3deb862..9d437d9 100644
--- a/linux-user/mips/syscall.h
+++ b/linux-user/mips/syscall.h
@@ -225,3 +225,5 @@
#define TARGET_QEMU_ESIGRETURN 255
#define UNAME_MACHINE "mips"
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h
index cd707df..1710f76 100644
--- a/linux-user/mips64/syscall.h
+++ b/linux-user/mips64/syscall.h
@@ -222,3 +222,5 @@
#define TARGET_QEMU_ESIGRETURN 255
#define UNAME_MACHINE "mips64"
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index de22197..a249f0c 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -33,7 +33,6 @@
//#define DEBUG_MMAP
-#if defined(CONFIG_USE_NPTL)
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
static __thread int mmap_lock_count;
@@ -66,16 +65,6 @@
else
pthread_mutex_unlock(&mmap_mutex);
}
-#else
-/* We aren't threadsafe to start with, so no need to worry about locking. */
-void mmap_lock(void)
-{
-}
-
-void mmap_unlock(void)
-{
-}
-#endif
/* NOTE: all the constants are the HOST ones, but addresses are target. */
int target_mprotect(abi_ulong start, abi_ulong len, int prot)
diff --git a/linux-user/openrisc/target_cpu.h b/linux-user/openrisc/target_cpu.h
index 501fb81..32a46ac 100644
--- a/linux-user/openrisc/target_cpu.h
+++ b/linux-user/openrisc/target_cpu.h
@@ -25,9 +25,14 @@
if (newsp) {
env->gpr[1] = newsp;
}
- env->gpr[2] = 0;
+ env->gpr[11] = 0;
}
-/* TODO: need to implement cpu_set_tls() */
+static inline void cpu_set_tls(CPUOpenRISCState *env, target_ulong newtls)
+{
+ /* Linux kernel 3.10 does not pay any attention to CLONE_SETTLS
+ * in copy_thread(), so QEMU need not do so either.
+ */
+}
#endif
diff --git a/linux-user/ppc/syscall.h b/linux-user/ppc/syscall.h
index 481047b..ba36acb 100644
--- a/linux-user/ppc/syscall.h
+++ b/linux-user/ppc/syscall.h
@@ -62,3 +62,5 @@
#else
#define UNAME_MACHINE "ppc"
#endif
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 6569608..4a16e8f 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -16,16 +16,10 @@
#include "exec/user/thunk.h"
#include "syscall_defs.h"
#include "syscall.h"
-#include "target_cpu.h"
-#include "target_signal.h"
#include "exec/gdbstub.h"
#include "qemu/queue.h"
-#if defined(CONFIG_USE_NPTL)
#define THREAD __thread
-#else
-#define THREAD
-#endif
/* This struct is used to hold certain information about the image.
* Basically, it replicates in user space what would be certain
@@ -118,11 +112,10 @@
uint32_t v86flags;
uint32_t v86mask;
#endif
-#ifdef CONFIG_USE_NPTL
abi_ulong child_tidptr;
-#endif
#ifdef TARGET_M68K
int sim_syscalls;
+ abi_ulong tp_value;
#endif
#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
/* Extra fields for semihosted binaries. */
@@ -269,10 +262,8 @@
abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
void cpu_list_lock(void);
void cpu_list_unlock(void);
-#if defined(CONFIG_USE_NPTL)
void mmap_fork_start(void);
void mmap_fork_end(int child);
-#endif
/* main.c */
extern unsigned long guest_stack_size;
@@ -450,8 +441,13 @@
#define unlock_user_struct(host_ptr, guest_addr, copy) \
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
-#if defined(CONFIG_USE_NPTL)
#include <pthread.h>
-#endif
+
+/* Include target-specific struct and function definitions;
+ * they may need access to the target-independent structures
+ * above, so include them last.
+ */
+#include "target_cpu.h"
+#include "target_signal.h"
#endif /* QEMU_H */
diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h
index e4603b7..ea8c304 100644
--- a/linux-user/s390x/syscall.h
+++ b/linux-user/s390x/syscall.h
@@ -21,3 +21,5 @@
};
#define UNAME_MACHINE "s390x"
+
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/signal.c b/linux-user/signal.c
index a5e8906..23d65da 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1552,7 +1552,7 @@
static long do_sigreturn_v1(CPUARMState *env)
{
abi_ulong frame_addr;
- struct sigframe_v1 *frame;
+ struct sigframe_v1 *frame = NULL;
target_sigset_t set;
sigset_t host_set;
int i;
@@ -1562,10 +1562,11 @@
* then 'sp' should be word aligned here. If it's
* not, then the user is trying to mess with us.
*/
- if (env->regs[13] & 7)
- goto badframe;
-
frame_addr = env->regs[13];
+ if (frame_addr & 7) {
+ goto badframe;
+ }
+
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
goto badframe;
@@ -1693,17 +1694,18 @@
static long do_sigreturn_v2(CPUARMState *env)
{
abi_ulong frame_addr;
- struct sigframe_v2 *frame;
+ struct sigframe_v2 *frame = NULL;
/*
* Since we stacked the signal on a 64-bit boundary,
* then 'sp' should be word aligned here. If it's
* not, then the user is trying to mess with us.
*/
- if (env->regs[13] & 7)
- goto badframe;
-
frame_addr = env->regs[13];
+ if (frame_addr & 7) {
+ goto badframe;
+ }
+
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
goto badframe;
@@ -1731,7 +1733,7 @@
static long do_rt_sigreturn_v1(CPUARMState *env)
{
abi_ulong frame_addr;
- struct rt_sigframe_v1 *frame;
+ struct rt_sigframe_v1 *frame = NULL;
sigset_t host_set;
/*
@@ -1739,10 +1741,11 @@
* then 'sp' should be word aligned here. If it's
* not, then the user is trying to mess with us.
*/
- if (env->regs[13] & 7)
- goto badframe;
-
frame_addr = env->regs[13];
+ if (frame_addr & 7) {
+ goto badframe;
+ }
+
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
goto badframe;
@@ -1772,17 +1775,18 @@
static long do_rt_sigreturn_v2(CPUARMState *env)
{
abi_ulong frame_addr;
- struct rt_sigframe_v2 *frame;
+ struct rt_sigframe_v2 *frame = NULL;
/*
* Since we stacked the signal on a 64-bit boundary,
* then 'sp' should be word aligned here. If it's
* not, then the user is trying to mess with us.
*/
- if (env->regs[13] & 7)
- goto badframe;
-
frame_addr = env->regs[13];
+ if (frame_addr & 7) {
+ goto badframe;
+ }
+
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
goto badframe;
@@ -4603,7 +4607,7 @@
{
struct target_sigcontext *sc = NULL;
struct target_mcontext *sr = NULL;
- target_ulong sr_addr, sc_addr;
+ target_ulong sr_addr = 0, sc_addr;
sigset_t blocked;
target_sigset_t set;
diff --git a/linux-user/sparc/syscall.h b/linux-user/sparc/syscall.h
index 5a9bb7e..4cd64bf 100644
--- a/linux-user/sparc/syscall.h
+++ b/linux-user/sparc/syscall.h
@@ -7,3 +7,10 @@
};
#define UNAME_MACHINE "sun4"
+
+/* SPARC kernels don't define this in their Kconfig, but they have the
+ * same ABI as if they did, implemented by sparc-specific code which fishes
+ * directly in the u_regs() struct for half the parameters in sparc_do_fork()
+ * and copy_thread().
+ */
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h
index 5a620a2..4944d46 100644
--- a/linux-user/sparc/target_cpu.h
+++ b/linux-user/sparc/target_cpu.h
@@ -25,12 +25,20 @@
if (newsp) {
env->regwptr[22] = newsp;
}
+ /* syscall return for clone child: 0, and clear CF since
+ * this counts as a success return value.
+ */
env->regwptr[0] = 0;
- /* FIXME: Do we also need to clear CF? */
- /* XXXXX */
- printf("HELPME: %s:%d\n", __FILE__, __LINE__);
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
+ env->xcc &= ~PSR_CARRY;
+#else
+ env->psr &= ~PSR_CARRY;
+#endif
}
-/* TODO: need to implement cpu_set_tls() */
+static inline void cpu_set_tls(CPUSPARCState *env, target_ulong newtls)
+{
+ env->gregs[7] = newtls;
+}
#endif
diff --git a/linux-user/sparc64/syscall.h b/linux-user/sparc64/syscall.h
index 81a816d..e60bf31 100644
--- a/linux-user/sparc64/syscall.h
+++ b/linux-user/sparc64/syscall.h
@@ -8,3 +8,10 @@
};
#define UNAME_MACHINE "sun4u"
+
+/* SPARC kernels don't define this in their Kconfig, but they have the
+ * same ABI as if they did, implemented by sparc-specific code which fishes
+ * directly in the u_regs() struct for half the parameters in sparc_do_fork()
+ * and copy_thread().
+ */
+#define TARGET_CLONE_BACKWARDS
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 00a0390..f986548 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -111,13 +111,8 @@
#include "qemu.h"
-#if defined(CONFIG_USE_NPTL)
#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
-#else
-/* XXX: Hardcode the above values. */
-#define CLONE_NPTL_FLAGS2 0
-#endif
//#define DEBUG
@@ -234,12 +229,10 @@
#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
_syscall1(int,set_tid_address,int *,tidptr)
#endif
-#if defined(CONFIG_USE_NPTL)
#if defined(TARGET_NR_futex) && defined(__NR_futex)
_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
const struct timespec *,timeout,int *,uaddr2,int,val3)
#endif
-#endif
#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
unsigned long *, user_mask_ptr);
@@ -1039,6 +1032,9 @@
#elif defined(TARGET_SH4)
((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
return host_pipe[0];
+#elif defined(TARGET_SPARC)
+ ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1];
+ return host_pipe[0];
#endif
}
@@ -4055,7 +4051,7 @@
}
#if defined(TARGET_I386) && defined(TARGET_ABI32)
-static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
+abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
{
uint64_t *gdt_table = g2h(env->gdt.base);
struct target_modify_ldt_ldt_s ldt_info;
@@ -4189,7 +4185,7 @@
#endif /* TARGET_I386 && TARGET_ABI32 */
#ifndef TARGET_ABI32
-static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
+abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
{
abi_long ret = 0;
abi_ulong val;
@@ -4227,7 +4223,6 @@
#define NEW_STACK_SIZE 0x40000
-#if defined(CONFIG_USE_NPTL)
static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
typedef struct {
@@ -4272,16 +4267,6 @@
/* never exits */
return NULL;
}
-#else
-
-static int clone_func(void *arg)
-{
- CPUArchState *env = arg;
- cpu_loop(env);
- /* never exits */
- return 0;
-}
-#endif
/* do_fork() Must return host values and target errnos (unlike most
do_*() functions). */
@@ -4292,12 +4277,8 @@
int ret;
TaskState *ts;
CPUArchState *new_env;
-#if defined(CONFIG_USE_NPTL)
unsigned int nptl_flags;
sigset_t sigmask;
-#else
- uint8_t *new_stack;
-#endif
/* Emulate vfork() with fork() */
if (flags & CLONE_VFORK)
@@ -4305,23 +4286,18 @@
if (flags & CLONE_VM) {
TaskState *parent_ts = (TaskState *)env->opaque;
-#if defined(CONFIG_USE_NPTL)
new_thread_info info;
pthread_attr_t attr;
-#endif
+
ts = g_malloc0(sizeof(TaskState));
init_task_state(ts);
/* we create a new CPU instance. */
new_env = cpu_copy(env);
-#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
- cpu_reset(ENV_GET_CPU(new_env));
-#endif
/* Init regs that differ from the parent. */
cpu_clone_regs(new_env, newsp);
new_env->opaque = ts;
ts->bprm = parent_ts->bprm;
ts->info = parent_ts->info;
-#if defined(CONFIG_USE_NPTL)
nptl_flags = flags;
flags &= ~CLONE_NPTL_FLAGS2;
@@ -4371,17 +4347,6 @@
pthread_cond_destroy(&info.cond);
pthread_mutex_destroy(&info.mutex);
pthread_mutex_unlock(&clone_lock);
-#else
- if (flags & CLONE_NPTL_FLAGS2)
- return -EINVAL;
- /* This is probably going to die very quickly, but do it anyway. */
- new_stack = g_malloc0 (NEW_STACK_SIZE);
-#ifdef __ia64__
- ret = __clone2(clone_func, new_stack, NEW_STACK_SIZE, flags, new_env);
-#else
- ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
-#endif
-#endif
} else {
/* if no CLONE_VM, we consider it is a fork */
if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
@@ -4392,7 +4357,6 @@
/* Child Process. */
cpu_clone_regs(env, newsp);
fork_end(1);
-#if defined(CONFIG_USE_NPTL)
/* There is a race condition here. The parent process could
theoretically read the TID in the child process before the child
tid is set. This would require using either ptrace
@@ -4408,7 +4372,6 @@
cpu_set_tls (env, newtls);
if (flags & CLONE_CHILD_CLEARTID)
ts->child_tidptr = child_tidptr;
-#endif
} else {
fork_end(0);
}
@@ -4834,7 +4797,6 @@
}
#endif
-#if defined(CONFIG_USE_NPTL)
/* ??? Using host futex calls even when target atomic operations
are not really atomic probably breaks things. However implementing
futexes locally would make futexes shared between multiple processes
@@ -4886,7 +4848,6 @@
return -TARGET_ENOSYS;
}
}
-#endif
/* Map host to target signal numbers for the wait family of syscalls.
Assume all other status bits are the same. */
@@ -5132,9 +5093,7 @@
abi_long arg5, abi_long arg6, abi_long arg7,
abi_long arg8)
{
-#ifdef CONFIG_USE_NPTL
CPUState *cpu = ENV_GET_CPU(cpu_env);
-#endif
abi_long ret;
struct stat st;
struct statfs stfs;
@@ -5148,7 +5107,6 @@
switch(num) {
case TARGET_NR_exit:
-#ifdef CONFIG_USE_NPTL
/* In old applications this may be used to implement _exit(2).
However in threaded applictions it is used for thread termination,
and _exit_group is used for application termination.
@@ -5186,7 +5144,6 @@
g_free(ts);
pthread_exit(NULL);
}
-#endif
#ifdef TARGET_GPROF
_mcleanup();
#endif
@@ -6956,16 +6913,20 @@
ret = get_errno(fsync(arg1));
break;
case TARGET_NR_clone:
-#if defined(TARGET_SH4) || defined(TARGET_ALPHA)
- ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
-#elif defined(TARGET_CRIS)
- ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
-#elif defined(TARGET_MICROBLAZE)
+ /* Linux manages to have three different orderings for its
+ * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
+ * match the kernel's CONFIG_CLONE_* settings.
+ * Microblaze is further special in that it uses a sixth
+ * implicit argument to clone for the TLS pointer.
+ */
+#if defined(TARGET_MICROBLAZE)
ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
-#elif defined(TARGET_S390X)
+#elif defined(TARGET_CLONE_BACKWARDS)
+ ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
+#elif defined(TARGET_CLONE_BACKWARDS2)
ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
#else
- ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
+ ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
#endif
break;
#ifdef __NR_exit_group
@@ -8558,6 +8519,13 @@
#elif defined(TARGET_I386) && defined(TARGET_ABI32)
ret = do_set_thread_area(cpu_env, arg1);
break;
+#elif defined(TARGET_M68K)
+ {
+ TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
+ ts->tp_value = arg1;
+ ret = 0;
+ break;
+ }
#else
goto unimplemented_nowarn;
#endif
@@ -8566,6 +8534,13 @@
case TARGET_NR_get_thread_area:
#if defined(TARGET_I386) && defined(TARGET_ABI32)
ret = do_get_thread_area(cpu_env, arg1);
+ break;
+#elif defined(TARGET_M68K)
+ {
+ TaskState *ts = ((CPUArchState *)cpu_env)->opaque;
+ ret = ts->tp_value;
+ break;
+ }
#else
goto unimplemented_nowarn;
#endif
@@ -8670,11 +8645,9 @@
}
break;
#endif
-#if defined(CONFIG_USE_NPTL)
case TARGET_NR_futex:
ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
break;
-#endif
#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
case TARGET_NR_inotify_init:
ret = get_errno(sys_inotify_init());
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 92c01a9..086fbff 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1138,8 +1138,7 @@
#endif
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) \
- || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \
- || defined(TARGET_OPENRISC)
+ || defined(TARGET_CRIS) || defined(TARGET_UNICORE32)
struct target_stat {
unsigned short st_dev;
unsigned short __pad1;
@@ -1837,29 +1836,55 @@
abi_ulong __unused[3];
};
#elif defined(TARGET_OPENRISC)
+
+/* These are the asm-generic versions of the stat and stat64 structures */
+
struct target_stat {
abi_ulong st_dev;
abi_ulong st_ino;
- abi_ulong st_nlink;
-
unsigned int st_mode;
+ unsigned int st_nlink;
unsigned int st_uid;
unsigned int st_gid;
- unsigned int __pad0;
abi_ulong st_rdev;
+ abi_ulong __pad1;
abi_long st_size;
- abi_long st_blksize;
- abi_long st_blocks; /* Number 512-byte blocks allocated. */
-
- abi_ulong target_st_atime;
+ int st_blksize;
+ int __pad2;
+ abi_long st_blocks;
+ abi_long target_st_atime;
abi_ulong target_st_atime_nsec;
- abi_ulong target_st_mtime;
+ abi_long target_st_mtime;
abi_ulong target_st_mtime_nsec;
- abi_ulong target_st_ctime;
+ abi_long target_st_ctime;
abi_ulong target_st_ctime_nsec;
-
- abi_long __unused[3];
+ unsigned int __unused4;
+ unsigned int __unused5;
};
+
+struct target_stat64 {
+ uint64_t st_dev;
+ uint64_t st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ uint64_t st_rdev;
+ uint64_t __pad1;
+ int64_t st_size;
+ int st_blksize;
+ int __pad2;
+ int64_t st_blocks;
+ int target_st_atime;
+ unsigned int target_st_atime_nsec;
+ int target_st_mtime;
+ unsigned int target_st_mtime_nsec;
+ int target_st_ctime;
+ unsigned int target_st_ctime_nsec;
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+
#else
#error unsupported CPU
#endif
@@ -2434,8 +2459,11 @@
struct target_epoll_event {
uint32_t events;
+#ifdef TARGET_ARM
+ uint32_t __pad;
+#endif
target_epoll_data_t data;
-};
+} QEMU_PACKED;
#endif
struct target_rlimit64 {
uint64_t rlim_cur;
diff --git a/main-loop.c b/main-loop.c
index a44fff6..1c38ea2 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -131,10 +131,6 @@
GSource *src;
init_clocks();
- if (init_timer_alarm() < 0) {
- fprintf(stderr, "could not initialize alarm timer\n");
- exit(1);
- }
ret = qemu_signal_init();
if (ret) {
@@ -155,10 +151,11 @@
static int glib_pollfds_idx;
static int glib_n_poll_fds;
-static void glib_pollfds_fill(uint32_t *cur_timeout)
+static void glib_pollfds_fill(int64_t *cur_timeout)
{
GMainContext *context = g_main_context_default();
int timeout = 0;
+ int64_t timeout_ns;
int n;
g_main_context_prepare(context, &max_priority);
@@ -174,9 +171,13 @@
glib_n_poll_fds);
} while (n != glib_n_poll_fds);
- if (timeout >= 0 && timeout < *cur_timeout) {
- *cur_timeout = timeout;
+ if (timeout < 0) {
+ timeout_ns = -1;
+ } else {
+ timeout_ns = (int64_t)timeout * (int64_t)SCALE_MS;
}
+
+ *cur_timeout = qemu_soonest_timeout(timeout_ns, *cur_timeout);
}
static void glib_pollfds_poll(void)
@@ -191,7 +192,7 @@
#define MAX_MAIN_LOOP_SPIN (1000)
-static int os_host_main_loop_wait(uint32_t timeout)
+static int os_host_main_loop_wait(int64_t timeout)
{
int ret;
static int spin_counter;
@@ -204,7 +205,7 @@
* print a message to the screen. If we run into this condition, create
* a fake timeout in order to give the VCPU threads a chance to run.
*/
- if (spin_counter > MAX_MAIN_LOOP_SPIN) {
+ if (!timeout && (spin_counter > MAX_MAIN_LOOP_SPIN)) {
static bool notified;
if (!notified) {
@@ -214,19 +215,19 @@
notified = true;
}
- timeout = 1;
+ timeout = SCALE_MS;
}
- if (timeout > 0) {
+ if (timeout) {
spin_counter = 0;
qemu_mutex_unlock_iothread();
} else {
spin_counter++;
}
- ret = g_poll((GPollFD *)gpollfds->data, gpollfds->len, timeout);
+ ret = qemu_poll_ns((GPollFD *)gpollfds->data, gpollfds->len, timeout);
- if (timeout > 0) {
+ if (timeout) {
qemu_mutex_lock_iothread();
}
@@ -373,7 +374,7 @@
}
}
-static int os_host_main_loop_wait(uint32_t timeout)
+static int os_host_main_loop_wait(int64_t timeout)
{
GMainContext *context = g_main_context_default();
GPollFD poll_fds[1024 * 2]; /* this is probably overkill */
@@ -382,6 +383,7 @@
PollingEntry *pe;
WaitObjects *w = &wait_objects;
gint poll_timeout;
+ int64_t poll_timeout_ns;
static struct timeval tv0;
fd_set rfds, wfds, xfds;
int nfds;
@@ -419,12 +421,17 @@
poll_fds[n_poll_fds + i].events = G_IO_IN;
}
- if (poll_timeout < 0 || timeout < poll_timeout) {
- poll_timeout = timeout;
+ if (poll_timeout < 0) {
+ poll_timeout_ns = -1;
+ } else {
+ poll_timeout_ns = (int64_t)poll_timeout * (int64_t)SCALE_MS;
}
+ poll_timeout_ns = qemu_soonest_timeout(poll_timeout_ns, timeout);
+
qemu_mutex_unlock_iothread();
- g_poll_ret = g_poll(poll_fds, n_poll_fds + w->num, poll_timeout);
+ g_poll_ret = qemu_poll_ns(poll_fds, n_poll_fds + w->num, poll_timeout_ns);
+
qemu_mutex_lock_iothread();
if (g_poll_ret > 0) {
for (i = 0; i < w->num; i++) {
@@ -449,6 +456,7 @@
{
int ret;
uint32_t timeout = UINT32_MAX;
+ int64_t timeout_ns;
if (nonblocking) {
timeout = 0;
@@ -462,13 +470,24 @@
slirp_pollfds_fill(gpollfds);
#endif
qemu_iohandler_fill(gpollfds);
- ret = os_host_main_loop_wait(timeout);
+
+ if (timeout == UINT32_MAX) {
+ timeout_ns = -1;
+ } else {
+ timeout_ns = (uint64_t)timeout * (int64_t)(SCALE_MS);
+ }
+
+ timeout_ns = qemu_soonest_timeout(timeout_ns,
+ timerlistgroup_deadline_ns(
+ &main_loop_tlg));
+
+ ret = os_host_main_loop_wait(timeout_ns);
qemu_iohandler_poll(gpollfds, ret);
#ifdef CONFIG_SLIRP
slirp_pollfds_poll(gpollfds, (ret < 0));
#endif
- qemu_run_all_timers();
+ qemu_clock_run_all_timers();
return ret;
}
@@ -489,17 +508,14 @@
void qemu_aio_set_fd_handler(int fd,
IOHandler *io_read,
IOHandler *io_write,
- AioFlushHandler *io_flush,
void *opaque)
{
- aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, io_flush,
- opaque);
+ aio_set_fd_handler(qemu_aio_context, fd, io_read, io_write, opaque);
}
#endif
void qemu_aio_set_event_notifier(EventNotifier *notifier,
- EventNotifierHandler *io_read,
- AioFlushEventNotifierHandler *io_flush)
+ EventNotifierHandler *io_read)
{
- aio_set_event_notifier(qemu_aio_context, notifier, io_read, io_flush);
+ aio_set_event_notifier(qemu_aio_context, notifier, io_read);
}
diff --git a/memory.c b/memory.c
index 01846c9..886f838 100644
--- a/memory.c
+++ b/memory.c
@@ -18,7 +18,7 @@
#include "exec/ioport.h"
#include "qemu/bitops.h"
#include "qom/object.h"
-#include "sysemu/kvm.h"
+#include "trace.h"
#include <assert.h>
#include "exec/memory-internal.h"
@@ -339,65 +339,104 @@
}
}
-static void memory_region_oldmmio_read_accessor(void *opaque,
+static bool memory_region_big_endian(MemoryRegion *mr)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ return mr->ops->endianness != DEVICE_LITTLE_ENDIAN;
+#else
+ return mr->ops->endianness == DEVICE_BIG_ENDIAN;
+#endif
+}
+
+static bool memory_region_wrong_endianness(MemoryRegion *mr)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ return mr->ops->endianness == DEVICE_LITTLE_ENDIAN;
+#else
+ return mr->ops->endianness == DEVICE_BIG_ENDIAN;
+#endif
+}
+
+static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
+{
+ if (memory_region_wrong_endianness(mr)) {
+ switch (size) {
+ case 1:
+ break;
+ case 2:
+ *data = bswap16(*data);
+ break;
+ case 4:
+ *data = bswap32(*data);
+ break;
+ case 8:
+ *data = bswap64(*data);
+ break;
+ default:
+ abort();
+ }
+ }
+}
+
+static void memory_region_oldmmio_read_accessor(MemoryRegion *mr,
hwaddr addr,
uint64_t *value,
unsigned size,
unsigned shift,
uint64_t mask)
{
- MemoryRegion *mr = opaque;
uint64_t tmp;
tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);
+ trace_memory_region_ops_read(mr, addr, tmp, size);
*value |= (tmp & mask) << shift;
}
-static void memory_region_read_accessor(void *opaque,
+static void memory_region_read_accessor(MemoryRegion *mr,
hwaddr addr,
uint64_t *value,
unsigned size,
unsigned shift,
uint64_t mask)
{
- MemoryRegion *mr = opaque;
uint64_t tmp;
if (mr->flush_coalesced_mmio) {
qemu_flush_coalesced_mmio_buffer();
}
tmp = mr->ops->read(mr->opaque, addr, size);
+ trace_memory_region_ops_read(mr, addr, tmp, size);
*value |= (tmp & mask) << shift;
}
-static void memory_region_oldmmio_write_accessor(void *opaque,
+static void memory_region_oldmmio_write_accessor(MemoryRegion *mr,
hwaddr addr,
uint64_t *value,
unsigned size,
unsigned shift,
uint64_t mask)
{
- MemoryRegion *mr = opaque;
uint64_t tmp;
tmp = (*value >> shift) & mask;
+ trace_memory_region_ops_write(mr, addr, tmp, size);
mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp);
}
-static void memory_region_write_accessor(void *opaque,
+static void memory_region_write_accessor(MemoryRegion *mr,
hwaddr addr,
uint64_t *value,
unsigned size,
unsigned shift,
uint64_t mask)
{
- MemoryRegion *mr = opaque;
uint64_t tmp;
if (mr->flush_coalesced_mmio) {
qemu_flush_coalesced_mmio_buffer();
}
tmp = (*value >> shift) & mask;
+ trace_memory_region_ops_write(mr, addr, tmp, size);
mr->ops->write(mr->opaque, addr, tmp, size);
}
@@ -406,13 +445,13 @@
unsigned size,
unsigned access_size_min,
unsigned access_size_max,
- void (*access)(void *opaque,
+ void (*access)(MemoryRegion *mr,
hwaddr addr,
uint64_t *value,
unsigned size,
unsigned shift,
uint64_t mask),
- void *opaque)
+ MemoryRegion *mr)
{
uint64_t access_mask;
unsigned access_size;
@@ -428,13 +467,15 @@
/* FIXME: support unaligned access? */
access_size = MAX(MIN(size, access_size_max), access_size_min);
access_mask = -1ULL >> (64 - access_size * 8);
- for (i = 0; i < size; i += access_size) {
-#ifdef TARGET_WORDS_BIGENDIAN
- access(opaque, addr + i, value, access_size,
- (size - access_size - i) * 8, access_mask);
-#else
- access(opaque, addr + i, value, access_size, i * 8, access_mask);
-#endif
+ if (memory_region_big_endian(mr)) {
+ for (i = 0; i < size; i += access_size) {
+ access(mr, addr + i, value, access_size,
+ (size - access_size - i) * 8, access_mask);
+ }
+ } else {
+ for (i = 0; i < size; i += access_size) {
+ access(mr, addr + i, value, access_size, i * 8, access_mask);
+ }
}
}
@@ -786,15 +827,6 @@
qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
}
-static bool memory_region_wrong_endianness(MemoryRegion *mr)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- return mr->ops->endianness == DEVICE_LITTLE_ENDIAN;
-#else
- return mr->ops->endianness == DEVICE_BIG_ENDIAN;
-#endif
-}
-
void memory_region_init(MemoryRegion *mr,
Object *owner,
const char *name,
@@ -921,27 +953,6 @@
return data;
}
-static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
-{
- if (memory_region_wrong_endianness(mr)) {
- switch (size) {
- case 1:
- break;
- case 2:
- *data = bswap16(*data);
- break;
- case 4:
- *data = bswap32(*data);
- break;
- case 8:
- *data = bswap64(*data);
- break;
- default:
- abort();
- }
- }
-}
-
static bool memory_region_dispatch_read(MemoryRegion *mr,
hwaddr addr,
uint64_t *pval,
diff --git a/memory_mapping.c b/memory_mapping.c
index 515a984..eeeeb44 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -11,9 +11,15 @@
*
*/
+#include <glib.h>
+
#include "cpu.h"
#include "exec/cpu-all.h"
#include "sysemu/memory_mapping.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+
+//#define DEBUG_GUEST_PHYS_REGION_ADD
static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list,
MemoryMapping *mapping)
@@ -165,6 +171,101 @@
QTAILQ_INIT(&list->head);
}
+void guest_phys_blocks_free(GuestPhysBlockList *list)
+{
+ GuestPhysBlock *p, *q;
+
+ QTAILQ_FOREACH_SAFE(p, &list->head, next, q) {
+ QTAILQ_REMOVE(&list->head, p, next);
+ g_free(p);
+ }
+ list->num = 0;
+}
+
+void guest_phys_blocks_init(GuestPhysBlockList *list)
+{
+ list->num = 0;
+ QTAILQ_INIT(&list->head);
+}
+
+typedef struct GuestPhysListener {
+ GuestPhysBlockList *list;
+ MemoryListener listener;
+} GuestPhysListener;
+
+static void guest_phys_blocks_region_add(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ GuestPhysListener *g;
+ uint64_t section_size;
+ hwaddr target_start, target_end;
+ uint8_t *host_addr;
+ GuestPhysBlock *predecessor;
+
+ /* we only care about RAM */
+ if (!memory_region_is_ram(section->mr)) {
+ return;
+ }
+
+ g = container_of(listener, GuestPhysListener, listener);
+ section_size = int128_get64(section->size);
+ target_start = section->offset_within_address_space;
+ target_end = target_start + section_size;
+ host_addr = memory_region_get_ram_ptr(section->mr) +
+ section->offset_within_region;
+ predecessor = NULL;
+
+ /* find continuity in guest physical address space */
+ if (!QTAILQ_EMPTY(&g->list->head)) {
+ hwaddr predecessor_size;
+
+ predecessor = QTAILQ_LAST(&g->list->head, GuestPhysBlockHead);
+ predecessor_size = predecessor->target_end - predecessor->target_start;
+
+ /* the memory API guarantees monotonically increasing traversal */
+ g_assert(predecessor->target_end <= target_start);
+
+ /* we want continuity in both guest-physical and host-virtual memory */
+ if (predecessor->target_end < target_start ||
+ predecessor->host_addr + predecessor_size != host_addr) {
+ predecessor = NULL;
+ }
+ }
+
+ if (predecessor == NULL) {
+ /* isolated mapping, allocate it and add it to the list */
+ GuestPhysBlock *block = g_malloc0(sizeof *block);
+
+ block->target_start = target_start;
+ block->target_end = target_end;
+ block->host_addr = host_addr;
+
+ QTAILQ_INSERT_TAIL(&g->list->head, block, next);
+ ++g->list->num;
+ } else {
+ /* expand predecessor until @target_end; predecessor's start doesn't
+ * change
+ */
+ predecessor->target_end = target_end;
+ }
+
+#ifdef DEBUG_GUEST_PHYS_REGION_ADD
+ fprintf(stderr, "%s: target_start=" TARGET_FMT_plx " target_end="
+ TARGET_FMT_plx ": %s (count: %u)\n", __FUNCTION__, target_start,
+ target_end, predecessor ? "joined" : "added", g->list->num);
+#endif
+}
+
+void guest_phys_blocks_append(GuestPhysBlockList *list)
+{
+ GuestPhysListener g = { 0 };
+
+ g.list = list;
+ g.listener.region_add = &guest_phys_blocks_region_add;
+ memory_listener_register(&g.listener, &address_space_memory);
+ memory_listener_unregister(&g.listener);
+}
+
static CPUState *find_paging_enabled_cpu(CPUState *start_cpu)
{
CPUState *cpu;
@@ -178,10 +279,12 @@
return NULL;
}
-void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp)
+void qemu_get_guest_memory_mapping(MemoryMappingList *list,
+ const GuestPhysBlockList *guest_phys_blocks,
+ Error **errp)
{
CPUState *cpu, *first_paging_enabled_cpu;
- RAMBlock *block;
+ GuestPhysBlock *block;
ram_addr_t offset, length;
first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu);
@@ -201,19 +304,21 @@
* If the guest doesn't use paging, the virtual address is equal to physical
* address.
*/
- QTAILQ_FOREACH(block, &ram_list.blocks, next) {
- offset = block->offset;
- length = block->length;
+ QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) {
+ offset = block->target_start;
+ length = block->target_end - block->target_start;
create_new_memory_mapping(list, offset, offset, length);
}
}
-void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list,
+ const GuestPhysBlockList *guest_phys_blocks)
{
- RAMBlock *block;
+ GuestPhysBlock *block;
- QTAILQ_FOREACH(block, &ram_list.blocks, next) {
- create_new_memory_mapping(list, block->offset, 0, block->length);
+ QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) {
+ create_new_memory_mapping(list, block->target_start, 0,
+ block->target_end - block->target_start);
}
}
diff --git a/migration-exec.c b/migration-exec.c
index deab4e3..4790247 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -17,6 +17,7 @@
#include "qemu-common.h"
#include "qemu/sockets.h"
+#include "qemu/main-loop.h"
#include "migration/migration.h"
#include "migration/qemu-file.h"
#include "block/block.h"
diff --git a/migration-fd.c b/migration-fd.c
index 3d4613c..d2e523a 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -14,6 +14,7 @@
*/
#include "qemu-common.h"
+#include "qemu/main-loop.h"
#include "qemu/sockets.h"
#include "migration/migration.h"
#include "monitor/monitor.h"
diff --git a/migration-rdma.c b/migration-rdma.c
index d044830..3d1266f 100644
--- a/migration-rdma.c
+++ b/migration-rdma.c
@@ -27,7 +27,7 @@
#include <string.h>
#include <rdma/rdma_cma.h>
-#define DEBUG_RDMA
+//#define DEBUG_RDMA
//#define DEBUG_RDMA_VERBOSE
//#define DEBUG_RDMA_REALLY_VERBOSE
@@ -60,7 +60,7 @@
*/
#define ERROR(errp, fmt, ...) \
do { \
- fprintf(stderr, "RDMA ERROR: " fmt, ## __VA_ARGS__); \
+ fprintf(stderr, "RDMA ERROR: " fmt "\n", ## __VA_ARGS__); \
if (errp && (*(errp) == NULL)) { \
error_setg(errp, "RDMA ERROR: " fmt, ## __VA_ARGS__); \
} \
@@ -322,7 +322,7 @@
char *host;
int port;
- RDMAWorkRequestData wr_data[RDMA_WRID_MAX + 1];
+ RDMAWorkRequestData wr_data[RDMA_WRID_MAX];
/*
* This is used by *_exchange_send() to figure out whether or not
@@ -707,15 +707,27 @@
*/
static void qemu_rdma_dump_id(const char *who, struct ibv_context *verbs)
{
+ struct ibv_port_attr port;
+
+ if (ibv_query_port(verbs, 1, &port)) {
+ fprintf(stderr, "FAILED TO QUERY PORT INFORMATION!\n");
+ return;
+ }
+
printf("%s RDMA Device opened: kernel name %s "
"uverbs device name %s, "
- "infiniband_verbs class device path %s,"
- " infiniband class device path %s\n",
+ "infiniband_verbs class device path %s, "
+ "infiniband class device path %s, "
+ "transport: (%d) %s\n",
who,
verbs->device->name,
verbs->device->dev_name,
verbs->device->dev_path,
- verbs->device->ibdev_path);
+ verbs->device->ibdev_path,
+ port.link_layer,
+ (port.link_layer == IBV_LINK_LAYER_INFINIBAND) ? "Infiniband" :
+ ((port.link_layer == IBV_LINK_LAYER_ETHERNET)
+ ? "Ethernet" : "Unknown"));
}
/*
@@ -733,6 +745,132 @@
}
/*
+ * As of now, IPv6 over RoCE / iWARP is not supported by linux.
+ * We will try the next addrinfo struct, and fail if there are
+ * no other valid addresses to bind against.
+ *
+ * If user is listening on '[::]', then we will not have a opened a device
+ * yet and have no way of verifying if the device is RoCE or not.
+ *
+ * In this case, the source VM will throw an error for ALL types of
+ * connections (both IPv4 and IPv6) if the destination machine does not have
+ * a regular infiniband network available for use.
+ *
+ * The only way to gaurantee that an error is thrown for broken kernels is
+ * for the management software to choose a *specific* interface at bind time
+ * and validate what time of hardware it is.
+ *
+ * Unfortunately, this puts the user in a fix:
+ *
+ * If the source VM connects with an IPv4 address without knowing that the
+ * destination has bound to '[::]' the migration will unconditionally fail
+ * unless the management software is explicitly listening on the the IPv4
+ * address while using a RoCE-based device.
+ *
+ * If the source VM connects with an IPv6 address, then we're OK because we can
+ * throw an error on the source (and similarly on the destination).
+ *
+ * But in mixed environments, this will be broken for a while until it is fixed
+ * inside linux.
+ *
+ * We do provide a *tiny* bit of help in this function: We can list all of the
+ * devices in the system and check to see if all the devices are RoCE or
+ * Infiniband.
+ *
+ * If we detect that we have a *pure* RoCE environment, then we can safely
+ * thrown an error even if the management sofware has specified '[::]' as the
+ * bind address.
+ *
+ * However, if there is are multiple hetergeneous devices, then we cannot make
+ * this assumption and the user just has to be sure they know what they are
+ * doing.
+ *
+ * Patches are being reviewed on linux-rdma.
+ */
+static int qemu_rdma_broken_ipv6_kernel(Error **errp, struct ibv_context *verbs)
+{
+ struct ibv_port_attr port_attr;
+
+ /* This bug only exists in linux, to our knowledge. */
+#ifdef CONFIG_LINUX
+
+ /*
+ * Verbs are only NULL if management has bound to '[::]'.
+ *
+ * Let's iterate through all the devices and see if there any pure IB
+ * devices (non-ethernet).
+ *
+ * If not, then we can safely proceed with the migration.
+ * Otherwise, there are no gaurantees until the bug is fixed in linux.
+ */
+ if (!verbs) {
+ int num_devices, x;
+ struct ibv_device ** dev_list = ibv_get_device_list(&num_devices);
+ bool roce_found = false;
+ bool ib_found = false;
+
+ for (x = 0; x < num_devices; x++) {
+ verbs = ibv_open_device(dev_list[x]);
+
+ if (ibv_query_port(verbs, 1, &port_attr)) {
+ ibv_close_device(verbs);
+ ERROR(errp, "Could not query initial IB port");
+ return -EINVAL;
+ }
+
+ if (port_attr.link_layer == IBV_LINK_LAYER_INFINIBAND) {
+ ib_found = true;
+ } else if (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET) {
+ roce_found = true;
+ }
+
+ ibv_close_device(verbs);
+
+ }
+
+ if (roce_found) {
+ if (ib_found) {
+ fprintf(stderr, "WARN: migrations may fail:"
+ " IPv6 over RoCE / iWARP in linux"
+ " is broken. But since you appear to have a"
+ " mixed RoCE / IB environment, be sure to only"
+ " migrate over the IB fabric until the kernel "
+ " fixes the bug.\n");
+ } else {
+ ERROR(errp, "You only have RoCE / iWARP devices in your systems"
+ " and your management software has specified '[::]'"
+ ", but IPv6 over RoCE / iWARP is not supported in Linux.");
+ return -ENONET;
+ }
+ }
+
+ return 0;
+ }
+
+ /*
+ * If we have a verbs context, that means that some other than '[::]' was
+ * used by the management software for binding. In which case we can actually
+ * warn the user about a potential broken kernel;
+ */
+
+ /* IB ports start with 1, not 0 */
+ if (ibv_query_port(verbs, 1, &port_attr)) {
+ ERROR(errp, "Could not query initial IB port");
+ return -EINVAL;
+ }
+
+ if (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET) {
+ ERROR(errp, "Linux kernel's RoCE / iWARP does not support IPv6 "
+ "(but patches on linux-rdma in progress)");
+ return -ENONET;
+ }
+
+#endif
+
+ return 0;
+}
+
+/*
* Figure out which RDMA device corresponds to the requested IP hostname
* Also create the initial connection manager identifiers for opening
* the connection.
@@ -740,63 +878,73 @@
static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
{
int ret;
- struct addrinfo *res;
+ struct rdma_addrinfo *res;
char port_str[16];
struct rdma_cm_event *cm_event;
char ip[40] = "unknown";
+ struct rdma_addrinfo *e;
if (rdma->host == NULL || !strcmp(rdma->host, "")) {
- ERROR(errp, "RDMA hostname has not been set\n");
- return -1;
+ ERROR(errp, "RDMA hostname has not been set");
+ return -EINVAL;
}
/* create CM channel */
rdma->channel = rdma_create_event_channel();
if (!rdma->channel) {
- ERROR(errp, "could not create CM channel\n");
- return -1;
+ ERROR(errp, "could not create CM channel");
+ return -EINVAL;
}
/* create CM id */
ret = rdma_create_id(rdma->channel, &rdma->cm_id, NULL, RDMA_PS_TCP);
if (ret) {
- ERROR(errp, "could not create channel id\n");
+ ERROR(errp, "could not create channel id");
goto err_resolve_create_id;
}
snprintf(port_str, 16, "%d", rdma->port);
port_str[15] = '\0';
- ret = getaddrinfo(rdma->host, port_str, NULL, &res);
+ ret = rdma_getaddrinfo(rdma->host, port_str, NULL, &res);
if (ret < 0) {
- ERROR(errp, "could not getaddrinfo address %s\n", rdma->host);
+ ERROR(errp, "could not rdma_getaddrinfo address %s", rdma->host);
goto err_resolve_get_addr;
}
- inet_ntop(AF_INET, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
- ip, sizeof ip);
- DPRINTF("%s => %s\n", rdma->host, ip);
+ for (e = res; e != NULL; e = e->ai_next) {
+ inet_ntop(e->ai_family,
+ &((struct sockaddr_in *) e->ai_dst_addr)->sin_addr, ip, sizeof ip);
+ DPRINTF("Trying %s => %s\n", rdma->host, ip);
- /* resolve the first address */
- ret = rdma_resolve_addr(rdma->cm_id, NULL, res->ai_addr,
- RDMA_RESOLVE_TIMEOUT_MS);
- if (ret) {
- ERROR(errp, "could not resolve address %s\n", rdma->host);
- goto err_resolve_get_addr;
+ ret = rdma_resolve_addr(rdma->cm_id, NULL, e->ai_dst_addr,
+ RDMA_RESOLVE_TIMEOUT_MS);
+ if (!ret) {
+ ret = qemu_rdma_broken_ipv6_kernel(errp, rdma->cm_id->verbs);
+ if (ret) {
+ continue;
+ }
+ goto route;
+ }
}
+ ERROR(errp, "could not resolve address %s", rdma->host);
+ goto err_resolve_get_addr;
+
+route:
qemu_rdma_dump_gid("source_resolve_addr", rdma->cm_id);
ret = rdma_get_cm_event(rdma->channel, &cm_event);
if (ret) {
- ERROR(errp, "could not perform event_addr_resolved\n");
+ ERROR(errp, "could not perform event_addr_resolved");
goto err_resolve_get_addr;
}
if (cm_event->event != RDMA_CM_EVENT_ADDR_RESOLVED) {
- ERROR(errp, "result not equal to event_addr_resolved %s\n",
+ ERROR(errp, "result not equal to event_addr_resolved %s",
rdma_event_str(cm_event->event));
perror("rdma_resolve_addr");
+ ret = -EINVAL;
goto err_resolve_get_addr;
}
rdma_ack_cm_event(cm_event);
@@ -804,19 +952,20 @@
/* resolve route */
ret = rdma_resolve_route(rdma->cm_id, RDMA_RESOLVE_TIMEOUT_MS);
if (ret) {
- ERROR(errp, "could not resolve rdma route\n");
+ ERROR(errp, "could not resolve rdma route");
goto err_resolve_get_addr;
}
ret = rdma_get_cm_event(rdma->channel, &cm_event);
if (ret) {
- ERROR(errp, "could not perform event_route_resolved\n");
+ ERROR(errp, "could not perform event_route_resolved");
goto err_resolve_get_addr;
}
if (cm_event->event != RDMA_CM_EVENT_ROUTE_RESOLVED) {
- ERROR(errp, "result not equal to event_route_resolved: %s\n",
+ ERROR(errp, "result not equal to event_route_resolved: %s",
rdma_event_str(cm_event->event));
rdma_ack_cm_event(cm_event);
+ ret = -EINVAL;
goto err_resolve_get_addr;
}
rdma_ack_cm_event(cm_event);
@@ -831,8 +980,7 @@
err_resolve_create_id:
rdma_destroy_event_channel(rdma->channel);
rdma->channel = NULL;
-
- return -1;
+ return ret;
}
/*
@@ -1212,7 +1360,8 @@
* (of any kind) has completed.
* Return the work request ID that completed.
*/
-static uint64_t qemu_rdma_poll(RDMAContext *rdma, uint64_t *wr_id_out)
+static uint64_t qemu_rdma_poll(RDMAContext *rdma, uint64_t *wr_id_out,
+ uint32_t *byte_len)
{
int ret;
struct ibv_wc wc;
@@ -1283,6 +1432,9 @@
}
*wr_id_out = wc.wr_id;
+ if (byte_len) {
+ *byte_len = wc.byte_len;
+ }
return 0;
}
@@ -1300,7 +1452,8 @@
* completions only need to be recorded, but do not actually
* need further processing.
*/
-static int qemu_rdma_block_for_wrid(RDMAContext *rdma, int wrid_requested)
+static int qemu_rdma_block_for_wrid(RDMAContext *rdma, int wrid_requested,
+ uint32_t *byte_len)
{
int num_cq_events = 0, ret = 0;
struct ibv_cq *cq;
@@ -1312,7 +1465,7 @@
}
/* poll cq first */
while (wr_id != wrid_requested) {
- ret = qemu_rdma_poll(rdma, &wr_id_in);
+ ret = qemu_rdma_poll(rdma, &wr_id_in, byte_len);
if (ret < 0) {
return ret;
}
@@ -1354,7 +1507,7 @@
}
while (wr_id != wrid_requested) {
- ret = qemu_rdma_poll(rdma, &wr_id_in);
+ ret = qemu_rdma_poll(rdma, &wr_id_in, byte_len);
if (ret < 0) {
goto err_block_for_wrid;
}
@@ -1397,7 +1550,7 @@
RDMAControlHeader *head)
{
int ret = 0;
- RDMAWorkRequestData *wr = &rdma->wr_data[RDMA_WRID_MAX];
+ RDMAWorkRequestData *wr = &rdma->wr_data[RDMA_WRID_CONTROL];
struct ibv_send_wr *bad_wr;
struct ibv_sge sge = {
.addr = (uint64_t)(wr->control),
@@ -1422,6 +1575,7 @@
* The copy makes the RDMAControlHeader simpler to manipulate
* for the time being.
*/
+ assert(head->len <= RDMA_CONTROL_MAX_BUFFER - sizeof(*head));
memcpy(wr->control, head, sizeof(RDMAControlHeader));
control_to_network((void *) wr->control);
@@ -1439,7 +1593,7 @@
return ret;
}
- ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_SEND_CONTROL);
+ ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_SEND_CONTROL, NULL);
if (ret < 0) {
fprintf(stderr, "rdma migration: send polling control error!\n");
}
@@ -1480,7 +1634,9 @@
static int qemu_rdma_exchange_get_response(RDMAContext *rdma,
RDMAControlHeader *head, int expecting, int idx)
{
- int ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RECV_CONTROL + idx);
+ uint32_t byte_len;
+ int ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RECV_CONTROL + idx,
+ &byte_len);
if (ret < 0) {
fprintf(stderr, "rdma migration: recv polling control error!\n");
@@ -1502,6 +1658,15 @@
control_desc[head->type], head->type, head->len);
return -EIO;
}
+ if (head->len > RDMA_CONTROL_MAX_BUFFER - sizeof(*head)) {
+ fprintf(stderr, "too long length: %d\n", head->len);
+ return -EINVAL;
+ }
+ if (sizeof(*head) + head->len != byte_len) {
+ fprintf(stderr, "Malformed length: %d byte_len %d\n",
+ head->len, byte_len);
+ return -EINVAL;
+ }
return 0;
}
@@ -1731,7 +1896,7 @@
count++, current_index, chunk,
sge.addr, length, rdma->nb_sent, block->nb_chunks);
- ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE);
+ ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE, NULL);
if (ret < 0) {
fprintf(stderr, "Failed to Wait for previous write to complete "
@@ -1875,7 +2040,7 @@
if (ret == ENOMEM) {
DDPRINTF("send queue is full. wait a little....\n");
- ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE);
+ ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE, NULL);
if (ret < 0) {
fprintf(stderr, "rdma migration: failed to make "
"room in full send queue! %d\n", ret);
@@ -1931,10 +2096,21 @@
static inline int qemu_rdma_buffer_mergable(RDMAContext *rdma,
uint64_t offset, uint64_t len)
{
- RDMALocalBlock *block =
- &(rdma->local_ram_blocks.block[rdma->current_index]);
- uint8_t *host_addr = block->local_host_addr + (offset - block->offset);
- uint8_t *chunk_end = ram_chunk_end(block, rdma->current_chunk);
+ RDMALocalBlock *block;
+ uint8_t *host_addr;
+ uint8_t *chunk_end;
+
+ if (rdma->current_index < 0) {
+ return 0;
+ }
+
+ if (rdma->current_chunk < 0) {
+ return 0;
+ }
+
+ block = &(rdma->local_ram_blocks.block[rdma->current_index]);
+ host_addr = block->local_host_addr + (offset - block->offset);
+ chunk_end = ram_chunk_end(block, rdma->current_chunk);
if (rdma->current_length == 0) {
return 0;
@@ -1947,10 +2123,6 @@
return 0;
}
- if (rdma->current_index < 0) {
- return 0;
- }
-
if (offset < block->offset) {
return 0;
}
@@ -1959,10 +2131,6 @@
return 0;
}
- if (rdma->current_chunk < 0) {
- return 0;
- }
-
if ((host_addr + len) > chunk_end) {
return 0;
}
@@ -2049,7 +2217,7 @@
g_free(rdma->block);
rdma->block = NULL;
- for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
+ for (idx = 0; idx < RDMA_WRID_MAX; idx++) {
if (rdma->wr_data[idx].control_mr) {
rdma->total_registrations--;
ibv_dereg_mr(rdma->wr_data[idx].control_mr);
@@ -2092,6 +2260,8 @@
rdma_destroy_event_channel(rdma->channel);
rdma->channel = NULL;
}
+ g_free(rdma->host);
+ rdma->host = NULL;
}
@@ -2115,26 +2285,26 @@
if (ret) {
ERROR(temp, "rdma migration: error allocating pd and cq! Your mlock()"
" limits may be too low. Please check $ ulimit -a # and "
- "search for 'ulimit -l' in the output\n");
+ "search for 'ulimit -l' in the output");
goto err_rdma_source_init;
}
ret = qemu_rdma_alloc_qp(rdma);
if (ret) {
- ERROR(temp, "rdma migration: error allocating qp!\n");
+ ERROR(temp, "rdma migration: error allocating qp!");
goto err_rdma_source_init;
}
ret = qemu_rdma_init_ram_blocks(rdma);
if (ret) {
- ERROR(temp, "rdma migration: error initializing ram blocks!\n");
+ ERROR(temp, "rdma migration: error initializing ram blocks!");
goto err_rdma_source_init;
}
- for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
+ for (idx = 0; idx < RDMA_WRID_MAX; idx++) {
ret = qemu_rdma_reg_control(rdma, idx);
if (ret) {
- ERROR(temp, "rdma migration: error registering %d control!\n",
+ ERROR(temp, "rdma migration: error registering %d control!",
idx);
goto err_rdma_source_init;
}
@@ -2176,7 +2346,7 @@
ret = rdma_connect(rdma->cm_id, &conn_param);
if (ret) {
perror("rdma_connect");
- ERROR(errp, "connecting to destination!\n");
+ ERROR(errp, "connecting to destination!");
rdma_destroy_id(rdma->cm_id);
rdma->cm_id = NULL;
goto err_rdma_source_connect;
@@ -2185,7 +2355,7 @@
ret = rdma_get_cm_event(rdma->channel, &cm_event);
if (ret) {
perror("rdma_get_cm_event after rdma_connect");
- ERROR(errp, "connecting to destination!\n");
+ ERROR(errp, "connecting to destination!");
rdma_ack_cm_event(cm_event);
rdma_destroy_id(rdma->cm_id);
rdma->cm_id = NULL;
@@ -2194,7 +2364,7 @@
if (cm_event->event != RDMA_CM_EVENT_ESTABLISHED) {
perror("rdma_get_cm_event != EVENT_ESTABLISHED after rdma_connect");
- ERROR(errp, "connecting to destination!\n");
+ ERROR(errp, "connecting to destination!");
rdma_ack_cm_event(cm_event);
rdma_destroy_id(rdma->cm_id);
rdma->cm_id = NULL;
@@ -2210,7 +2380,7 @@
*/
if (rdma->pin_all && !(cap.flags & RDMA_CAPABILITY_PIN_ALL)) {
ERROR(errp, "Server cannot support pinning all memory. "
- "Will register memory dynamically.\n");
+ "Will register memory dynamically.");
rdma->pin_all = false;
}
@@ -2218,9 +2388,9 @@
rdma_ack_cm_event(cm_event);
- ret = qemu_rdma_post_recv_control(rdma, 0);
+ ret = qemu_rdma_post_recv_control(rdma, RDMA_WRID_READY);
if (ret) {
- ERROR(errp, "posting second control recv!\n");
+ ERROR(errp, "posting second control recv!");
goto err_rdma_source_connect;
}
@@ -2236,24 +2406,25 @@
static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
{
int ret = -EINVAL, idx;
- struct sockaddr_in sin;
struct rdma_cm_id *listen_id;
char ip[40] = "unknown";
+ struct rdma_addrinfo *res;
+ char port_str[16];
- for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
+ for (idx = 0; idx < RDMA_WRID_MAX; idx++) {
rdma->wr_data[idx].control_len = 0;
rdma->wr_data[idx].control_curr = NULL;
}
if (rdma->host == NULL) {
- ERROR(errp, "RDMA host is not set!\n");
+ ERROR(errp, "RDMA host is not set!");
rdma->error_state = -EINVAL;
return -1;
}
/* create CM channel */
rdma->channel = rdma_create_event_channel();
if (!rdma->channel) {
- ERROR(errp, "could not create rdma event channel\n");
+ ERROR(errp, "could not create rdma event channel");
rdma->error_state = -EINVAL;
return -1;
}
@@ -2261,36 +2432,47 @@
/* create CM id */
ret = rdma_create_id(rdma->channel, &listen_id, NULL, RDMA_PS_TCP);
if (ret) {
- ERROR(errp, "could not create cm_id!\n");
+ ERROR(errp, "could not create cm_id!");
goto err_dest_init_create_listen_id;
}
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_port = htons(rdma->port);
+ snprintf(port_str, 16, "%d", rdma->port);
+ port_str[15] = '\0';
if (rdma->host && strcmp("", rdma->host)) {
- struct hostent *dest_addr;
- dest_addr = gethostbyname(rdma->host);
- if (!dest_addr) {
- ERROR(errp, "migration could not gethostbyname!\n");
- ret = -EINVAL;
+ struct rdma_addrinfo *e;
+
+ ret = rdma_getaddrinfo(rdma->host, port_str, NULL, &res);
+ if (ret < 0) {
+ ERROR(errp, "could not rdma_getaddrinfo address %s", rdma->host);
goto err_dest_init_bind_addr;
}
- memcpy(&sin.sin_addr.s_addr, dest_addr->h_addr,
- dest_addr->h_length);
- inet_ntop(AF_INET, dest_addr->h_addr, ip, sizeof ip);
+
+ for (e = res; e != NULL; e = e->ai_next) {
+ inet_ntop(e->ai_family,
+ &((struct sockaddr_in *) e->ai_dst_addr)->sin_addr, ip, sizeof ip);
+ DPRINTF("Trying %s => %s\n", rdma->host, ip);
+ ret = rdma_bind_addr(listen_id, e->ai_dst_addr);
+ if (!ret) {
+ if (e->ai_family == AF_INET6) {
+ ret = qemu_rdma_broken_ipv6_kernel(errp, listen_id->verbs);
+ if (ret) {
+ continue;
+ }
+ }
+
+ goto listen;
+ }
+ }
+
+ ERROR(errp, "Error: could not rdma_bind_addr!");
+ goto err_dest_init_bind_addr;
} else {
- sin.sin_addr.s_addr = INADDR_ANY;
- }
-
- DPRINTF("%s => %s\n", rdma->host, ip);
-
- ret = rdma_bind_addr(listen_id, (struct sockaddr *)&sin);
- if (ret) {
- ERROR(errp, "Error: could not rdma_bind_addr!\n");
+ ERROR(errp, "migration host and port not specified!");
+ ret = -EINVAL;
goto err_dest_init_bind_addr;
}
+listen:
rdma->listen_id = listen_id;
qemu_rdma_dump_gid("dest_init", listen_id);
@@ -2452,7 +2634,7 @@
}
while (rdma->nb_sent) {
- ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE);
+ ret = qemu_rdma_block_for_wrid(rdma, RDMA_WRID_RDMA_WRITE, NULL);
if (ret < 0) {
fprintf(stderr, "rdma migration: complete polling error!\n");
return -EIO;
@@ -2494,7 +2676,7 @@
* @size == 0 :
* A 'hint' or 'advice' that means that we wish to speculatively
* and asynchronously unregister this memory. In this case, there is no
- * gaurantee that the unregister will actually happen, for example,
+ * guarantee that the unregister will actually happen, for example,
* if the memory is being actively transmitted. Additionally, the memory
* may be re-registered at any future time if a write within the same
* chunk was requested again, even if you attempted to unregister it
@@ -2570,7 +2752,7 @@
qemu_rdma_signal_unregister(rdma, index, chunk, 0);
/*
- * TODO: Synchronous, gauranteed unregistration (should not occur during
+ * TODO: Synchronous, guaranteed unregistration (should not occur during
* fast-path). Otherwise, unregisters will process on the next call to
* qemu_rdma_drain_cq()
if (size < 0) {
@@ -2588,7 +2770,7 @@
*/
while (1) {
uint64_t wr_id, wr_id_in;
- int ret = qemu_rdma_poll(rdma, &wr_id_in);
+ int ret = qemu_rdma_poll(rdma, &wr_id_in, NULL);
if (ret < 0) {
fprintf(stderr, "rdma migration: polling error! %d\n", ret);
goto err;
@@ -2693,7 +2875,7 @@
goto err_rdma_dest_wait;
}
- for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
+ for (idx = 0; idx < RDMA_WRID_MAX; idx++) {
ret = qemu_rdma_reg_control(rdma, idx);
if (ret) {
fprintf(stderr, "rdma: error registering %d control!\n", idx);
@@ -2723,7 +2905,7 @@
rdma_ack_cm_event(cm_event);
- ret = qemu_rdma_post_recv_control(rdma, 0);
+ ret = qemu_rdma_post_recv_control(rdma, RDMA_WRID_READY);
if (ret) {
fprintf(stderr, "rdma migration: error posting second control recv!\n");
goto err_rdma_dest_wait;
@@ -3027,14 +3209,10 @@
®_result_idx, rdma->pin_all ?
qemu_rdma_reg_whole_ram_blocks : NULL);
if (ret < 0) {
- ERROR(errp, "receiving remote info!\n");
+ ERROR(errp, "receiving remote info!");
return ret;
}
- qemu_rdma_move_header(rdma, reg_result_idx, &resp);
- memcpy(rdma->block,
- rdma->wr_data[reg_result_idx].control_curr, resp.len);
-
nb_remote_blocks = resp.len / sizeof(RDMARemoteBlock);
/*
@@ -3052,10 +3230,13 @@
if (local->nb_blocks != nb_remote_blocks) {
ERROR(errp, "ram blocks mismatch #1! "
"Your QEMU command line parameters are probably "
- "not identical on both the source and destination.\n");
+ "not identical on both the source and destination.");
return -EINVAL;
}
+ qemu_rdma_move_header(rdma, reg_result_idx, &resp);
+ memcpy(rdma->block,
+ rdma->wr_data[reg_result_idx].control_curr, resp.len);
for (i = 0; i < nb_remote_blocks; i++) {
network_to_remote_block(&rdma->block[i]);
@@ -3068,7 +3249,7 @@
if (rdma->block[i].length != local->block[j].length) {
ERROR(errp, "ram blocks mismatch #2! "
"Your QEMU command line parameters are probably "
- "not identical on both the source and destination.\n");
+ "not identical on both the source and destination.");
return -EINVAL;
}
local->block[j].remote_host_addr =
@@ -3080,7 +3261,7 @@
if (j >= local->nb_blocks) {
ERROR(errp, "ram blocks mismatch #3! "
"Your QEMU command line parameters are probably "
- "not identical on both the source and destination.\n");
+ "not identical on both the source and destination.");
return -EINVAL;
}
}
@@ -3154,7 +3335,7 @@
ret = qemu_rdma_accept(rdma);
if (ret) {
- ERROR(errp, "RDMA Migration initialization failed!\n");
+ ERROR(errp, "RDMA Migration initialization failed!");
return;
}
@@ -3162,7 +3343,7 @@
f = qemu_fopen_rdma(rdma, "rb");
if (f == NULL) {
- ERROR(errp, "could not qemu_fopen_rdma!\n");
+ ERROR(errp, "could not qemu_fopen_rdma!");
qemu_rdma_cleanup(rdma);
return;
}
@@ -3195,7 +3376,7 @@
ret = rdma_listen(rdma->listen_id, 5);
if (ret) {
- ERROR(errp, "listening on socket!\n");
+ ERROR(errp, "listening on socket!");
goto err;
}
@@ -3219,7 +3400,7 @@
int ret = 0;
if (rdma == NULL) {
- ERROR(temp, "Failed to initialize RDMA data structures! %d\n", ret);
+ ERROR(temp, "Failed to initialize RDMA data structures! %d", ret);
goto err;
}
diff --git a/migration-tcp.c b/migration-tcp.c
index b20ee58..782572d 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -18,6 +18,7 @@
#include "migration/migration.h"
#include "migration/qemu-file.h"
#include "block/block.h"
+#include "qemu/main-loop.h"
//#define DEBUG_MIGRATION_TCP
diff --git a/migration-unix.c b/migration-unix.c
index 94b7022..651fc5b 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -15,6 +15,7 @@
#include "qemu-common.h"
#include "qemu/sockets.h"
+#include "qemu/main-loop.h"
#include "migration/migration.h"
#include "migration/qemu-file.h"
#include "block/block.h"
diff --git a/migration.c b/migration.c
index e12e784..200d404 100644
--- a/migration.c
+++ b/migration.c
@@ -14,6 +14,7 @@
*/
#include "qemu-common.h"
+#include "qemu/main-loop.h"
#include "migration/migration.h"
#include "monitor/monitor.h"
#include "migration/qemu-file.h"
@@ -197,7 +198,7 @@
info->has_status = true;
info->status = g_strdup("active");
info->has_total_time = true;
- info->total_time = qemu_get_clock_ms(rt_clock)
+ info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME)
- s->total_time;
info->has_expected_downtime = true;
info->expected_downtime = s->expected_downtime;
@@ -231,6 +232,7 @@
info->has_status = true;
info->status = g_strdup("completed");
+ info->has_total_time = true;
info->total_time = s->total_time;
info->has_downtime = true;
info->downtime = s->downtime;
@@ -338,9 +340,9 @@
notifier_remove(notify);
}
-bool migration_is_active(MigrationState *s)
+bool migration_in_setup(MigrationState *s)
{
- return s->state == MIG_STATE_ACTIVE;
+ return s->state == MIG_STATE_SETUP;
}
bool migration_has_finished(MigrationState *s)
@@ -374,7 +376,7 @@
s->state = MIG_STATE_SETUP;
trace_migrate_set_state(MIG_STATE_SETUP);
- s->total_time = qemu_get_clock_ms(rt_clock);
+ s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
return s;
}
@@ -399,8 +401,8 @@
MigrationParams params;
const char *p;
- params.blk = blk;
- params.shared = inc;
+ params.blk = has_blk && blk;
+ params.shared = has_inc && inc;
if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP) {
error_set(errp, QERR_MIGRATION_ACTIVE);
@@ -543,8 +545,8 @@
static void *migration_thread(void *opaque)
{
MigrationState *s = opaque;
- int64_t initial_time = qemu_get_clock_ms(rt_clock);
- int64_t setup_start = qemu_get_clock_ms(host_clock);
+ int64_t initial_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+ int64_t setup_start = qemu_clock_get_ms(QEMU_CLOCK_HOST);
int64_t initial_bytes = 0;
int64_t max_size = 0;
int64_t start_time = initial_time;
@@ -553,7 +555,7 @@
DPRINTF("beginning savevm\n");
qemu_savevm_state_begin(s->file, &s->params);
- s->setup_time = qemu_get_clock_ms(host_clock) - setup_start;
+ s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start;
migrate_set_state(s, MIG_STATE_SETUP, MIG_STATE_ACTIVE);
DPRINTF("setup complete\n");
@@ -573,7 +575,7 @@
DPRINTF("done iterating\n");
qemu_mutex_lock_iothread();
- start_time = qemu_get_clock_ms(rt_clock);
+ start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
old_vm_running = runstate_is_running();
@@ -600,7 +602,7 @@
migrate_set_state(s, MIG_STATE_ACTIVE, MIG_STATE_ERROR);
break;
}
- current_time = qemu_get_clock_ms(rt_clock);
+ current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
if (current_time >= initial_time + BUFFER_DELAY) {
uint64_t transferred_bytes = qemu_ftell(s->file) - initial_bytes;
uint64_t time_spent = current_time - initial_time;
@@ -631,7 +633,7 @@
qemu_mutex_lock_iothread();
if (s->state == MIG_STATE_COMPLETED) {
- int64_t end_time = qemu_get_clock_ms(rt_clock);
+ int64_t end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
s->total_time = end_time - s->total_time;
s->downtime = end_time - start_time;
runstate_set(RUN_STATE_POSTMIGRATE);
@@ -658,7 +660,9 @@
qemu_file_set_rate_limit(s->file,
s->bandwidth_limit / XFER_LIMIT_RATIO);
+ /* Notify before starting migration thread */
+ notifier_list_notify(&migration_state_notifiers, s);
+
qemu_thread_create(&s->thread, migration_thread, s,
QEMU_THREAD_JOINABLE);
- notifier_list_notify(&migration_state_notifiers, s);
}
diff --git a/monitor.c b/monitor.c
index 5dc0aa9..ee9744c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -537,7 +537,7 @@
QObject *data)
{
MonitorEventState *evstate;
- int64_t now = qemu_get_clock_ns(rt_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
assert(event < QEVENT_MAX);
qemu_mutex_lock(&monitor_event_state_lock);
@@ -564,7 +564,7 @@
qobject_decref(evstate->data);
} else {
int64_t then = evstate->last + evstate->rate;
- qemu_mod_timer_ns(evstate->timer, then);
+ timer_mod_ns(evstate->timer, then);
}
evstate->data = data;
qobject_incref(evstate->data);
@@ -584,7 +584,7 @@
static void monitor_protocol_event_handler(void *opaque)
{
MonitorEventState *evstate = opaque;
- int64_t now = qemu_get_clock_ns(rt_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
qemu_mutex_lock(&monitor_event_state_lock);
@@ -622,7 +622,7 @@
trace_monitor_protocol_event_throttle(event, rate);
evstate->event = event;
evstate->rate = rate * SCALE_MS;
- evstate->timer = qemu_new_timer(rt_clock,
+ evstate->timer = timer_new(QEMU_CLOCK_REALTIME,
SCALE_MS,
monitor_protocol_event_handler,
evstate);
@@ -3171,9 +3171,13 @@
{ NULL },
};
-static void expr_error(Monitor *mon, const char *msg)
+static void expr_error(Monitor *mon, const char *fmt, ...)
{
- monitor_printf(mon, "%s\n", msg);
+ va_list ap;
+ va_start(ap, fmt);
+ monitor_vprintf(mon, fmt, ap);
+ monitor_printf(mon, "\n");
+ va_end(ap);
siglongjmp(expr_env, 1);
}
@@ -3291,7 +3295,7 @@
expr_error(mon, "number too large");
}
if (pch == p) {
- expr_error(mon, "invalid char in expression");
+ expr_error(mon, "invalid char '%c' in expression", *p);
}
pch = p;
while (qemu_isspace(*pch))
diff --git a/nbd.c b/nbd.c
index 2606403..0fd0583 100644
--- a/nbd.c
+++ b/nbd.c
@@ -38,6 +38,7 @@
#include "qemu/sockets.h"
#include "qemu/queue.h"
+#include "qemu/main-loop.h"
//#define DEBUG_NBD
diff --git a/net/dump.c b/net/dump.c
index 4119721..9d3a09e 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -69,7 +69,7 @@
return size;
}
- ts = muldiv64(qemu_get_clock_ns(vm_clock), 1000000, get_ticks_per_sec());
+ ts = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 1000000, get_ticks_per_sec());
caplen = size > s->pcap_caplen ? s->pcap_caplen : size;
hdr.ts.tv_sec = ts / 1000000 + s->start_ts;
diff --git a/net/eth.c b/net/eth.c
index 1d7494d..7c61132 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -73,7 +73,7 @@
}
/* Unsupported offload */
- assert(false);
+ g_assert_not_reached();
return VIRTIO_NET_HDR_GSO_NONE | ecn_state;
}
diff --git a/net/net.c b/net/net.c
index c0d61bf..1148592 100644
--- a/net/net.c
+++ b/net/net.c
@@ -36,6 +36,7 @@
#include "qmp-commands.h"
#include "hw/qdev.h"
#include "qemu/iov.h"
+#include "qemu/main-loop.h"
#include "qapi-visit.h"
#include "qapi/opts-visitor.h"
#include "qapi/dealloc-visitor.h"
diff --git a/net/socket.c b/net/socket.c
index 87af1d3..e61309d 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -31,6 +31,7 @@
#include "qemu/option.h"
#include "qemu/sockets.h"
#include "qemu/iov.h"
+#include "qemu/main-loop.h"
typedef struct NetSocketState {
NetClientState nc;
diff --git a/pc-bios/README b/pc-bios/README
index 53b5289..e404a22 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -11,8 +11,8 @@
firmware implementation. The goal is to implement a 100% IEEE
1275-1994 (referred to as Open Firmware) compliant firmware.
The included images for PowerPC (for 32 and 64 bit PPC CPUs),
- Sparc32 and Sparc64 are built from OpenBIOS 1.1 release (SVN
- revision 1136).
+ Sparc32 and Sparc64 are built from OpenBIOS SVN revision
+ 1198.
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
implementation for certain IBM POWER hardware. The sources are at
diff --git a/pc-bios/acpi-dsdt.aml b/pc-bios/acpi-dsdt.aml
index 75dfd1e..48dbe32 100644
--- a/pc-bios/acpi-dsdt.aml
+++ b/pc-bios/acpi-dsdt.aml
Binary files differ
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index c2a19b8..cccc487 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differ
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index 77eb55d..c6b3319 100644
--- a/pc-bios/openbios-ppc
+++ b/pc-bios/openbios-ppc
Binary files differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index c5ba6ae..2aa400c 100644
--- a/pc-bios/openbios-sparc32
+++ b/pc-bios/openbios-sparc32
Binary files differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index c4aaa05..f6ee286 100644
--- a/pc-bios/openbios-sparc64
+++ b/pc-bios/openbios-sparc64
Binary files differ
diff --git a/pc-bios/q35-acpi-dsdt.aml b/pc-bios/q35-acpi-dsdt.aml
index cf7b085..91ab67c 100644
--- a/pc-bios/q35-acpi-dsdt.aml
+++ b/pc-bios/q35-acpi-dsdt.aml
Binary files differ
diff --git a/pc-bios/qemu-nsis.bmp b/pc-bios/qemu-nsis.bmp
new file mode 100644
index 0000000..ae82cd2
--- /dev/null
+++ b/pc-bios/qemu-nsis.bmp
Binary files differ
diff --git a/pc-bios/qemu-nsis.ico b/pc-bios/qemu-nsis.ico
new file mode 100644
index 0000000..1d0128c
--- /dev/null
+++ b/pc-bios/qemu-nsis.ico
Binary files differ
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index 1b2a11e..05fc7c2 100644
--- a/pc-bios/s390-ccw.img
+++ b/pc-bios/s390-ccw.img
Binary files differ
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
index cb5815a..f5b4549 100644
--- a/pc-bios/s390-ccw/cio.h
+++ b/pc-bios/s390-ccw/cio.h
@@ -93,6 +93,26 @@
__u32 sch_no : 16;
} __attribute__ ((packed, aligned(4)));
+struct chsc_header {
+ __u16 length;
+ __u16 code;
+} __attribute__((packed));
+
+struct chsc_area_sda {
+ struct chsc_header request;
+ __u8 reserved1:4;
+ __u8 format:4;
+ __u8 reserved2;
+ __u16 operation_code;
+ __u32 reserved3;
+ __u32 reserved4;
+ __u32 operation_data_area[252];
+ struct chsc_header response;
+ __u32 reserved5:4;
+ __u32 format2:4;
+ __u32 reserved6:24;
+} __attribute__((packed));
+
/*
* TPI info structure
*/
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 1665c57..c5d5332 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -35,6 +35,13 @@
check_devno = true;
dev_no = dev_info & 0xffff;
debug_print_int("device no. ", dev_no);
+ blk_schid.ssid = (dev_info >> 16) & 0x3;
+ if (blk_schid.ssid != 0) {
+ debug_print_int("ssid ", blk_schid.ssid);
+ if (enable_mss_facility() != 0) {
+ virtio_panic("Failed to enable mss facility\n");
+ }
+ }
}
for (i = 0; i < 0x10000; i++) {
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 8241b0a..5e871ac 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -61,6 +61,7 @@
bool virtio_is_blk(struct subchannel_id schid);
void virtio_setup_block(struct subchannel_id schid);
int virtio_read(ulong sector, void *load_addr);
+int enable_mss_facility(void);
/* bootmap.c */
int zipl_load(void);
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index f438af1..49f2d29 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -13,6 +13,8 @@
struct vring block;
+static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+
static long kvm_hypercall(unsigned long nr, unsigned long param1,
unsigned long param2)
{
@@ -301,3 +303,19 @@
return true;
}
+int enable_mss_facility(void)
+{
+ int ret;
+ struct chsc_area_sda *sda_area = (struct chsc_area_sda *) chsc_page;
+
+ memset(sda_area, 0, PAGE_SIZE);
+ sda_area->request.length = 0x0400;
+ sda_area->request.code = 0x0031;
+ sda_area->operation_code = 0x2;
+
+ ret = chsc(sda_area);
+ if ((ret == 0) && (sda_area->response.code == 0x0001)) {
+ return 0;
+ }
+ return -EIO;
+}
diff --git a/po/Makefile b/po/Makefile
index 60ccd7d..705166e 100644
--- a/po/Makefile
+++ b/po/Makefile
@@ -1,20 +1,23 @@
# This makefile is very special as it's meant to build as part of the build
# process and also within the source tree to update the translation files.
-VERSION=$(shell cat ../VERSION)
-SRCS=$(filter-out messages.po,$(wildcard *.po))
-OBJS=$(patsubst %.po,%.mo,$(SRCS))
-
+# Set SRC_PATH for in-tree builds without configuration.
SRC_PATH=..
-include ../config-host.mak
+include $(SRC_PATH)/rules.mak
-vpath %.po $(SRC_PATH)/po
+PO_PATH=$(SRC_PATH)/po
+
+VERSION=$(shell cat $(SRC_PATH)/VERSION)
+SRCS=$(filter-out $(PO_PATH)/messages.po,$(wildcard $(PO_PATH)/*.po))
+OBJS=$(patsubst $(PO_PATH)/%.po,%.mo,$(SRCS))
+
+vpath %.po $(PO_PATH)
all:
- @echo Use 'make update' to update translation files
- @echo or us 'make build' or 'make install' to build and install
- @echo the translation files
+ @echo "Use 'make update' to update translation files or use 'make build'"
+ @echo "or 'make install' to build and install the translation files."
update: $(SRCS)
@@ -31,12 +34,16 @@
done
%.mo: %.po
- @msgfmt -o $@ $(SRC_PATH)/po/`basename $@ .mo`.po
+ $(call quiet-command, msgfmt -o $@ $<, " GEN $@")
-messages.po: $(SRC_PATH)/ui/gtk.c
- @xgettext -o $@ --foreign-user --package-name=QEMU --package-version=$(VERSION) --msgid-bugs-address=qemu-devel@nongnu.org -k_ -C $<
+$(PO_PATH)/messages.po: $(SRC_PATH)/ui/gtk.c
+ $(call quiet-command, cd $(SRC_PATH) && \
+ (xgettext -o - --from-code=UTF-8 --foreign-user \
+ --package-name=QEMU --package-version=$(VERSION) \
+ --msgid-bugs-address=qemu-devel@nongnu.org -k_ -C ui/gtk.c | \
+ sed -e s/CHARSET/UTF-8/) >$@, " GEN $@")
-%.po: messages.po
- @msgmerge $@ $< > $@.bak && mv $@.bak $@
+$(PO_PATH)/%.po: $(PO_PATH)/messages.po
+ $(call quiet-command, msgmerge -q $@ $< > $@.bak && mv $@.bak $@, " GEN $@")
.PHONY: clean all
diff --git a/po/de_DE.po b/po/de_DE.po
index e35aaf4..fcbde95 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -6,7 +6,7 @@
msgstr ""
"Project-Id-Version: QEMU 1.4.50\n"
"Report-Msgid-Bugs-To: qemu-devel@nongnu.org\n"
-"POT-Creation-Date: 2013-03-31 20:42+0200\n"
+"POT-Creation-Date: 2013-07-05 22:36+0200\n"
"PO-Revision-Date: 2012-02-28 16:00+0100\n"
"Last-Translator: Kevin Wolf <kwolf@redhat.com>\n"
"Language-Team: Deutsch <de@li.org>\n"
@@ -16,49 +16,49 @@
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
-#: ../ui/gtk.c:213
+#: ui/gtk.c:214
msgid " - Press Ctrl+Alt+G to release grab"
msgstr " - Strg+Alt+G drücken, um Eingabegeräte freizugeben"
-#: ../ui/gtk.c:217
+#: ui/gtk.c:218
msgid " [Paused]"
msgstr " [Angehalten]"
-#: ../ui/gtk.c:1250
-msgid "_Machine"
-msgstr "_Maschine"
-
-#: ../ui/gtk.c:1252
+#: ui/gtk.c:1318
msgid "_Pause"
msgstr "_Angehalten"
-#: ../ui/gtk.c:1258
+#: ui/gtk.c:1324
msgid "_Reset"
msgstr "_Reset"
-#: ../ui/gtk.c:1261
+#: ui/gtk.c:1327
msgid "Power _Down"
msgstr "_Herunterfahren"
-#: ../ui/gtk.c:1276
-msgid "_View"
-msgstr "_Ansicht"
-
-#: ../ui/gtk.c:1306
+#: ui/gtk.c:1381
msgid "Zoom To _Fit"
msgstr "Auf _Fenstergröße skalieren"
-#: ../ui/gtk.c:1312
+#: ui/gtk.c:1387
msgid "Grab On _Hover"
msgstr "Tastatur _automatisch einfangen"
-#: ../ui/gtk.c:1315
+#: ui/gtk.c:1390
msgid "_Grab Input"
msgstr "_Eingabegeräte einfangen"
-#: ../ui/gtk.c:1341
+#: ui/gtk.c:1416
msgid "Show _Tabs"
msgstr "_Tableiste anzeigen"
+#: ui/gtk.c:1430
+msgid "_Machine"
+msgstr "_Maschine"
+
+#: ui/gtk.c:1435
+msgid "_View"
+msgstr "_Ansicht"
+
#~ msgid "_File"
#~ msgstr "_Datei"
diff --git a/po/fr_FR.po b/po/fr_FR.po
index 27d8636..45b2c01 100644
--- a/po/fr_FR.po
+++ b/po/fr_FR.po
@@ -6,7 +6,7 @@
msgstr ""
"Project-Id-Version: QEMU 1.4.50\n"
"Report-Msgid-Bugs-To: qemu-devel@nongnu.org\n"
-"POT-Creation-Date: 2013-03-31 20:42+0200\n"
+"POT-Creation-Date: 2013-07-05 22:36+0200\n"
"PO-Revision-Date: 2013-03-31 19:39+0200\n"
"Last-Translator: Aurelien Jarno <aurelien@aurel32.net>\n"
"Language-Team: French <FR@li.org>\n"
@@ -17,46 +17,46 @@
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Lokalize 1.4\n"
-#: ../ui/gtk.c:213
+#: ui/gtk.c:214
msgid " - Press Ctrl+Alt+G to release grab"
msgstr "- Appuyer sur Ctrl+Alt+G pour arrêter la capture"
-#: ../ui/gtk.c:217
+#: ui/gtk.c:218
msgid " [Paused]"
msgstr " [En pause]"
-#: ../ui/gtk.c:1250
-msgid "_Machine"
-msgstr "_Machine"
-
-#: ../ui/gtk.c:1252
+#: ui/gtk.c:1318
msgid "_Pause"
msgstr "_Pause"
-#: ../ui/gtk.c:1258
+#: ui/gtk.c:1324
msgid "_Reset"
msgstr "_Réinitialiser"
-#: ../ui/gtk.c:1261
+#: ui/gtk.c:1327
msgid "Power _Down"
msgstr "_Éteindre"
-#: ../ui/gtk.c:1276
-msgid "_View"
-msgstr "_Vue"
-
-#: ../ui/gtk.c:1306
+#: ui/gtk.c:1381
msgid "Zoom To _Fit"
msgstr "Zoomer pour _ajuster"
-#: ../ui/gtk.c:1312
+#: ui/gtk.c:1387
msgid "Grab On _Hover"
msgstr "Capturer en _survolant"
-#: ../ui/gtk.c:1315
+#: ui/gtk.c:1390
msgid "_Grab Input"
msgstr "_Capturer les entrées"
-#: ../ui/gtk.c:1341
+#: ui/gtk.c:1416
msgid "Show _Tabs"
msgstr "Montrer les _onglets"
+
+#: ui/gtk.c:1430
+msgid "_Machine"
+msgstr "_Machine"
+
+#: ui/gtk.c:1435
+msgid "_View"
+msgstr "_Vue"
diff --git a/po/hu.po b/po/hu.po
index debba96..0a44c66 100644
--- a/po/hu.po
+++ b/po/hu.po
@@ -6,7 +6,7 @@
msgstr ""
"Project-Id-Version: QEMU 1.4.50\n"
"Report-Msgid-Bugs-To: qemu-devel@nongnu.org\n"
-"POT-Creation-Date: 2013-05-06 20:42+0200\n"
+"POT-Creation-Date: 2013-07-05 22:36+0200\n"
"PO-Revision-Date: 2013-05-06 20:42+0200\n"
"Last-Translator: Ákos Kovács <akoskovacs@gmx.com>\n"
"Language-Team: Hungarian <hu@li.org>\n"
@@ -15,49 +15,49 @@
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: ../ui/gtk.c:213
+#: ui/gtk.c:214
msgid " - Press Ctrl+Alt+G to release grab"
msgstr " - Nyomj Ctrl+Alt+G-t a bemeneti eszközök elengedéséhez"
-#: ../ui/gtk.c:217
+#: ui/gtk.c:218
msgid " [Paused]"
msgstr " [Megállítva]"
-#: ../ui/gtk.c:1250
-msgid "_Machine"
-msgstr "_Gép"
-
-#: ../ui/gtk.c:1252
+#: ui/gtk.c:1318
msgid "_Pause"
msgstr "_Megállítás"
-#: ../ui/gtk.c:1258
+#: ui/gtk.c:1324
msgid "_Reset"
msgstr "Új_raindítás"
-#: ../ui/gtk.c:1261
+#: ui/gtk.c:1327
msgid "Power _Down"
msgstr "_Leállítás"
-#: ../ui/gtk.c:1276
-msgid "_View"
-msgstr "_Nézet"
-
-#: ../ui/gtk.c:1306
+#: ui/gtk.c:1381
msgid "Zoom To _Fit"
msgstr "Ablakmérethez _igazítás"
-#: ../ui/gtk.c:1312
+#: ui/gtk.c:1387
msgid "Grab On _Hover"
msgstr "Automatikus _elfogás"
-#: ../ui/gtk.c:1315
+#: ui/gtk.c:1390
msgid "_Grab Input"
msgstr "_Bemeneti eszközök megragadása"
-#: ../ui/gtk.c:1341
+#: ui/gtk.c:1416
msgid "Show _Tabs"
msgstr "_Fülek megjelenítése"
+#: ui/gtk.c:1430
+msgid "_Machine"
+msgstr "_Gép"
+
+#: ui/gtk.c:1435
+msgid "_View"
+msgstr "_Nézet"
+
#~ msgid "_File"
#~ msgstr "_File"
diff --git a/po/it.po b/po/it.po
index 2ace3b0..592d3d8 100644
--- a/po/it.po
+++ b/po/it.po
@@ -6,7 +6,7 @@
msgstr ""
"Project-Id-Version: QEMU 1.4.50\n"
"Report-Msgid-Bugs-To: qemu-devel@nongnu.org\n"
-"POT-Creation-Date: 2013-03-31 20:42+0200\n"
+"POT-Creation-Date: 2013-07-05 22:36+0200\n"
"PO-Revision-Date: 2012-02-27 08:23+0100\n"
"Last-Translator: Paolo Bonzini <pbonzini@redhat.com>\n"
"Language-Team: Italian <it@li.org>\n"
@@ -16,49 +16,49 @@
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-#: ../ui/gtk.c:213
+#: ui/gtk.c:214
msgid " - Press Ctrl+Alt+G to release grab"
msgstr ""
-#: ../ui/gtk.c:217
+#: ui/gtk.c:218
msgid " [Paused]"
msgstr ""
-#: ../ui/gtk.c:1250
-msgid "_Machine"
-msgstr ""
-
-#: ../ui/gtk.c:1252
+#: ui/gtk.c:1318
msgid "_Pause"
msgstr ""
-#: ../ui/gtk.c:1258
+#: ui/gtk.c:1324
msgid "_Reset"
msgstr ""
-#: ../ui/gtk.c:1261
+#: ui/gtk.c:1327
msgid "Power _Down"
msgstr ""
-#: ../ui/gtk.c:1276
-msgid "_View"
-msgstr "_Visualizza"
-
-#: ../ui/gtk.c:1306
+#: ui/gtk.c:1381
msgid "Zoom To _Fit"
msgstr "Adatta alla _finestra"
-#: ../ui/gtk.c:1312
+#: ui/gtk.c:1387
msgid "Grab On _Hover"
msgstr "Cattura _automatica input"
-#: ../ui/gtk.c:1315
+#: ui/gtk.c:1390
msgid "_Grab Input"
msgstr "_Cattura input"
-#: ../ui/gtk.c:1341
+#: ui/gtk.c:1416
msgid "Show _Tabs"
msgstr "Mostra _tab"
+#: ui/gtk.c:1430
+msgid "_Machine"
+msgstr ""
+
+#: ui/gtk.c:1435
+msgid "_View"
+msgstr "_Visualizza"
+
#~ msgid "_File"
#~ msgstr "_File"
diff --git a/po/messages.po b/po/messages.po
index 42a3eac..26c76bc 100644
--- a/po/messages.po
+++ b/po/messages.po
@@ -5,57 +5,57 @@
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: QEMU 1.4.50\n"
+"Project-Id-Version: QEMU 1.5.50\n"
"Report-Msgid-Bugs-To: qemu-devel@nongnu.org\n"
-"POT-Creation-Date: 2013-03-31 20:42+0200\n"
+"POT-Creation-Date: 2013-07-05 22:36+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: ../ui/gtk.c:213
+#: ui/gtk.c:214
msgid " - Press Ctrl+Alt+G to release grab"
msgstr ""
-#: ../ui/gtk.c:217
+#: ui/gtk.c:218
msgid " [Paused]"
msgstr ""
-#: ../ui/gtk.c:1250
-msgid "_Machine"
-msgstr ""
-
-#: ../ui/gtk.c:1252
+#: ui/gtk.c:1318
msgid "_Pause"
msgstr ""
-#: ../ui/gtk.c:1258
+#: ui/gtk.c:1324
msgid "_Reset"
msgstr ""
-#: ../ui/gtk.c:1261
+#: ui/gtk.c:1327
msgid "Power _Down"
msgstr ""
-#: ../ui/gtk.c:1276
-msgid "_View"
-msgstr ""
-
-#: ../ui/gtk.c:1306
+#: ui/gtk.c:1381
msgid "Zoom To _Fit"
msgstr ""
-#: ../ui/gtk.c:1312
+#: ui/gtk.c:1387
msgid "Grab On _Hover"
msgstr ""
-#: ../ui/gtk.c:1315
+#: ui/gtk.c:1390
msgid "_Grab Input"
msgstr ""
-#: ../ui/gtk.c:1341
+#: ui/gtk.c:1416
msgid "Show _Tabs"
msgstr ""
+
+#: ui/gtk.c:1430
+msgid "_Machine"
+msgstr ""
+
+#: ui/gtk.c:1435
+msgid "_View"
+msgstr ""
diff --git a/po/tr.po b/po/tr.po
index 4faefbd..d57995a 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -6,7 +6,7 @@
msgstr ""
"Project-Id-Version: QEMU 1.4.50\n"
"Report-Msgid-Bugs-To: qemu-devel@nongnu.org\n"
-"POT-Creation-Date: 2013-04-22 18:33+0300\n"
+"POT-Creation-Date: 2013-07-05 22:36+0200\n"
"PO-Revision-Date: 2013-04-22 18:35+0300\n"
"Last-Translator: Ozan ÇaÄŸlayan <ozancag@gmail.com>\n"
"Language-Team: Türkçe <>\n"
@@ -17,46 +17,46 @@
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Gtranslator 2.91.6\n"
-#: ../ui/gtk.c:214
+#: ui/gtk.c:214
msgid " - Press Ctrl+Alt+G to release grab"
msgstr " - Yakalamayı durdurmak için Ctrl+Alt+G tuÅŸlarına basın"
-#: ../ui/gtk.c:218
+#: ui/gtk.c:218
msgid " [Paused]"
msgstr " [Duraklatıldı]"
-#: ../ui/gtk.c:1282
-msgid "_Machine"
-msgstr "_Makine"
-
-#: ../ui/gtk.c:1284
+#: ui/gtk.c:1318
msgid "_Pause"
msgstr "_Duraklat"
-#: ../ui/gtk.c:1290
+#: ui/gtk.c:1324
msgid "_Reset"
msgstr "_Sıfırla"
-#: ../ui/gtk.c:1293
+#: ui/gtk.c:1327
msgid "Power _Down"
msgstr "_Kapat"
-#: ../ui/gtk.c:1308
-msgid "_View"
-msgstr "_Görüntüle"
-
-#: ../ui/gtk.c:1338
+#: ui/gtk.c:1381
msgid "Zoom To _Fit"
msgstr "Yakınlaş ve Sığ_dır"
-#: ../ui/gtk.c:1344
+#: ui/gtk.c:1387
msgid "Grab On _Hover"
msgstr "Ü_zerindeyken Yakala"
-#: ../ui/gtk.c:1347
+#: ui/gtk.c:1390
msgid "_Grab Input"
msgstr "Girdiyi _Yakala"
-#: ../ui/gtk.c:1373
+#: ui/gtk.c:1416
msgid "Show _Tabs"
msgstr "Se_kmeleri Göster"
+
+#: ui/gtk.c:1430
+msgid "_Machine"
+msgstr "_Makine"
+
+#: ui/gtk.c:1435
+msgid "_View"
+msgstr "_Görüntüle"
diff --git a/qapi-schema.json b/qapi-schema.json
index f82d829..a51f7d2 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3362,15 +3362,15 @@
'*rows' : 'int' } }
##
-# @ChardevMemory:
+# @ChardevRingbuf:
#
-# Configuration info for memory chardevs
+# Configuration info for ring buffer chardevs.
#
-# @size: #optional Ringbuffer size, must be power of two, default is 65536
+# @size: #optional ring buffer size, must be power of two, default is 65536
#
# Since: 1.5
##
-{ 'type': 'ChardevMemory', 'data': { '*size' : 'int' } }
+{ 'type': 'ChardevRingbuf', 'data': { '*size' : 'int' } }
##
# @ChardevBackend:
@@ -3397,7 +3397,9 @@
'spicevmc' : 'ChardevSpiceChannel',
'spiceport' : 'ChardevSpicePort',
'vc' : 'ChardevVC',
- 'memory' : 'ChardevMemory' } }
+ 'ringbuf': 'ChardevRingbuf',
+ # next one is just for compatibility
+ 'memory' : 'ChardevRingbuf' } }
##
# @ChardevReturn:
diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c
index 174bd8b..96ed858 100644
--- a/qapi/opts-visitor.c
+++ b/qapi/opts-visitor.c
@@ -1,7 +1,7 @@
/*
* Options Visitor
*
- * Copyright Red Hat, Inc. 2012
+ * Copyright Red Hat, Inc. 2012, 2013
*
* Author: Laszlo Ersek <lersek@redhat.com>
*
@@ -18,6 +18,40 @@
#include "qapi/visitor-impl.h"
+enum ListMode
+{
+ LM_NONE, /* not traversing a list of repeated options */
+ LM_STARTED, /* opts_start_list() succeeded */
+
+ LM_IN_PROGRESS, /* opts_next_list() has been called.
+ *
+ * Generating the next list link will consume the most
+ * recently parsed QemuOpt instance of the repeated
+ * option.
+ *
+ * Parsing a value into the list link will examine the
+ * next QemuOpt instance of the repeated option, and
+ * possibly enter LM_SIGNED_INTERVAL or
+ * LM_UNSIGNED_INTERVAL.
+ */
+
+ LM_SIGNED_INTERVAL, /* opts_next_list() has been called.
+ *
+ * Generating the next list link will consume the most
+ * recently stored element from the signed interval,
+ * parsed from the most recent QemuOpt instance of the
+ * repeated option. This may consume QemuOpt itself
+ * and return to LM_IN_PROGRESS.
+ *
+ * Parsing a value into the list link will store the
+ * next element of the signed interval.
+ */
+
+ LM_UNSIGNED_INTERVAL /* Same as above, only for an unsigned interval. */
+};
+
+typedef enum ListMode ListMode;
+
struct OptsVisitor
{
Visitor visitor;
@@ -35,8 +69,17 @@
/* The list currently being traversed with opts_start_list() /
* opts_next_list(). The list must have a struct element type in the
* schema, with a single mandatory scalar member. */
+ ListMode list_mode;
GQueue *repeated_opts;
- bool repeated_opts_first;
+
+ /* When parsing a list of repeating options as integers, values of the form
+ * "a-b", representing a closed interval, are allowed. Elements in the
+ * range are generated individually.
+ */
+ union {
+ int64_t s;
+ uint64_t u;
+ } range_next, range_limit;
/* If "opts_root->id" is set, reinstantiate it as a fake QemuOpt for
* uniformity. Only its "name" and "str" fields are set. "fake_id_opt" does
@@ -156,9 +199,11 @@
OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
/* we can't traverse a list in a list */
- assert(ov->repeated_opts == NULL);
+ assert(ov->list_mode == LM_NONE);
ov->repeated_opts = lookup_distinct(ov, name, errp);
- ov->repeated_opts_first = (ov->repeated_opts != NULL);
+ if (ov->repeated_opts != NULL) {
+ ov->list_mode = LM_STARTED;
+ }
}
@@ -168,10 +213,29 @@
OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
GenericList **link;
- if (ov->repeated_opts_first) {
- ov->repeated_opts_first = false;
+ switch (ov->list_mode) {
+ case LM_STARTED:
+ ov->list_mode = LM_IN_PROGRESS;
link = list;
- } else {
+ break;
+
+ case LM_SIGNED_INTERVAL:
+ case LM_UNSIGNED_INTERVAL:
+ link = &(*list)->next;
+
+ if (ov->list_mode == LM_SIGNED_INTERVAL) {
+ if (ov->range_next.s < ov->range_limit.s) {
+ ++ov->range_next.s;
+ break;
+ }
+ } else if (ov->range_next.u < ov->range_limit.u) {
+ ++ov->range_next.u;
+ break;
+ }
+ ov->list_mode = LM_IN_PROGRESS;
+ /* range has been completed, fall through in order to pop option */
+
+ case LM_IN_PROGRESS: {
const QemuOpt *opt;
opt = g_queue_pop_head(ov->repeated_opts);
@@ -180,6 +244,11 @@
return NULL;
}
link = &(*list)->next;
+ break;
+ }
+
+ default:
+ abort();
}
*link = g_malloc0(sizeof **link);
@@ -192,14 +261,19 @@
{
OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
+ assert(ov->list_mode == LM_STARTED ||
+ ov->list_mode == LM_IN_PROGRESS ||
+ ov->list_mode == LM_SIGNED_INTERVAL ||
+ ov->list_mode == LM_UNSIGNED_INTERVAL);
ov->repeated_opts = NULL;
+ ov->list_mode = LM_NONE;
}
static const QemuOpt *
lookup_scalar(const OptsVisitor *ov, const char *name, Error **errp)
{
- if (ov->repeated_opts == NULL) {
+ if (ov->list_mode == LM_NONE) {
GQueue *list;
/* the last occurrence of any QemuOpt takes effect when queried by name
@@ -207,6 +281,7 @@
list = lookup_distinct(ov, name, errp);
return list ? g_queue_peek_tail(list) : NULL;
}
+ assert(ov->list_mode == LM_IN_PROGRESS);
return g_queue_peek_head(ov->repeated_opts);
}
@@ -214,9 +289,12 @@
static void
processed(OptsVisitor *ov, const char *name)
{
- if (ov->repeated_opts == NULL) {
+ if (ov->list_mode == LM_NONE) {
g_hash_table_remove(ov->unprocessed_opts, name);
+ return;
}
+ assert(ov->list_mode == LM_IN_PROGRESS);
+ /* do nothing */
}
@@ -278,21 +356,50 @@
long long val;
char *endptr;
+ if (ov->list_mode == LM_SIGNED_INTERVAL) {
+ *obj = ov->range_next.s;
+ return;
+ }
+
opt = lookup_scalar(ov, name, errp);
if (!opt) {
return;
}
str = opt->str ? opt->str : "";
+ /* we've gotten past lookup_scalar() */
+ assert(ov->list_mode == LM_NONE || ov->list_mode == LM_IN_PROGRESS);
+
errno = 0;
val = strtoll(str, &endptr, 0);
- if (*str != '\0' && *endptr == '\0' && errno == 0 && INT64_MIN <= val &&
- val <= INT64_MAX) {
- *obj = val;
- processed(ov, name);
- return;
+ if (errno == 0 && endptr > str && INT64_MIN <= val && val <= INT64_MAX) {
+ if (*endptr == '\0') {
+ *obj = val;
+ processed(ov, name);
+ return;
+ }
+ if (*endptr == '-' && ov->list_mode == LM_IN_PROGRESS) {
+ long long val2;
+
+ str = endptr + 1;
+ val2 = strtoll(str, &endptr, 0);
+ if (errno == 0 && endptr > str && *endptr == '\0' &&
+ INT64_MIN <= val2 && val2 <= INT64_MAX && val <= val2 &&
+ (val > INT64_MAX - OPTS_VISITOR_RANGE_MAX ||
+ val2 < val + OPTS_VISITOR_RANGE_MAX)) {
+ ov->range_next.s = val;
+ ov->range_limit.s = val2;
+ ov->list_mode = LM_SIGNED_INTERVAL;
+
+ /* as if entering on the top */
+ *obj = ov->range_next.s;
+ return;
+ }
+ }
}
- error_set(errp, QERR_INVALID_PARAMETER_VALUE, opt->name, "an int64 value");
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
+ (ov->list_mode == LM_NONE) ? "an int64 value" :
+ "an int64 value or range");
}
@@ -302,34 +409,49 @@
OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
const QemuOpt *opt;
const char *str;
+ unsigned long long val;
+ char *endptr;
+
+ if (ov->list_mode == LM_UNSIGNED_INTERVAL) {
+ *obj = ov->range_next.u;
+ return;
+ }
opt = lookup_scalar(ov, name, errp);
if (!opt) {
return;
}
-
str = opt->str;
- if (str != NULL) {
- while (isspace((unsigned char)*str)) {
- ++str;
+
+ /* we've gotten past lookup_scalar() */
+ assert(ov->list_mode == LM_NONE || ov->list_mode == LM_IN_PROGRESS);
+
+ if (parse_uint(str, &val, &endptr, 0) == 0 && val <= UINT64_MAX) {
+ if (*endptr == '\0') {
+ *obj = val;
+ processed(ov, name);
+ return;
}
+ if (*endptr == '-' && ov->list_mode == LM_IN_PROGRESS) {
+ unsigned long long val2;
- if (*str != '-' && *str != '\0') {
- unsigned long long val;
- char *endptr;
+ str = endptr + 1;
+ if (parse_uint_full(str, &val2, 0) == 0 &&
+ val2 <= UINT64_MAX && val <= val2 &&
+ val2 - val < OPTS_VISITOR_RANGE_MAX) {
+ ov->range_next.u = val;
+ ov->range_limit.u = val2;
+ ov->list_mode = LM_UNSIGNED_INTERVAL;
- /* non-empty, non-negative subject sequence */
- errno = 0;
- val = strtoull(str, &endptr, 0);
- if (*endptr == '\0' && errno == 0 && val <= UINT64_MAX) {
- *obj = val;
- processed(ov, name);
+ /* as if entering on the top */
+ *obj = ov->range_next.u;
return;
}
}
}
error_set(errp, QERR_INVALID_PARAMETER_VALUE, opt->name,
- "an uint64 value");
+ (ov->list_mode == LM_NONE) ? "a uint64 value" :
+ "a uint64 value or range");
}
@@ -365,7 +487,7 @@
OptsVisitor *ov = DO_UPCAST(OptsVisitor, visitor, v);
/* we only support a single mandatory scalar field in a list node */
- assert(ov->repeated_opts == NULL);
+ assert(ov->list_mode == LM_NONE);
*present = (lookup_distinct(ov, name, NULL) != NULL);
}
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 401ee6e..6451a21 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -12,6 +12,7 @@
*/
#include "qemu-common.h"
+#include "qapi/qmp/qobject.h"
#include "qapi/qmp/qerror.h"
#include "qapi/visitor.h"
#include "qapi/visitor-impl.h"
@@ -45,6 +46,22 @@
v->end_struct(v, errp);
}
+void visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
+ Error **errp)
+{
+ if (!error_is_set(errp) && v->start_implicit_struct) {
+ v->start_implicit_struct(v, obj, size, errp);
+ }
+}
+
+void visit_end_implicit_struct(Visitor *v, Error **errp)
+{
+ assert(!error_is_set(errp));
+ if (v->end_implicit_struct) {
+ v->end_implicit_struct(v, errp);
+ }
+}
+
void visit_start_list(Visitor *v, const char *name, Error **errp)
{
if (!error_is_set(errp)) {
@@ -82,6 +99,14 @@
}
}
+void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
+ const char *name, Error **errp)
+{
+ if (!error_is_set(errp) && v->get_next_type) {
+ v->get_next_type(v, obj, qtypes, name, errp);
+ }
+}
+
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
const char *kind, const char *name, Error **errp)
{
@@ -238,8 +263,17 @@
void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp)
{
+ int64_t value;
if (!error_is_set(errp)) {
- (v->type_size ? v->type_size : v->type_uint64)(v, obj, name, errp);
+ if (v->type_size) {
+ v->type_size(v, obj, name, errp);
+ } else if (v->type_uint64) {
+ v->type_uint64(v, obj, name, errp);
+ } else {
+ value = *obj;
+ v->type_int(v, &value, name, errp);
+ *obj = value;
+ }
}
}
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index 67fb127..bf42c04 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -41,13 +41,14 @@
}
static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
- const char *name)
+ const char *name,
+ bool consume)
{
QObject *qobj = qiv->stack[qiv->nb_stack - 1].obj;
if (qobj) {
if (name && qobject_type(qobj) == QTYPE_QDICT) {
- if (qiv->stack[qiv->nb_stack - 1].h) {
+ if (qiv->stack[qiv->nb_stack - 1].h && consume) {
g_hash_table_remove(qiv->stack[qiv->nb_stack - 1].h, name);
}
return qdict_get(qobject_to_qdict(qobj), name);
@@ -117,7 +118,7 @@
const char *name, size_t size, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name);
+ QObject *qobj = qmp_input_get_object(qiv, name, true);
Error *err = NULL;
if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
@@ -144,10 +145,22 @@
qmp_input_pop(qiv, errp);
}
+static void qmp_input_start_implicit_struct(Visitor *v, void **obj,
+ size_t size, Error **errp)
+{
+ if (obj) {
+ *obj = g_malloc0(size);
+ }
+}
+
+static void qmp_input_end_implicit_struct(Visitor *v, Error **errp)
+{
+}
+
static void qmp_input_start_list(Visitor *v, const char *name, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name);
+ QObject *qobj = qmp_input_get_object(qiv, name, true);
if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -195,11 +208,24 @@
qmp_input_pop(qiv, errp);
}
+static void qmp_input_get_next_type(Visitor *v, int *kind, const int *qobjects,
+ const char *name, Error **errp)
+{
+ QmpInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qmp_input_get_object(qiv, name, false);
+
+ if (!qobj) {
+ error_set(errp, QERR_MISSING_PARAMETER, name ? name : "null");
+ return;
+ }
+ *kind = qobjects[qobject_type(qobj)];
+}
+
static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name,
Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name);
+ QObject *qobj = qmp_input_get_object(qiv, name, true);
if (!qobj || qobject_type(qobj) != QTYPE_QINT) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -214,7 +240,7 @@
Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name);
+ QObject *qobj = qmp_input_get_object(qiv, name, true);
if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -229,7 +255,7 @@
Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name);
+ QObject *qobj = qmp_input_get_object(qiv, name, true);
if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
@@ -244,7 +270,7 @@
Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name);
+ QObject *qobj = qmp_input_get_object(qiv, name, true);
if (!qobj || (qobject_type(qobj) != QTYPE_QFLOAT &&
qobject_type(qobj) != QTYPE_QINT)) {
@@ -264,7 +290,7 @@
const char *name, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name);
+ QObject *qobj = qmp_input_get_object(qiv, name, true);
if (!qobj) {
*present = false;
@@ -293,6 +319,8 @@
v->visitor.start_struct = qmp_input_start_struct;
v->visitor.end_struct = qmp_input_end_struct;
+ v->visitor.start_implicit_struct = qmp_input_start_implicit_struct;
+ v->visitor.end_implicit_struct = qmp_input_end_implicit_struct;
v->visitor.start_list = qmp_input_start_list;
v->visitor.next_list = qmp_input_next_list;
v->visitor.end_list = qmp_input_end_list;
@@ -302,6 +330,7 @@
v->visitor.type_str = qmp_input_type_str;
v->visitor.type_number = qmp_input_type_number;
v->visitor.start_optional = qmp_input_start_optional;
+ v->visitor.get_next_type = qmp_input_get_next_type;
qmp_input_push(v, obj, NULL);
qobject_incref(obj);
diff --git a/qdev-monitor.c b/qdev-monitor.c
index e54dbc2..410cdcb 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -75,24 +75,27 @@
return (qdev_class_get_alias(dc) != NULL);
}
-static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
+static void qdev_print_class_devinfo(DeviceClass *dc)
{
- DeviceClass *dc;
- bool *show_no_user = opaque;
+ DeviceCategory category;
- dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
-
- if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
+ if (!dc) {
return;
}
- error_printf("name \"%s\"", object_class_get_name(klass));
+ error_printf("name \"%s\"", object_class_get_name(OBJECT_CLASS(dc)));
if (dc->bus_type) {
error_printf(", bus %s", dc->bus_type);
}
if (qdev_class_has_alias(dc)) {
error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
}
+ error_printf(", categories");
+ for (category = 0; category < DEVICE_CATEGORY_MAX; ++category) {
+ if (test_bit(category, dc->categories)) {
+ error_printf(" \"%s\"", qdev_category_get_name(category));
+ }
+ }
if (dc->desc) {
error_printf(", desc \"%s\"", dc->desc);
}
@@ -102,6 +105,15 @@
error_printf("\n");
}
+static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
+{
+ DeviceClass *dc;
+
+ dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
+
+ qdev_print_class_devinfo(dc);
+}
+
static int set_property(const char *name, const char *value, void *opaque)
{
DeviceState *dev = opaque;
@@ -139,6 +151,21 @@
return NULL;
}
+static void qdev_print_category_devices(DeviceCategory category)
+{
+ DeviceClass *dc;
+ GSList *list, *curr;
+
+ list = object_class_get_list(TYPE_DEVICE, false);
+ for (curr = list; curr; curr = g_slist_next(curr)) {
+ dc = (DeviceClass *)object_class_dynamic_cast(curr->data, TYPE_DEVICE);
+ if (!dc->no_user && test_bit(category, dc->categories)) {
+ qdev_print_class_devinfo(dc);
+ }
+ }
+ g_slist_free(list);
+}
+
int qdev_device_help(QemuOpts *opts)
{
const char *driver;
@@ -147,8 +174,11 @@
driver = qemu_opt_get(opts, "driver");
if (driver && is_help_option(driver)) {
- bool show_no_user = false;
- object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
+ DeviceCategory category;
+ for (category = 0; category < DEVICE_CATEGORY_MAX; ++category) {
+ qdev_print_category_devices(category);
+ }
+
return 1;
}
@@ -360,7 +390,7 @@
/* find device */
if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
- assert(0);
+ g_assert_not_reached();
elem[0] = len = 0;
}
pos += len;
@@ -397,7 +427,7 @@
/* find bus */
if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
- assert(0);
+ g_assert_not_reached();
elem[0] = len = 0;
}
pos += len;
diff --git a/qemu-char.c b/qemu-char.c
index c86ce4b..6259496 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -281,7 +281,7 @@
int64_t ti;
int secs;
- ti = qemu_get_clock_ms(rt_clock);
+ ti = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
if (d->timestamps_start == -1)
d->timestamps_start = ti;
ti -= d->timestamps_start;
@@ -476,6 +476,46 @@
mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
}
+static bool muxes_realized;
+
+/**
+ * Called after processing of default and command-line-specified
+ * chardevs to deliver CHR_EVENT_OPENED events to any FEs attached
+ * to a mux chardev. This is done here to ensure that
+ * output/prompts/banners are only displayed for the FE that has
+ * focus when initial command-line processing/machine init is
+ * completed.
+ *
+ * After this point, any new FE attached to any new or existing
+ * mux will receive CHR_EVENT_OPENED notifications for the BE
+ * immediately.
+ */
+static void muxes_realize_done(Notifier *notifier, void *unused)
+{
+ CharDriverState *chr;
+
+ QTAILQ_FOREACH(chr, &chardevs, next) {
+ if (chr->is_mux) {
+ MuxDriver *d = chr->opaque;
+ int i;
+
+ /* send OPENED to all already-attached FEs */
+ for (i = 0; i < d->mux_cnt; i++) {
+ mux_chr_send_event(d, i, CHR_EVENT_OPENED);
+ }
+ /* mark mux as OPENED so any new FEs will immediately receive
+ * OPENED event
+ */
+ qemu_chr_be_generic_open(chr);
+ }
+ }
+ muxes_realized = true;
+}
+
+static Notifier muxes_realize_notify = {
+ .notify = muxes_realize_done,
+};
+
static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
{
CharDriverState *chr;
@@ -492,6 +532,11 @@
chr->chr_accept_input = mux_chr_accept_input;
/* Frontend guest-open / -close notification is not support with muxes */
chr->chr_set_fe_open = NULL;
+ /* only default to opened state if we've realized the initial
+ * set of muxes
+ */
+ chr->explicit_be_open = muxes_realized ? 0 : 1;
+ chr->is_mux = 1;
return chr;
}
@@ -1097,8 +1142,8 @@
s->timer_tag = 0;
}
if (!s->connected) {
- qemu_chr_be_generic_open(chr);
s->connected = 1;
+ qemu_chr_be_generic_open(chr);
s->fd_tag = io_add_watch_poll(s->fd, pty_chr_read_poll, pty_chr_read, chr);
}
}
@@ -2783,8 +2828,8 @@
chr->opaque = NULL;
}
-static CharDriverState *qemu_chr_open_memory(ChardevMemory *opts,
- Error **errp)
+static CharDriverState *qemu_chr_open_ringbuf(ChardevRingbuf *opts,
+ Error **errp)
{
CharDriverState *chr;
RingBufCharDriver *d;
@@ -2796,7 +2841,7 @@
/* The size must be power of 2 */
if (d->size & (d->size - 1)) {
- error_setg(errp, "size of memory chardev must be power of two");
+ error_setg(errp, "size of ringbuf chardev must be power of two");
goto fail;
}
@@ -3105,17 +3150,17 @@
backend->pipe->device = g_strdup(device);
}
-static void qemu_chr_parse_memory(QemuOpts *opts, ChardevBackend *backend,
- Error **errp)
+static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
{
int val;
- backend->memory = g_new0(ChardevMemory, 1);
+ backend->ringbuf = g_new0(ChardevRingbuf, 1);
val = qemu_opt_get_size(opts, "size", 0);
if (val != 0) {
- backend->memory->has_size = true;
- backend->memory->size = val;
+ backend->ringbuf->has_size = true;
+ backend->ringbuf->size = val;
}
}
@@ -3299,7 +3344,7 @@
chr = qemu_chr_new_from_opts(opts, init, &err);
if (error_is_set(&err)) {
- fprintf(stderr, "%s\n", error_get_pretty(err));
+ error_report("%s", error_get_pretty(err));
error_free(err);
}
if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
@@ -3723,8 +3768,9 @@
case CHARDEV_BACKEND_KIND_VC:
chr = vc_init(backend->vc);
break;
+ case CHARDEV_BACKEND_KIND_RINGBUF:
case CHARDEV_BACKEND_KIND_MEMORY:
- chr = qemu_chr_open_memory(backend->memory, errp);
+ chr = qemu_chr_open_ringbuf(backend->ringbuf, errp);
break;
default:
error_setg(errp, "unknown chardev backend (%d)", backend->kind);
@@ -3774,8 +3820,8 @@
register_char_driver_qapi("null", CHARDEV_BACKEND_KIND_NULL, NULL);
register_char_driver("socket", qemu_chr_open_socket);
register_char_driver("udp", qemu_chr_open_udp);
- register_char_driver_qapi("memory", CHARDEV_BACKEND_KIND_MEMORY,
- qemu_chr_parse_memory);
+ register_char_driver_qapi("ringbuf", CHARDEV_BACKEND_KIND_RINGBUF,
+ qemu_chr_parse_ringbuf);
register_char_driver_qapi("file", CHARDEV_BACKEND_KIND_FILE,
qemu_chr_parse_file_out);
register_char_driver_qapi("stdio", CHARDEV_BACKEND_KIND_STDIO,
@@ -3794,6 +3840,14 @@
qemu_chr_parse_pipe);
register_char_driver_qapi("mux", CHARDEV_BACKEND_KIND_MUX,
qemu_chr_parse_mux);
+ /* Bug-compatibility: */
+ register_char_driver_qapi("memory", CHARDEV_BACKEND_KIND_MEMORY,
+ qemu_chr_parse_ringbuf);
+ /* this must be done after machine init, since we register FEs with muxes
+ * as part of realize functions like serial_isa_realizefn when -nographic
+ * is specified
+ */
+ qemu_add_machine_init_done_notifier(&muxes_realize_notify);
}
type_init(register_types);
diff --git a/qemu-coroutine-io.c b/qemu-coroutine-io.c
index c4df35a..054ca70 100644
--- a/qemu-coroutine-io.c
+++ b/qemu-coroutine-io.c
@@ -26,6 +26,7 @@
#include "qemu/sockets.h"
#include "block/coroutine.h"
#include "qemu/iov.h"
+#include "qemu/main-loop.h"
ssize_t coroutine_fn
qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
diff --git a/qemu-coroutine-lock.c b/qemu-coroutine-lock.c
index d9fea49..aeb33b9 100644
--- a/qemu-coroutine-lock.c
+++ b/qemu-coroutine-lock.c
@@ -88,16 +88,32 @@
return true;
}
-bool qemu_co_queue_next(CoQueue *queue)
+bool coroutine_fn qemu_co_queue_next(CoQueue *queue)
{
+ assert(qemu_in_coroutine());
return qemu_co_queue_do_restart(queue, true);
}
-void qemu_co_queue_restart_all(CoQueue *queue)
+void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue)
{
+ assert(qemu_in_coroutine());
qemu_co_queue_do_restart(queue, false);
}
+bool qemu_co_enter_next(CoQueue *queue)
+{
+ Coroutine *next;
+
+ next = QTAILQ_FIRST(&queue->entries);
+ if (!next) {
+ return false;
+ }
+
+ QTAILQ_REMOVE(&queue->entries, next, co_queue_next);
+ qemu_coroutine_enter(next, NULL);
+ return true;
+}
+
bool qemu_co_queue_empty(CoQueue *queue)
{
return (QTAILQ_FIRST(&queue->entries) == NULL);
diff --git a/qemu-coroutine-sleep.c b/qemu-coroutine-sleep.c
index 169ce5c..f6db978 100644
--- a/qemu-coroutine-sleep.c
+++ b/qemu-coroutine-sleep.c
@@ -26,14 +26,14 @@
qemu_coroutine_enter(sleep_cb->co, NULL);
}
-void coroutine_fn co_sleep_ns(QEMUClock *clock, int64_t ns)
+void coroutine_fn co_sleep_ns(QEMUClockType type, int64_t ns)
{
CoSleepCB sleep_cb = {
.co = qemu_coroutine_self(),
};
- sleep_cb.ts = qemu_new_timer(clock, SCALE_NS, co_sleep_cb, &sleep_cb);
- qemu_mod_timer(sleep_cb.ts, qemu_get_clock_ns(clock) + ns);
+ sleep_cb.ts = timer_new(type, SCALE_NS, co_sleep_cb, &sleep_cb);
+ timer_mod(sleep_cb.ts, qemu_clock_get_ns(type) + ns);
qemu_coroutine_yield();
- qemu_del_timer(sleep_cb.ts);
- qemu_free_timer(sleep_cb.ts);
+ timer_del(sleep_cb.ts);
+ timer_free(sleep_cb.ts);
}
diff --git a/qemu-img.c b/qemu-img.c
index c55ca5c..b9a848d 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -396,6 +396,9 @@
}
img_size = (uint64_t)sval;
}
+ if (optind != argc) {
+ help();
+ }
if (options && is_help_option(options)) {
return print_block_option_help(filename, fmt);
@@ -573,7 +576,7 @@
break;
}
}
- if (optind >= argc) {
+ if (optind != argc - 1) {
help();
}
filename = argv[optind++];
@@ -684,7 +687,7 @@
break;
}
}
- if (optind >= argc) {
+ if (optind != argc - 1) {
help();
}
filename = argv[optind++];
@@ -930,7 +933,7 @@
}
- if (optind > argc - 2) {
+ if (optind != argc - 2) {
help();
}
filename1 = argv[optind++];
@@ -1741,7 +1744,7 @@
break;
}
}
- if (optind >= argc) {
+ if (optind != argc - 1) {
help();
}
filename = argv[optind++];
@@ -1842,7 +1845,7 @@
}
}
- if (optind >= argc) {
+ if (optind != argc - 1) {
help();
}
filename = argv[optind++];
@@ -1953,7 +1956,7 @@
progress = 0;
}
- if ((optind >= argc) || (!unsafe && !out_baseimg)) {
+ if ((optind != argc - 1) || (!unsafe && !out_baseimg)) {
help();
}
filename = argv[optind++];
@@ -2232,7 +2235,7 @@
break;
}
}
- if (optind >= argc) {
+ if (optind != argc - 1) {
help();
}
filename = argv[optind++];
@@ -2319,6 +2322,10 @@
const img_cmd_t *cmd;
const char *cmdname;
+#ifdef CONFIG_POSIX
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
error_set_progname(argv[0]);
qemu_init_main_loop();
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index ffbcf31..f91b6c4 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -10,6 +10,7 @@
#include "qemu-io.h"
#include "block/block_int.h"
+#include "qemu/main-loop.h"
#define CMD_NOFILE_OK 0x01
diff --git a/qemu-io.c b/qemu-io.c
index cb9def5..d54dc86 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -335,6 +335,10 @@
int opt_index = 0;
int flags = BDRV_O_UNMAP;
+#ifdef CONFIG_POSIX
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
progname = basename(argv[0]);
while ((c = getopt_long(argc, argv, sopt, lopt, &opt_index)) != -1) {
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 9c31d45..f044546 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -19,6 +19,7 @@
#include "qemu-common.h"
#include "block/block.h"
#include "block/nbd.h"
+#include "qemu/main-loop.h"
#include <stdarg.h>
#include <stdio.h>
diff --git a/qemu-options.hx b/qemu-options.hx
index 2dbfd42..d15338e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -844,7 +844,8 @@
command line application. The emulated serial port is redirected on
the console and muxed with the monitor (unless redirected elsewhere
explicitly). Therefore, you can still use QEMU to debug a Linux kernel
-with a serial console.
+with a serial console. Use @key{C-a h} for help on switching between
+the console and monitor.
ETEXI
DEF("curses", 0, QEMU_OPTION_curses,
@@ -1782,7 +1783,7 @@
"-chardev msmouse,id=id[,mux=on|off]\n"
"-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n"
" [,mux=on|off]\n"
- "-chardev memory,id=id[,size=size]\n"
+ "-chardev ringbuf,id=id[,size=size]\n"
"-chardev file,id=id,path=path[,mux=on|off]\n"
"-chardev pipe,id=id,path=path[,mux=on|off]\n"
#ifdef _WIN32
@@ -1820,7 +1821,7 @@
@option{udp},
@option{msmouse},
@option{vc},
-@option{memory},
+@option{ringbuf},
@option{file},
@option{pipe},
@option{console},
@@ -1929,7 +1930,7 @@
@option{cols} and @option{rows} specify that the console be sized to fit a text
console with the given dimensions.
-@item -chardev memory ,id=@var{id} [,size=@var{size}]
+@item -chardev ringbuf ,id=@var{id} [,size=@var{size}]
Create a ring buffer with fixed size @option{size}.
@var{size} must be a power of two, and defaults to @code{64K}).
diff --git a/qemu-seccomp.c b/qemu-seccomp.c
index ca123bf..37d38f8 100644
--- a/qemu-seccomp.c
+++ b/qemu-seccomp.c
@@ -26,13 +26,11 @@
{ SCMP_SYS(timer_gettime), 254 },
{ SCMP_SYS(futex), 253 },
{ SCMP_SYS(select), 252 },
-#if defined(__x86_64__)
{ SCMP_SYS(recvfrom), 251 },
{ SCMP_SYS(sendto), 250 },
-#elif defined(__i386__)
{ SCMP_SYS(socketcall), 250 },
-#endif
{ SCMP_SYS(read), 249 },
+ { SCMP_SYS(io_submit), 249 },
{ SCMP_SYS(brk), 248 },
{ SCMP_SYS(clone), 247 },
{ SCMP_SYS(mmap), 247 },
@@ -40,7 +38,6 @@
{ SCMP_SYS(execve), 245 },
{ SCMP_SYS(open), 245 },
{ SCMP_SYS(ioctl), 245 },
-#if defined(__x86_64__)
{ SCMP_SYS(socket), 245 },
{ SCMP_SYS(setsockopt), 245 },
{ SCMP_SYS(recvmsg), 245 },
@@ -51,9 +48,7 @@
{ SCMP_SYS(bind), 245 },
{ SCMP_SYS(listen), 245 },
{ SCMP_SYS(semget), 245 },
-#elif defined(__i386__)
{ SCMP_SYS(ipc), 245 },
-#endif
{ SCMP_SYS(gettimeofday), 245 },
{ SCMP_SYS(readlink), 245 },
{ SCMP_SYS(access), 245 },
@@ -64,7 +59,6 @@
{ SCMP_SYS(statfs), 245 },
{ SCMP_SYS(unlink), 245 },
{ SCMP_SYS(wait4), 245 },
-#if defined(__i386__)
{ SCMP_SYS(fcntl64), 245 },
{ SCMP_SYS(fstat64), 245 },
{ SCMP_SYS(stat64), 245 },
@@ -77,7 +71,6 @@
{ SCMP_SYS(_llseek), 245 },
{ SCMP_SYS(mmap2), 245 },
{ SCMP_SYS(sigprocmask), 245 },
-#endif
{ SCMP_SYS(sched_getparam), 245 },
{ SCMP_SYS(sched_getscheduler), 245 },
{ SCMP_SYS(fstat), 245 },
@@ -116,7 +109,6 @@
{ SCMP_SYS(lseek), 245 },
{ SCMP_SYS(pselect6), 245 },
{ SCMP_SYS(fork), 245 },
- { SCMP_SYS(eventfd), 245 },
{ SCMP_SYS(rt_sigprocmask), 245 },
{ SCMP_SYS(write), 244 },
{ SCMP_SYS(fcntl), 243 },
@@ -145,21 +137,17 @@
{ SCMP_SYS(epoll_create), 242 },
{ SCMP_SYS(epoll_ctl), 242 },
{ SCMP_SYS(epoll_wait), 242 },
-#if defined(__i386__)
{ SCMP_SYS(waitpid), 242 },
-#elif defined(__x86_64__)
{ SCMP_SYS(getsockname), 242 },
{ SCMP_SYS(getpeername), 242 },
{ SCMP_SYS(accept4), 242 },
{ SCMP_SYS(newfstatat), 241 },
{ SCMP_SYS(shutdown), 241 },
{ SCMP_SYS(getsockopt), 241 },
- { SCMP_SYS(semctl), 241 },
{ SCMP_SYS(semop), 241 },
{ SCMP_SYS(semtimedop), 241 },
{ SCMP_SYS(epoll_ctl_old), 241 },
{ SCMP_SYS(epoll_wait_old), 241 },
-#endif
{ SCMP_SYS(epoll_pwait), 241 },
{ SCMP_SYS(epoll_create1), 241 },
{ SCMP_SYS(ppoll), 241 },
@@ -174,7 +162,6 @@
{ SCMP_SYS(getresuid), 241 },
{ SCMP_SYS(getresgid), 241 },
{ SCMP_SYS(getgroups), 241 },
-#if defined(__i386__)
{ SCMP_SYS(getresuid32), 241 },
{ SCMP_SYS(getresgid32), 241 },
{ SCMP_SYS(getgroups32), 241 },
@@ -193,7 +180,6 @@
{ SCMP_SYS(lstat64), 241 },
{ SCMP_SYS(sendfile64), 241 },
{ SCMP_SYS(ugetrlimit), 241 },
-#endif
{ SCMP_SYS(alarm), 241 },
{ SCMP_SYS(rt_sigsuspend), 241 },
{ SCMP_SYS(rt_sigqueueinfo), 241 },
@@ -205,12 +191,10 @@
{ SCMP_SYS(lchown), 241 },
{ SCMP_SYS(fchownat), 241 },
{ SCMP_SYS(fstatfs), 241 },
- { SCMP_SYS(sendfile), 241 },
{ SCMP_SYS(getitimer), 241 },
{ SCMP_SYS(syncfs), 241 },
{ SCMP_SYS(fsync), 241 },
{ SCMP_SYS(fchdir), 241 },
- { SCMP_SYS(flock), 241 },
{ SCMP_SYS(msync), 241 },
{ SCMP_SYS(sched_setparam), 241 },
{ SCMP_SYS(sched_setscheduler), 241 },
@@ -231,8 +215,10 @@
{ SCMP_SYS(recvmmsg), 241 },
{ SCMP_SYS(prlimit64), 241 },
{ SCMP_SYS(waitid), 241 },
+ { SCMP_SYS(io_cancel), 241 },
{ SCMP_SYS(io_setup), 241 },
- { SCMP_SYS(io_destroy), 241 }
+ { SCMP_SYS(io_destroy), 241 },
+ { SCMP_SYS(arch_prctl), 240 }
};
int seccomp_start(void)
diff --git a/qemu-timer.c b/qemu-timer.c
index b2d95e2..95ff47f 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -33,276 +33,277 @@
#include <pthread.h>
#endif
-#ifdef _WIN32
-#include <mmsystem.h>
+#ifdef CONFIG_PPOLL
+#include <poll.h>
+#endif
+
+#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
+#include <sys/prctl.h>
#endif
/***********************************************************/
/* timers */
-#define QEMU_CLOCK_REALTIME 0
-#define QEMU_CLOCK_VIRTUAL 1
-#define QEMU_CLOCK_HOST 2
-
-struct QEMUClock {
- QEMUTimer *active_timers;
+typedef struct QEMUClock {
+ QLIST_HEAD(, QEMUTimerList) timerlists;
NotifierList reset_notifiers;
int64_t last;
- int type;
+ QEMUClockType type;
bool enabled;
-};
+} QEMUClock;
-struct QEMUTimer {
- int64_t expire_time; /* in nanoseconds */
+QEMUTimerListGroup main_loop_tlg;
+QEMUClock qemu_clocks[QEMU_CLOCK_MAX];
+
+/* A QEMUTimerList is a list of timers attached to a clock. More
+ * than one QEMUTimerList can be attached to each clock, for instance
+ * used by different AioContexts / threads. Each clock also has
+ * a list of the QEMUTimerLists associated with it, in order that
+ * reenabling the clock can call all the notifiers.
+ */
+
+struct QEMUTimerList {
QEMUClock *clock;
- QEMUTimerCB *cb;
- void *opaque;
- QEMUTimer *next;
- int scale;
+ QEMUTimer *active_timers;
+ QLIST_ENTRY(QEMUTimerList) list;
+ QEMUTimerListNotifyCB *notify_cb;
+ void *notify_opaque;
};
-struct qemu_alarm_timer {
- char const *name;
- int (*start)(struct qemu_alarm_timer *t);
- void (*stop)(struct qemu_alarm_timer *t);
- void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
-#if defined(__linux__)
- timer_t timer;
- int fd;
-#elif defined(_WIN32)
- HANDLE timer;
-#endif
- bool expired;
- bool pending;
-};
+/**
+ * qemu_clock_ptr:
+ * @type: type of clock
+ *
+ * Translate a clock type into a pointer to QEMUClock object.
+ *
+ * Returns: a pointer to the QEMUClock object
+ */
+static inline QEMUClock *qemu_clock_ptr(QEMUClockType type)
+{
+ return &qemu_clocks[type];
+}
-static struct qemu_alarm_timer *alarm_timer;
-
-static bool qemu_timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
+static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time)
{
return timer_head && (timer_head->expire_time <= current_time);
}
-static int64_t qemu_next_alarm_deadline(void)
+QEMUTimerList *timerlist_new(QEMUClockType type,
+ QEMUTimerListNotifyCB *cb,
+ void *opaque)
{
- int64_t delta = INT64_MAX;
- int64_t rtdelta;
+ QEMUTimerList *timer_list;
+ QEMUClock *clock = qemu_clock_ptr(type);
- if (!use_icount && vm_clock->enabled && vm_clock->active_timers) {
- delta = vm_clock->active_timers->expire_time -
- qemu_get_clock_ns(vm_clock);
- }
- if (host_clock->enabled && host_clock->active_timers) {
- int64_t hdelta = host_clock->active_timers->expire_time -
- qemu_get_clock_ns(host_clock);
- if (hdelta < delta) {
- delta = hdelta;
- }
- }
- if (rt_clock->enabled && rt_clock->active_timers) {
- rtdelta = (rt_clock->active_timers->expire_time -
- qemu_get_clock_ns(rt_clock));
- if (rtdelta < delta) {
- delta = rtdelta;
- }
- }
-
- return delta;
+ timer_list = g_malloc0(sizeof(QEMUTimerList));
+ timer_list->clock = clock;
+ timer_list->notify_cb = cb;
+ timer_list->notify_opaque = opaque;
+ QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list);
+ return timer_list;
}
-static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
+void timerlist_free(QEMUTimerList *timer_list)
{
- int64_t nearest_delta_ns = qemu_next_alarm_deadline();
- if (nearest_delta_ns < INT64_MAX) {
- t->rearm(t, nearest_delta_ns);
+ assert(!timerlist_has_timers(timer_list));
+ if (timer_list->clock) {
+ QLIST_REMOVE(timer_list, list);
}
+ g_free(timer_list);
}
-/* TODO: MIN_TIMER_REARM_NS should be optimized */
-#define MIN_TIMER_REARM_NS 250000
-
-#ifdef _WIN32
-
-static int mm_start_timer(struct qemu_alarm_timer *t);
-static void mm_stop_timer(struct qemu_alarm_timer *t);
-static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
-
-static int win32_start_timer(struct qemu_alarm_timer *t);
-static void win32_stop_timer(struct qemu_alarm_timer *t);
-static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
-
-#else
-
-static int unix_start_timer(struct qemu_alarm_timer *t);
-static void unix_stop_timer(struct qemu_alarm_timer *t);
-static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
-
-#ifdef __linux__
-
-static int dynticks_start_timer(struct qemu_alarm_timer *t);
-static void dynticks_stop_timer(struct qemu_alarm_timer *t);
-static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
-
-#endif /* __linux__ */
-
-#endif /* _WIN32 */
-
-static struct qemu_alarm_timer alarm_timers[] = {
-#ifndef _WIN32
-#ifdef __linux__
- {"dynticks", dynticks_start_timer,
- dynticks_stop_timer, dynticks_rearm_timer},
-#endif
- {"unix", unix_start_timer, unix_stop_timer, unix_rearm_timer},
-#else
- {"mmtimer", mm_start_timer, mm_stop_timer, mm_rearm_timer},
- {"dynticks", win32_start_timer, win32_stop_timer, win32_rearm_timer},
-#endif
- {NULL, }
-};
-
-static void show_available_alarms(void)
+static void qemu_clock_init(QEMUClockType type)
{
- int i;
+ QEMUClock *clock = qemu_clock_ptr(type);
- printf("Available alarm timers, in order of precedence:\n");
- for (i = 0; alarm_timers[i].name; i++)
- printf("%s\n", alarm_timers[i].name);
-}
-
-void configure_alarms(char const *opt)
-{
- int i;
- int cur = 0;
- int count = ARRAY_SIZE(alarm_timers) - 1;
- char *arg;
- char *name;
- struct qemu_alarm_timer tmp;
-
- if (is_help_option(opt)) {
- show_available_alarms();
- exit(0);
- }
-
- arg = g_strdup(opt);
-
- /* Reorder the array */
- name = strtok(arg, ",");
- while (name) {
- for (i = 0; i < count && alarm_timers[i].name; i++) {
- if (!strcmp(alarm_timers[i].name, name))
- break;
- }
-
- if (i == count) {
- fprintf(stderr, "Unknown clock %s\n", name);
- goto next;
- }
-
- if (i < cur)
- /* Ignore */
- goto next;
-
- /* Swap */
- tmp = alarm_timers[i];
- alarm_timers[i] = alarm_timers[cur];
- alarm_timers[cur] = tmp;
-
- cur++;
-next:
- name = strtok(NULL, ",");
- }
-
- g_free(arg);
-
- if (cur) {
- /* Disable remaining timers */
- for (i = cur; i < count; i++)
- alarm_timers[i].name = NULL;
- } else {
- show_available_alarms();
- exit(1);
- }
-}
-
-QEMUClock *rt_clock;
-QEMUClock *vm_clock;
-QEMUClock *host_clock;
-
-static QEMUClock *qemu_new_clock(int type)
-{
- QEMUClock *clock;
-
- clock = g_malloc0(sizeof(QEMUClock));
clock->type = type;
clock->enabled = true;
clock->last = INT64_MIN;
+ QLIST_INIT(&clock->timerlists);
notifier_list_init(&clock->reset_notifiers);
- return clock;
+ main_loop_tlg.tl[type] = timerlist_new(type, NULL, NULL);
}
-void qemu_clock_enable(QEMUClock *clock, bool enabled)
+bool qemu_clock_use_for_deadline(QEMUClockType type)
{
+ return !(use_icount && (type == QEMU_CLOCK_VIRTUAL));
+}
+
+void qemu_clock_notify(QEMUClockType type)
+{
+ QEMUTimerList *timer_list;
+ QEMUClock *clock = qemu_clock_ptr(type);
+ QLIST_FOREACH(timer_list, &clock->timerlists, list) {
+ timerlist_notify(timer_list);
+ }
+}
+
+void qemu_clock_enable(QEMUClockType type, bool enabled)
+{
+ QEMUClock *clock = qemu_clock_ptr(type);
bool old = clock->enabled;
clock->enabled = enabled;
if (enabled && !old) {
- qemu_rearm_alarm_timer(alarm_timer);
+ qemu_clock_notify(type);
}
}
-int64_t qemu_clock_has_timers(QEMUClock *clock)
+bool timerlist_has_timers(QEMUTimerList *timer_list)
{
- return !!clock->active_timers;
+ return !!timer_list->active_timers;
}
-int64_t qemu_clock_expired(QEMUClock *clock)
+bool qemu_clock_has_timers(QEMUClockType type)
{
- return (clock->active_timers &&
- clock->active_timers->expire_time < qemu_get_clock_ns(clock));
+ return timerlist_has_timers(
+ main_loop_tlg.tl[type]);
}
-int64_t qemu_clock_deadline(QEMUClock *clock)
+bool timerlist_expired(QEMUTimerList *timer_list)
{
- /* To avoid problems with overflow limit this to 2^32. */
- int64_t delta = INT32_MAX;
+ return (timer_list->active_timers &&
+ timer_list->active_timers->expire_time <
+ qemu_clock_get_ns(timer_list->clock->type));
+}
- if (clock->active_timers) {
- delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock);
+bool qemu_clock_expired(QEMUClockType type)
+{
+ return timerlist_expired(
+ main_loop_tlg.tl[type]);
+}
+
+/*
+ * As above, but return -1 for no deadline, and do not cap to 2^32
+ * as we know the result is always positive.
+ */
+
+int64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
+{
+ int64_t delta;
+
+ if (!timer_list->clock->enabled || !timer_list->active_timers) {
+ return -1;
}
- if (delta < 0) {
- delta = 0;
+
+ delta = timer_list->active_timers->expire_time -
+ qemu_clock_get_ns(timer_list->clock->type);
+
+ if (delta <= 0) {
+ return 0;
}
+
return delta;
}
-QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
- QEMUTimerCB *cb, void *opaque)
+/* Calculate the soonest deadline across all timerlists attached
+ * to the clock. This is used for the icount timeout so we
+ * ignore whether or not the clock should be used in deadline
+ * calculations.
+ */
+int64_t qemu_clock_deadline_ns_all(QEMUClockType type)
{
- QEMUTimer *ts;
+ int64_t deadline = -1;
+ QEMUTimerList *timer_list;
+ QEMUClock *clock = qemu_clock_ptr(type);
+ QLIST_FOREACH(timer_list, &clock->timerlists, list) {
+ deadline = qemu_soonest_timeout(deadline,
+ timerlist_deadline_ns(timer_list));
+ }
+ return deadline;
+}
- ts = g_malloc0(sizeof(QEMUTimer));
- ts->clock = clock;
+QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list)
+{
+ return timer_list->clock->type;
+}
+
+QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type)
+{
+ return main_loop_tlg.tl[type];
+}
+
+void timerlist_notify(QEMUTimerList *timer_list)
+{
+ if (timer_list->notify_cb) {
+ timer_list->notify_cb(timer_list->notify_opaque);
+ } else {
+ qemu_notify_event();
+ }
+}
+
+/* Transition function to convert a nanosecond timeout to ms
+ * This is used where a system does not support ppoll
+ */
+int qemu_timeout_ns_to_ms(int64_t ns)
+{
+ int64_t ms;
+ if (ns < 0) {
+ return -1;
+ }
+
+ if (!ns) {
+ return 0;
+ }
+
+ /* Always round up, because it's better to wait too long than to wait too
+ * little and effectively busy-wait
+ */
+ ms = (ns + SCALE_MS - 1) / SCALE_MS;
+
+ /* To avoid overflow problems, limit this to 2^31, i.e. approx 25 days */
+ if (ms > (int64_t) INT32_MAX) {
+ ms = INT32_MAX;
+ }
+
+ return (int) ms;
+}
+
+
+/* qemu implementation of g_poll which uses a nanosecond timeout but is
+ * otherwise identical to g_poll
+ */
+int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout)
+{
+#ifdef CONFIG_PPOLL
+ if (timeout < 0) {
+ return ppoll((struct pollfd *)fds, nfds, NULL, NULL);
+ } else {
+ struct timespec ts;
+ ts.tv_sec = timeout / 1000000000LL;
+ ts.tv_nsec = timeout % 1000000000LL;
+ return ppoll((struct pollfd *)fds, nfds, &ts, NULL);
+ }
+#else
+ return g_poll(fds, nfds, qemu_timeout_ns_to_ms(timeout));
+#endif
+}
+
+
+void timer_init(QEMUTimer *ts,
+ QEMUTimerList *timer_list, int scale,
+ QEMUTimerCB *cb, void *opaque)
+{
+ ts->timer_list = timer_list;
ts->cb = cb;
ts->opaque = opaque;
ts->scale = scale;
- return ts;
}
-void qemu_free_timer(QEMUTimer *ts)
+void timer_free(QEMUTimer *ts)
{
g_free(ts);
}
/* stop a timer, but do not dealloc it */
-void qemu_del_timer(QEMUTimer *ts)
+void timer_del(QEMUTimer *ts)
{
QEMUTimer **pt, *t;
/* NOTE: this code must be signal safe because
- qemu_timer_expired() can be called from a signal. */
- pt = &ts->clock->active_timers;
+ timer_expired() can be called from a signal. */
+ pt = &ts->timer_list->active_timers;
for(;;) {
t = *pt;
if (!t)
@@ -317,19 +318,19 @@
/* modify the current timer so that it will be fired when current_time
>= expire_time. The corresponding callback will be called. */
-void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
+void timer_mod_ns(QEMUTimer *ts, int64_t expire_time)
{
QEMUTimer **pt, *t;
- qemu_del_timer(ts);
+ timer_del(ts);
/* add the timer in the sorted list */
/* NOTE: this code must be signal safe because
- qemu_timer_expired() can be called from a signal. */
- pt = &ts->clock->active_timers;
+ timer_expired() can be called from a signal. */
+ pt = &ts->timer_list->active_timers;
for(;;) {
t = *pt;
- if (!qemu_timer_expired_ns(t, expire_time)) {
+ if (!timer_expired_ns(t, expire_time)) {
break;
}
pt = &t->next;
@@ -339,27 +340,22 @@
*pt = ts;
/* Rearm if necessary */
- if (pt == &ts->clock->active_timers) {
- if (!alarm_timer->pending) {
- qemu_rearm_alarm_timer(alarm_timer);
- }
+ if (pt == &ts->timer_list->active_timers) {
/* Interrupt execution to force deadline recalculation. */
- qemu_clock_warp(ts->clock);
- if (use_icount) {
- qemu_notify_event();
- }
+ qemu_clock_warp(ts->timer_list->clock->type);
+ timerlist_notify(ts->timer_list);
}
}
-void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
+void timer_mod(QEMUTimer *ts, int64_t expire_time)
{
- qemu_mod_timer_ns(ts, expire_time * ts->scale);
+ timer_mod_ns(ts, expire_time * ts->scale);
}
-bool qemu_timer_pending(QEMUTimer *ts)
+bool timer_pending(QEMUTimer *ts)
{
QEMUTimer *t;
- for (t = ts->clock->active_timers; t != NULL; t = t->next) {
+ for (t = ts->timer_list->active_timers; t != NULL; t = t->next) {
if (t == ts) {
return true;
}
@@ -367,39 +363,90 @@
return false;
}
-bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
+bool timer_expired(QEMUTimer *timer_head, int64_t current_time)
{
- return qemu_timer_expired_ns(timer_head, current_time * timer_head->scale);
+ return timer_expired_ns(timer_head, current_time * timer_head->scale);
}
-void qemu_run_timers(QEMUClock *clock)
+bool timerlist_run_timers(QEMUTimerList *timer_list)
{
QEMUTimer *ts;
int64_t current_time;
+ bool progress = false;
- if (!clock->enabled)
- return;
+ if (!timer_list->clock->enabled) {
+ return progress;
+ }
- current_time = qemu_get_clock_ns(clock);
+ current_time = qemu_clock_get_ns(timer_list->clock->type);
for(;;) {
- ts = clock->active_timers;
- if (!qemu_timer_expired_ns(ts, current_time)) {
+ ts = timer_list->active_timers;
+ if (!timer_expired_ns(ts, current_time)) {
break;
}
/* remove timer from the list before calling the callback */
- clock->active_timers = ts->next;
+ timer_list->active_timers = ts->next;
ts->next = NULL;
/* run the callback (the timer list can be modified) */
ts->cb(ts->opaque);
+ progress = true;
+ }
+ return progress;
+}
+
+bool qemu_clock_run_timers(QEMUClockType type)
+{
+ return timerlist_run_timers(main_loop_tlg.tl[type]);
+}
+
+void timerlistgroup_init(QEMUTimerListGroup *tlg,
+ QEMUTimerListNotifyCB *cb, void *opaque)
+{
+ QEMUClockType type;
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ tlg->tl[type] = timerlist_new(type, cb, opaque);
}
}
-int64_t qemu_get_clock_ns(QEMUClock *clock)
+void timerlistgroup_deinit(QEMUTimerListGroup *tlg)
+{
+ QEMUClockType type;
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ timerlist_free(tlg->tl[type]);
+ }
+}
+
+bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg)
+{
+ QEMUClockType type;
+ bool progress = false;
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ progress |= timerlist_run_timers(tlg->tl[type]);
+ }
+ return progress;
+}
+
+int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg)
+{
+ int64_t deadline = -1;
+ QEMUClockType type;
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ if (qemu_clock_use_for_deadline(tlg->tl[type]->clock->type)) {
+ deadline = qemu_soonest_timeout(deadline,
+ timerlist_deadline_ns(
+ tlg->tl[type]));
+ }
+ }
+ return deadline;
+}
+
+int64_t qemu_clock_get_ns(QEMUClockType type)
{
int64_t now, last;
+ QEMUClock *clock = qemu_clock_ptr(type);
- switch(clock->type) {
+ switch (type) {
case QEMU_CLOCK_REALTIME:
return get_clock();
default:
@@ -420,361 +467,44 @@
}
}
-void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
+void qemu_clock_register_reset_notifier(QEMUClockType type,
+ Notifier *notifier)
{
+ QEMUClock *clock = qemu_clock_ptr(type);
notifier_list_add(&clock->reset_notifiers, notifier);
}
-void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
+void qemu_clock_unregister_reset_notifier(QEMUClockType type,
+ Notifier *notifier)
{
notifier_remove(notifier);
}
void init_clocks(void)
{
- if (!rt_clock) {
- rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
- vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
- host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
+ QEMUClockType type;
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ qemu_clock_init(type);
}
-}
-uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts)
-{
- return qemu_timer_pending(ts) ? ts->expire_time : -1;
-}
-
-void qemu_run_all_timers(void)
-{
- alarm_timer->pending = false;
-
- /* vm time timers */
- qemu_run_timers(vm_clock);
- qemu_run_timers(rt_clock);
- qemu_run_timers(host_clock);
-
- /* rearm timer, if not periodic */
- if (alarm_timer->expired) {
- alarm_timer->expired = false;
- qemu_rearm_alarm_timer(alarm_timer);
- }
-}
-
-#ifdef _WIN32
-static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused)
-#else
-static void host_alarm_handler(int host_signum)
+#ifdef CONFIG_PRCTL_PR_SET_TIMERSLACK
+ prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
#endif
-{
- struct qemu_alarm_timer *t = alarm_timer;
- if (!t)
- return;
-
- t->expired = true;
- t->pending = true;
- qemu_notify_event();
}
-#if defined(__linux__)
-
-#include "qemu/compatfd.h"
-
-static int dynticks_start_timer(struct qemu_alarm_timer *t)
+uint64_t timer_expire_time_ns(QEMUTimer *ts)
{
- struct sigevent ev;
- timer_t host_timer;
- struct sigaction act;
-
- sigfillset(&act.sa_mask);
- act.sa_flags = 0;
- act.sa_handler = host_alarm_handler;
-
- sigaction(SIGALRM, &act, NULL);
-
- /*
- * Initialize ev struct to 0 to avoid valgrind complaining
- * about uninitialized data in timer_create call
- */
- memset(&ev, 0, sizeof(ev));
- ev.sigev_value.sival_int = 0;
- ev.sigev_notify = SIGEV_SIGNAL;
-#ifdef CONFIG_SIGEV_THREAD_ID
- if (qemu_signalfd_available()) {
- ev.sigev_notify = SIGEV_THREAD_ID;
- ev._sigev_un._tid = qemu_get_thread_id();
- }
-#endif /* CONFIG_SIGEV_THREAD_ID */
- ev.sigev_signo = SIGALRM;
-
- if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) {
- perror("timer_create");
- return -1;
- }
-
- t->timer = host_timer;
-
- return 0;
+ return timer_pending(ts) ? ts->expire_time : -1;
}
-static void dynticks_stop_timer(struct qemu_alarm_timer *t)
+bool qemu_clock_run_all_timers(void)
{
- timer_t host_timer = t->timer;
+ bool progress = false;
+ QEMUClockType type;
- timer_delete(host_timer);
+ for (type = 0; type < QEMU_CLOCK_MAX; type++) {
+ progress |= qemu_clock_run_timers(type);
+ }
+
+ return progress;
}
-
-static void dynticks_rearm_timer(struct qemu_alarm_timer *t,
- int64_t nearest_delta_ns)
-{
- timer_t host_timer = t->timer;
- struct itimerspec timeout;
- int64_t current_ns;
-
- if (nearest_delta_ns < MIN_TIMER_REARM_NS)
- nearest_delta_ns = MIN_TIMER_REARM_NS;
-
- /* check whether a timer is already running */
- if (timer_gettime(host_timer, &timeout)) {
- perror("gettime");
- fprintf(stderr, "Internal timer error: aborting\n");
- exit(1);
- }
- current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec;
- if (current_ns && current_ns <= nearest_delta_ns)
- return;
-
- timeout.it_interval.tv_sec = 0;
- timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
- timeout.it_value.tv_sec = nearest_delta_ns / 1000000000;
- timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000;
- if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
- perror("settime");
- fprintf(stderr, "Internal timer error: aborting\n");
- exit(1);
- }
-}
-
-#endif /* defined(__linux__) */
-
-#if !defined(_WIN32)
-
-static int unix_start_timer(struct qemu_alarm_timer *t)
-{
- struct sigaction act;
-
- /* timer signal */
- sigfillset(&act.sa_mask);
- act.sa_flags = 0;
- act.sa_handler = host_alarm_handler;
-
- sigaction(SIGALRM, &act, NULL);
- return 0;
-}
-
-static void unix_rearm_timer(struct qemu_alarm_timer *t,
- int64_t nearest_delta_ns)
-{
- struct itimerval itv;
- int err;
-
- if (nearest_delta_ns < MIN_TIMER_REARM_NS)
- nearest_delta_ns = MIN_TIMER_REARM_NS;
-
- itv.it_interval.tv_sec = 0;
- itv.it_interval.tv_usec = 0; /* 0 for one-shot timer */
- itv.it_value.tv_sec = nearest_delta_ns / 1000000000;
- itv.it_value.tv_usec = (nearest_delta_ns % 1000000000) / 1000;
- err = setitimer(ITIMER_REAL, &itv, NULL);
- if (err) {
- perror("setitimer");
- fprintf(stderr, "Internal timer error: aborting\n");
- exit(1);
- }
-}
-
-static void unix_stop_timer(struct qemu_alarm_timer *t)
-{
- struct itimerval itv;
-
- memset(&itv, 0, sizeof(itv));
- setitimer(ITIMER_REAL, &itv, NULL);
-}
-
-#endif /* !defined(_WIN32) */
-
-
-#ifdef _WIN32
-
-static MMRESULT mm_timer;
-static TIMECAPS mm_tc;
-
-static void CALLBACK mm_alarm_handler(UINT uTimerID, UINT uMsg,
- DWORD_PTR dwUser, DWORD_PTR dw1,
- DWORD_PTR dw2)
-{
- struct qemu_alarm_timer *t = alarm_timer;
- if (!t) {
- return;
- }
- t->expired = true;
- t->pending = true;
- qemu_notify_event();
-}
-
-static int mm_start_timer(struct qemu_alarm_timer *t)
-{
- timeGetDevCaps(&mm_tc, sizeof(mm_tc));
- return 0;
-}
-
-static void mm_stop_timer(struct qemu_alarm_timer *t)
-{
- if (mm_timer) {
- timeKillEvent(mm_timer);
- }
-}
-
-static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
-{
- int64_t nearest_delta_ms = delta / 1000000;
- if (nearest_delta_ms < mm_tc.wPeriodMin) {
- nearest_delta_ms = mm_tc.wPeriodMin;
- } else if (nearest_delta_ms > mm_tc.wPeriodMax) {
- nearest_delta_ms = mm_tc.wPeriodMax;
- }
-
- if (mm_timer) {
- timeKillEvent(mm_timer);
- }
- mm_timer = timeSetEvent((UINT)nearest_delta_ms,
- mm_tc.wPeriodMin,
- mm_alarm_handler,
- (DWORD_PTR)t,
- TIME_ONESHOT | TIME_CALLBACK_FUNCTION);
-
- if (!mm_timer) {
- fprintf(stderr, "Failed to re-arm win32 alarm timer\n");
- timeEndPeriod(mm_tc.wPeriodMin);
- exit(1);
- }
-}
-
-static int win32_start_timer(struct qemu_alarm_timer *t)
-{
- HANDLE hTimer;
- BOOLEAN success;
-
- /* If you call ChangeTimerQueueTimer on a one-shot timer (its period
- is zero) that has already expired, the timer is not updated. Since
- creating a new timer is relatively expensive, set a bogus one-hour
- interval in the dynticks case. */
- success = CreateTimerQueueTimer(&hTimer,
- NULL,
- host_alarm_handler,
- t,
- 1,
- 3600000,
- WT_EXECUTEINTIMERTHREAD);
-
- if (!success) {
- fprintf(stderr, "Failed to initialize win32 alarm timer: %ld\n",
- GetLastError());
- return -1;
- }
-
- t->timer = hTimer;
- return 0;
-}
-
-static void win32_stop_timer(struct qemu_alarm_timer *t)
-{
- HANDLE hTimer = t->timer;
-
- if (hTimer) {
- DeleteTimerQueueTimer(NULL, hTimer, NULL);
- }
-}
-
-static void win32_rearm_timer(struct qemu_alarm_timer *t,
- int64_t nearest_delta_ns)
-{
- HANDLE hTimer = t->timer;
- int64_t nearest_delta_ms;
- BOOLEAN success;
-
- nearest_delta_ms = nearest_delta_ns / 1000000;
- if (nearest_delta_ms < 1) {
- nearest_delta_ms = 1;
- }
- /* ULONG_MAX can be 32 bit */
- if (nearest_delta_ms > ULONG_MAX) {
- nearest_delta_ms = ULONG_MAX;
- }
- success = ChangeTimerQueueTimer(NULL,
- hTimer,
- (unsigned long) nearest_delta_ms,
- 3600000);
-
- if (!success) {
- fprintf(stderr, "Failed to rearm win32 alarm timer: %ld\n",
- GetLastError());
- exit(-1);
- }
-
-}
-
-#endif /* _WIN32 */
-
-static void quit_timers(void)
-{
- struct qemu_alarm_timer *t = alarm_timer;
- alarm_timer = NULL;
- t->stop(t);
-}
-
-#ifdef CONFIG_POSIX
-static void reinit_timers(void)
-{
- struct qemu_alarm_timer *t = alarm_timer;
- t->stop(t);
- if (t->start(t)) {
- fprintf(stderr, "Internal timer error: aborting\n");
- exit(1);
- }
- qemu_rearm_alarm_timer(t);
-}
-#endif /* CONFIG_POSIX */
-
-int init_timer_alarm(void)
-{
- struct qemu_alarm_timer *t = NULL;
- int i, err = -1;
-
- if (alarm_timer) {
- return 0;
- }
-
- for (i = 0; alarm_timers[i].name; i++) {
- t = &alarm_timers[i];
-
- err = t->start(t);
- if (!err)
- break;
- }
-
- if (err) {
- err = -ENOENT;
- goto fail;
- }
-
- atexit(quit_timers);
-#ifdef CONFIG_POSIX
- pthread_atfork(NULL, NULL, reinit_timers);
-#endif
- alarm_timer = t;
- return 0;
-
-fail:
- return err;
-}
-
diff --git a/qemu.nsi b/qemu.nsi
new file mode 100644
index 0000000..1d57455
--- /dev/null
+++ b/qemu.nsi
@@ -0,0 +1,250 @@
+;!/usr/bin/makensis
+
+; This NSIS script creates an installer for QEMU on Windows.
+
+; Copyright (C) 2006-2012 Stefan Weil
+;
+; This program is free software: you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation, either version 2 of the License, or
+; (at your option) version 3 or any later version.
+;
+; This program 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 General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+; NSIS_WIN32_MAKENSIS
+
+!define PRODUCT "QEMU"
+!define URL "http://www.qemu.org/"
+
+!define UNINST_EXE "$INSTDIR\qemu-uninstall.exe"
+!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT}"
+
+!ifndef BINDIR
+!define BINDIR nsis.tmp
+!endif
+!ifndef SRCDIR
+!define SRCDIR .
+!endif
+!ifndef OUTFILE
+!define OUTFILE "qemu-setup.exe"
+!endif
+
+; Optionally install documentation.
+!ifndef CONFIG_DOCUMENTATION
+!define CONFIG_DOCUMENTATION
+!endif
+
+; Use maximum compression.
+SetCompressor /SOLID lzma
+
+!include "MUI2.nsh"
+
+; The name of the installer.
+Name "QEMU"
+
+; The file to write
+OutFile "${OUTFILE}"
+
+; The default installation directory.
+!ifdef W64
+InstallDir $PROGRAMFILES64\qemu
+!else
+InstallDir $PROGRAMFILES\qemu
+!endif
+
+; Registry key to check for directory (so if you install again, it will
+; overwrite the old one automatically)
+InstallDirRegKey HKLM "Software\qemu" "Install_Dir"
+
+; Request administrator privileges for Windows Vista.
+RequestExecutionLevel admin
+
+;--------------------------------
+; Interface Settings.
+;!define MUI_HEADERIMAGE "qemu-nsis.bmp"
+; !define MUI_SPECIALBITMAP "qemu.bmp"
+!define MUI_ICON "${SRCDIR}\pc-bios\qemu-nsis.ico"
+!define MUI_UNICON "${SRCDIR}\pc-bios\qemu-nsis.ico"
+!define MUI_WELCOMEFINISHPAGE_BITMAP "${SRCDIR}\pc-bios\qemu-nsis.bmp"
+; !define MUI_HEADERIMAGE_BITMAP "qemu-install.bmp"
+; !define MUI_HEADERIMAGE_UNBITMAP "qemu-uninstall.bmp"
+; !define MUI_COMPONENTSPAGE_SMALLDESC
+; !define MUI_WELCOMEPAGE_TEXT "Insert text here.$\r$\n$\r$\n$\r$\n$_CLICK"
+
+;--------------------------------
+; Pages.
+
+!insertmacro MUI_PAGE_WELCOME
+!insertmacro MUI_PAGE_LICENSE "${SRCDIR}\COPYING"
+!insertmacro MUI_PAGE_COMPONENTS
+!insertmacro MUI_PAGE_DIRECTORY
+!insertmacro MUI_PAGE_INSTFILES
+!define MUI_FINISHPAGE_LINK "Visit the QEMU Wiki online!"
+!define MUI_FINISHPAGE_LINK_LOCATION "${URL}"
+!insertmacro MUI_PAGE_FINISH
+
+!insertmacro MUI_UNPAGE_CONFIRM
+!insertmacro MUI_UNPAGE_INSTFILES
+
+;--------------------------------
+; Languages.
+
+!insertmacro MUI_LANGUAGE "English"
+!insertmacro MUI_LANGUAGE "French"
+!insertmacro MUI_LANGUAGE "German"
+
+;--------------------------------
+
+; The stuff to install.
+Section "${PRODUCT} (required)"
+
+ SectionIn RO
+
+ ; Set output path to the installation directory.
+ SetOutPath "$INSTDIR"
+
+ File "${SRCDIR}\Changelog"
+ File "${SRCDIR}\COPYING"
+ File "${SRCDIR}\COPYING.LIB"
+ File "${SRCDIR}\README"
+ File "${SRCDIR}\VERSION"
+
+ File "${BINDIR}\*.bmp"
+ File "${BINDIR}\*.bin"
+ File "${BINDIR}\*.dtb"
+ File "${BINDIR}\*.rom"
+ File "${BINDIR}\openbios-*"
+
+ File /r "${BINDIR}\keymaps"
+!ifdef CONFIG_GTK
+ File /r "${BINDIR}\share"
+!endif
+
+!ifdef W64
+ SetRegView 64
+!endif
+
+ ; Write the installation path into the registry
+ WriteRegStr HKLM SOFTWARE\${PRODUCT} "Install_Dir" "$INSTDIR"
+
+ ; Write the uninstall keys for Windows
+ WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "QEMU"
+ WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" '"${UNINST_EXE}"'
+ WriteRegDWORD HKLM "${UNINST_KEY}" "NoModify" 1
+ WriteRegDWORD HKLM "${UNINST_KEY}" "NoRepair" 1
+ WriteUninstaller "qemu-uninstall.exe"
+SectionEnd
+
+Section "Tools" SectionTools
+ SetOutPath "$INSTDIR"
+ File "${BINDIR}\qemu-img.exe"
+ File "${BINDIR}\qemu-io.exe"
+SectionEnd
+
+SectionGroup "System Emulations" SectionSystem
+
+!include "${BINDIR}\system-emulations.nsh"
+
+SectionGroupEnd
+
+!ifdef DLLDIR
+Section "Libraries (DLL)" SectionDll
+ SetOutPath "$INSTDIR"
+ File "${DLLDIR}\*.dll"
+SectionEnd
+!endif
+
+!ifdef CONFIG_DOCUMENTATION
+Section "Documentation" SectionDoc
+ SetOutPath "$INSTDIR"
+ File "${BINDIR}\qemu-doc.html"
+ File "${BINDIR}\qemu-tech.html"
+ CreateDirectory "$SMPROGRAMS\${PRODUCT}"
+ CreateShortCut "$SMPROGRAMS\${PRODUCT}\User Documentation.lnk" "$INSTDIR\qemu-doc.html" "" "$INSTDIR\qemu-doc.html" 0
+ CreateShortCut "$SMPROGRAMS\${PRODUCT}\Technical Documentation.lnk" "$INSTDIR\qemu-tech.html" "" "$INSTDIR\qemu-tech.html" 0
+SectionEnd
+!endif
+
+; Optional section (can be disabled by the user)
+Section "Start Menu Shortcuts" SectionMenu
+ CreateDirectory "$SMPROGRAMS\${PRODUCT}"
+ CreateShortCut "$SMPROGRAMS\${PRODUCT}\Uninstall.lnk" "${UNINST_EXE}" "" "${UNINST_EXE}" 0
+SectionEnd
+
+;--------------------------------
+
+; Uninstaller
+
+Section "Uninstall"
+ ; Remove registry keys
+!ifdef W64
+ SetRegView 64
+!endif
+ DeleteRegKey HKLM "${UNINST_KEY}"
+ DeleteRegKey HKLM SOFTWARE\${PRODUCT}
+
+ ; Remove shortcuts, if any
+ Delete "$SMPROGRAMS\${PRODUCT}\User Documentation.lnk"
+ Delete "$SMPROGRAMS\${PRODUCT}\Technical Documentation.lnk"
+ Delete "$SMPROGRAMS\${PRODUCT}\Uninstall.lnk"
+ RMDir "$SMPROGRAMS\${PRODUCT}"
+
+ ; Remove files and directories used
+ Delete "$INSTDIR\Changelog"
+ Delete "$INSTDIR\COPYING"
+ Delete "$INSTDIR\COPYING.LIB"
+ Delete "$INSTDIR\README"
+ Delete "$INSTDIR\VERSION"
+ Delete "$INSTDIR\*.bmp"
+ Delete "$INSTDIR\*.bin"
+ Delete "$INSTDIR\*.dll"
+ Delete "$INSTDIR\*.dtb"
+ Delete "$INSTDIR\*.rom"
+ Delete "$INSTDIR\openbios-*"
+ Delete "$INSTDIR\qemu-img.exe"
+ Delete "$INSTDIR\qemu-io.exe"
+ Delete "$INSTDIR\qemu.exe"
+ Delete "$INSTDIR\qemu-system-*.exe"
+ Delete "$INSTDIR\qemu-doc.html"
+ Delete "$INSTDIR\qemu-tech.html"
+ RMDir /r "$INSTDIR\keymaps"
+ RMDir /r "$INSTDIR\share"
+ ; Remove generated files
+ Delete "$INSTDIR\stderr.txt"
+ Delete "$INSTDIR\stdout.txt"
+ ; Remove uninstaller
+ Delete "${UNINST_EXE}"
+ RMDir "$INSTDIR"
+SectionEnd
+
+;--------------------------------
+
+; Descriptions (mouse-over).
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+ !insertmacro MUI_DESCRIPTION_TEXT ${SectionSystem} "System emulation."
+ !insertmacro MUI_DESCRIPTION_TEXT ${Section_alpha} "Alpha system emulation."
+ !insertmacro MUI_DESCRIPTION_TEXT ${Section_alphaw} "Alpha system emulation (GUI)."
+ !insertmacro MUI_DESCRIPTION_TEXT ${Section_i386} "PC i386 system emulation."
+ !insertmacro MUI_DESCRIPTION_TEXT ${Section_i386w} "PC i386 system emulation (GUI)."
+ !insertmacro MUI_DESCRIPTION_TEXT ${SectionTools} "Tools."
+!ifdef DLLDIR
+ !insertmacro MUI_DESCRIPTION_TEXT ${SectionDll} "Runtime Libraries (DLL)."
+!endif
+!ifdef CONFIG_DOCUMENTATION
+ !insertmacro MUI_DESCRIPTION_TEXT ${SectionDoc} "Documentation."
+!endif
+ !insertmacro MUI_DESCRIPTION_TEXT ${SectionMenu} "Menu entries."
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
+
+;--------------------------------
+; Functions.
+
+Function .onInit
+ !insertmacro MUI_LANGDLL_DISPLAY
+FunctionEnd
diff --git a/qga/service-win32.c b/qga/service-win32.c
index 02926ab..aef41f0 100644
--- a/qga/service-win32.c
+++ b/qga/service-win32.c
@@ -29,36 +29,106 @@
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(char *)&message, 0,
NULL);
- n = printf("%s. (Error: %d) %s", text, (int)err, message);
+ n = fprintf(stderr, "%s. (Error: %d) %s", text, (int)err, message);
LocalFree(message);
return n;
}
+/* Windows command line escaping. Based on
+ * <http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx> and
+ * <http://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft%28v=vs.85%29.aspx>.
+ *
+ * The caller is responsible for initializing @buffer; prior contents are lost.
+ */
+static const char *win_escape_arg(const char *to_escape, GString *buffer)
+{
+ size_t backslash_count;
+ const char *c;
+
+ /* open with a double quote */
+ g_string_assign(buffer, "\"");
+
+ backslash_count = 0;
+ for (c = to_escape; *c != '\0'; ++c) {
+ switch (*c) {
+ case '\\':
+ /* The meaning depends on the first non-backslash character coming
+ * up.
+ */
+ ++backslash_count;
+ break;
+
+ case '"':
+ /* We must escape each pending backslash, then escape the double
+ * quote. This creates a case of "odd number of backslashes [...]
+ * followed by a double quotation mark".
+ */
+ while (backslash_count) {
+ --backslash_count;
+ g_string_append(buffer, "\\\\");
+ }
+ g_string_append(buffer, "\\\"");
+ break;
+
+ default:
+ /* Any pending backslashes are without special meaning, flush them.
+ * "Backslashes are interpreted literally, unless they immediately
+ * precede a double quotation mark."
+ */
+ while (backslash_count) {
+ --backslash_count;
+ g_string_append_c(buffer, '\\');
+ }
+ g_string_append_c(buffer, *c);
+ }
+ }
+
+ /* We're about to close with a double quote in string delimiter role.
+ * Double all pending backslashes, creating a case of "even number of
+ * backslashes [...] followed by a double quotation mark".
+ */
+ while (backslash_count) {
+ --backslash_count;
+ g_string_append(buffer, "\\\\");
+ }
+ g_string_append_c(buffer, '"');
+
+ return buffer->str;
+}
+
int ga_install_service(const char *path, const char *logfile,
const char *state_dir)
{
+ int ret = EXIT_FAILURE;
SC_HANDLE manager;
SC_HANDLE service;
TCHAR module_fname[MAX_PATH];
+ GString *esc;
GString *cmdline;
+ SERVICE_DESCRIPTION desc = { (char *)QGA_SERVICE_DESCRIPTION };
if (GetModuleFileName(NULL, module_fname, MAX_PATH) == 0) {
printf_win_error("No full path to service's executable");
return EXIT_FAILURE;
}
- cmdline = g_string_new(module_fname);
- g_string_append(cmdline, " -d");
+ esc = g_string_new("");
+ cmdline = g_string_new("");
+
+ g_string_append_printf(cmdline, "%s -d",
+ win_escape_arg(module_fname, esc));
if (path) {
- g_string_append_printf(cmdline, " -p %s", path);
+ g_string_append_printf(cmdline, " -p %s", win_escape_arg(path, esc));
}
if (logfile) {
- g_string_append_printf(cmdline, " -l %s -v", logfile);
+ g_string_append_printf(cmdline, " -l %s -v",
+ win_escape_arg(logfile, esc));
}
if (state_dir) {
- g_string_append_printf(cmdline, " -t %s", state_dir);
+ g_string_append_printf(cmdline, " -t %s",
+ win_escape_arg(state_dir, esc));
}
g_debug("service's cmdline: %s", cmdline->str);
@@ -66,28 +136,29 @@
manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (manager == NULL) {
printf_win_error("No handle to service control manager");
- g_string_free(cmdline, TRUE);
- return EXIT_FAILURE;
+ goto out_strings;
}
service = CreateService(manager, QGA_SERVICE_NAME, QGA_SERVICE_DISPLAY_NAME,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL, cmdline->str, NULL, NULL, NULL, NULL, NULL);
-
- if (service) {
- SERVICE_DESCRIPTION desc = { (char *)QGA_SERVICE_DESCRIPTION };
- ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &desc);
-
- printf("Service was installed successfully.\n");
- } else {
+ if (service == NULL) {
printf_win_error("Failed to install service");
+ goto out_manager;
}
+ ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &desc);
+ fprintf(stderr, "Service was installed successfully.\n");
+ ret = EXIT_SUCCESS;
CloseServiceHandle(service);
+
+out_manager:
CloseServiceHandle(manager);
+out_strings:
g_string_free(cmdline, TRUE);
- return (service == NULL);
+ g_string_free(esc, TRUE);
+ return ret;
}
int ga_uninstall_service(void)
@@ -111,7 +182,7 @@
if (DeleteService(service) == FALSE) {
printf_win_error("Failed to delete service");
} else {
- printf("Service was deleted successfully.\n");
+ fprintf(stderr, "Service was deleted successfully.\n");
}
CloseServiceHandle(service);
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 65a9e26..cf47e3f 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -960,6 +960,7 @@
Example:
-> { "execute": "drive-backup", "arguments": { "device": "drive0",
+ "sync": "full",
"target": "backup.img" } }
<- { "return": {} }
EQMP
@@ -2620,6 +2621,12 @@
- "total-time": total amount of ms since migration started. If
migration has ended, it returns the total migration
time (json-int)
+- "setup-time" amount of setup time in milliseconds _before_ the
+ iterations begin but _after_ the QMP command is issued.
+ This is designed to provide an accounting of any activities
+ (such as RDMA pinning) which may be expensive, but do not
+ actually occur during the iterative migration rounds
+ themselves. (json-int)
- "downtime": only present when migration has finished correctly
total amount in ms for downtime that happened (json-int)
- "expected-downtime": only present while migration is active
@@ -2673,6 +2680,7 @@
"remaining":123,
"total":246,
"total-time":12345,
+ "setup-time":12345,
"downtime":12345,
"duplicate":123,
"normal":123,
@@ -2697,6 +2705,7 @@
"remaining":123,
"total":246,
"total-time":12345,
+ "setup-time":12345,
"expected-downtime":12345,
"duplicate":123,
"normal":123,
@@ -2716,6 +2725,7 @@
"remaining":1053304,
"transferred":3720,
"total-time":12345,
+ "setup-time":12345,
"expected-downtime":12345,
"duplicate":123,
"normal":123,
@@ -2741,6 +2751,7 @@
"remaining":1053304,
"transferred":3720,
"total-time":12345,
+ "setup-time":12345,
"expected-downtime":12345,
"duplicate":10,
"normal":3333,
diff --git a/qobject/qdict.c b/qobject/qdict.c
index ed381f9..472f106 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -476,3 +476,54 @@
g_free(qdict);
}
+
+static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix)
+{
+ QObject *value;
+ const QDictEntry *entry, *next;
+ const char *new_key;
+ bool delete;
+
+ entry = qdict_first(qdict);
+
+ while (entry != NULL) {
+
+ next = qdict_next(qdict, entry);
+ value = qdict_entry_value(entry);
+ new_key = NULL;
+ delete = false;
+
+ if (prefix) {
+ qobject_incref(value);
+ new_key = g_strdup_printf("%s.%s", prefix, entry->key);
+ qdict_put_obj(target, new_key, value);
+ delete = true;
+ }
+
+ if (qobject_type(value) == QTYPE_QDICT) {
+ qdict_do_flatten(qobject_to_qdict(value), target,
+ new_key ? new_key : entry->key);
+ delete = true;
+ }
+
+ if (delete) {
+ qdict_del(qdict, entry->key);
+
+ /* Restart loop after modifying the iterated QDict */
+ entry = qdict_first(qdict);
+ continue;
+ }
+
+ entry = next;
+ }
+}
+
+/**
+ * qdict_flatten(): For each nested QDict with key x, all fields with key y
+ * are moved to this QDict and their key is renamed to "x.y". This operation
+ * is applied recursively for nested QDicts.
+ */
+void qdict_flatten(QDict *qdict)
+{
+ qdict_do_flatten(qdict, qdict, NULL);
+}
diff --git a/qobject/qjson.c b/qobject/qjson.c
index 19085a1..6cf2511 100644
--- a/qobject/qjson.c
+++ b/qobject/qjson.c
@@ -260,6 +260,8 @@
/* XXX: should QError be emitted? */
case QTYPE_NONE:
break;
+ case QTYPE_MAX:
+ abort();
}
}
diff --git a/qom/cpu.c b/qom/cpu.c
index 5c45ab5..e71e57b 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -157,6 +157,17 @@
}
+static int cpu_common_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg)
+{
+ return 0;
+}
+
+static int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg)
+{
+ return 0;
+}
+
+
void cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
@@ -217,8 +228,6 @@
{
CPUState *cpu = CPU(dev);
- qemu_init_vcpu(cpu);
-
if (dev->hotplugged) {
cpu_synchronize_post_init(cpu);
notifier_list_notify(&cpu_added_notifiers, dev);
@@ -226,6 +235,14 @@
}
}
+static void cpu_common_initfn(Object *obj)
+{
+ CPUState *cpu = CPU(obj);
+ CPUClass *cc = CPU_GET_CLASS(obj);
+
+ cpu->gdb_num_regs = cpu->gdb_num_g_regs = cc->gdb_num_core_regs;
+}
+
static int64_t cpu_common_get_arch_id(CPUState *cpu)
{
return cpu->cpu_index;
@@ -245,6 +262,8 @@
k->write_elf32_note = cpu_common_write_elf32_note;
k->write_elf64_qemunote = cpu_common_write_elf64_qemunote;
k->write_elf64_note = cpu_common_write_elf64_note;
+ k->gdb_read_register = cpu_common_gdb_read_register;
+ k->gdb_write_register = cpu_common_gdb_write_register;
dc->realize = cpu_common_realizefn;
dc->no_user = 1;
}
@@ -253,6 +272,7 @@
.name = TYPE_CPU,
.parent = TYPE_DEVICE,
.instance_size = sizeof(CPUState),
+ .instance_init = cpu_common_initfn,
.abstract = true,
.class_size = sizeof(CPUClass),
.class_init = cpu_class_init,
diff --git a/qom/object.c b/qom/object.c
index b2479d1..74fd241 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -51,6 +51,7 @@
void *class_data;
void (*instance_init)(Object *obj);
+ void (*instance_post_init)(Object *obj);
void (*instance_finalize)(Object *obj);
bool abstract;
@@ -111,6 +112,7 @@
ti->class_data = info->class_data;
ti->instance_init = info->instance_init;
+ ti->instance_post_init = info->instance_post_init;
ti->instance_finalize = info->instance_finalize;
ti->abstract = info->abstract;
@@ -298,6 +300,17 @@
}
}
+static void object_post_init_with_type(Object *obj, TypeImpl *ti)
+{
+ if (ti->instance_post_init) {
+ ti->instance_post_init(obj);
+ }
+
+ if (type_has_parent(ti)) {
+ object_post_init_with_type(obj, type_get_parent(ti));
+ }
+}
+
void object_initialize_with_type(void *data, TypeImpl *type)
{
Object *obj = data;
@@ -313,6 +326,7 @@
object_ref(obj);
QTAILQ_INIT(&obj->properties);
object_init_with_type(obj, type);
+ object_post_init_with_type(obj, type);
}
void object_initialize(void *data, const char *typename)
diff --git a/qtest.c b/qtest.c
index 74f1842..ef671fb 100644
--- a/qtest.c
+++ b/qtest.c
@@ -47,7 +47,7 @@
*
* Clock management:
*
- * The qtest client is completely in charge of the vm_clock. qtest commands
+ * The qtest client is completely in charge of the QEMU_CLOCK_VIRTUAL. qtest commands
* let you adjust the value of the clock (monotonically). All the commands
* return the current value of the clock in nanoseconds.
*
@@ -412,11 +412,11 @@
if (words[1]) {
ns = strtoll(words[1], NULL, 0);
} else {
- ns = qemu_clock_deadline(vm_clock);
+ ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
}
- qtest_clock_warp(qemu_get_clock_ns(vm_clock) + ns);
+ qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns);
qtest_send_prefix(chr);
- qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_get_clock_ns(vm_clock));
+ qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
} else if (strcmp(words[0], "clock_set") == 0) {
int64_t ns;
@@ -424,7 +424,7 @@
ns = strtoll(words[1], NULL, 0);
qtest_clock_warp(ns);
qtest_send_prefix(chr);
- qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_get_clock_ns(vm_clock));
+ qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
} else {
qtest_send_prefix(chr);
qtest_send(chr, "FAIL Unknown command `%s'\n", words[0]);
diff --git a/roms/openbios b/roms/openbios
index 569e40c..0f3d51e 160000
--- a/roms/openbios
+++ b/roms/openbios
@@ -1 +1 @@
-Subproject commit 569e40c517e9623e672be38a21da7bcec046e3be
+Subproject commit 0f3d51ef22ec9166beb3ed434d253029ed7cfe84
diff --git a/savevm.c b/savevm.c
index 03fc4d9..c536aa4 100644
--- a/savevm.c
+++ b/savevm.c
@@ -97,18 +97,18 @@
if (--count) {
/* delay 50ms, 150ms, 250ms, ... */
- qemu_mod_timer(timer, qemu_get_clock_ms(rt_clock) +
+ timer_mod(timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) +
50 + (SELF_ANNOUNCE_ROUNDS - count - 1) * 100);
} else {
- qemu_del_timer(timer);
- qemu_free_timer(timer);
+ timer_del(timer);
+ timer_free(timer);
}
}
void qemu_announce_self(void)
{
static QEMUTimer *timer;
- timer = qemu_new_timer_ms(rt_clock, qemu_announce_self_once, &timer);
+ timer = timer_new_ms(QEMU_CLOCK_REALTIME, qemu_announce_self_once, &timer);
qemu_announce_self_once(&timer);
}
@@ -979,23 +979,23 @@
/* timer */
-void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
+void timer_put(QEMUFile *f, QEMUTimer *ts)
{
uint64_t expire_time;
- expire_time = qemu_timer_expire_time_ns(ts);
+ expire_time = timer_expire_time_ns(ts);
qemu_put_be64(f, expire_time);
}
-void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
+void timer_get(QEMUFile *f, QEMUTimer *ts)
{
uint64_t expire_time;
expire_time = qemu_get_be64(f);
if (expire_time != -1) {
- qemu_mod_timer_ns(ts, expire_time);
+ timer_mod_ns(ts, expire_time);
} else {
- qemu_del_timer(ts);
+ timer_del(ts);
}
}
@@ -1339,14 +1339,14 @@
static int get_timer(QEMUFile *f, void *pv, size_t size)
{
QEMUTimer *v = pv;
- qemu_get_timer(f, v);
+ timer_get(f, v);
return 0;
}
static void put_timer(QEMUFile *f, void *pv, size_t size)
{
QEMUTimer *v = pv;
- qemu_put_timer(f, v);
+ timer_put(f, v);
}
const VMStateInfo vmstate_info_timer = {
@@ -2387,7 +2387,7 @@
qemu_gettimeofday(&tv);
sn->date_sec = tv.tv_sec;
sn->date_nsec = tv.tv_usec * 1000;
- sn->vm_clock_nsec = qemu_get_clock_ns(vm_clock);
+ sn->vm_clock_nsec = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
if (name) {
ret = bdrv_snapshot_find(bs, old_sn, name);
diff --git a/scripts/disas-objdump.pl b/scripts/disas-objdump.pl
new file mode 100755
index 0000000..8f7e818
--- /dev/null
+++ b/scripts/disas-objdump.pl
@@ -0,0 +1,99 @@
+#!/usr/bin/perl -w
+
+use File::Temp qw/ tempfile /;
+use Getopt::Long;
+
+# Default to the system objdump if a cross-compiler edition not given.
+my $aobjdump = "objdump";
+my $hobjdump = "";
+my $tobjdump = "";
+my $hmachine = "";
+my $tmachine = "";
+
+GetOptions ('O|objdump=s' => \$aobjdump,
+ 'host-objdump=s' => \$hobjdump,
+ 'target-objdump=s' => \$tobjdump,
+ 'h|host-machine=s' => \$hmachine,
+ 't|target-machine=s' => \$tmachine);
+
+# But we can't default the machines. Sanity check that we've at least one.
+die "No host or target machine type" if !$hmachine && !$tmachine;
+
+# Reuse one temp file for all of the hunks.
+my ($outh, $outname) = tempfile();
+binmode($outh);
+END { unlink $outname; }
+
+# Pre-construct the command-lines for executing the dump.
+sub mkobjcommand ($$) {
+ my ($cmd, $mach) = @_;
+ return 0 if !$mach;
+ $cmd = $aobjdump if !$cmd;
+ return "$cmd -m $mach --disassemble-all -b binary";
+}
+
+$objdump[1] = mkobjcommand($hobjdump, $hmachine);
+$objdump[2] = mkobjcommand($tobjdump, $tmachine);
+
+# Zero-initialize current dumping state.
+my $mem = "";
+my $inobjd = 0;
+my $vma = 0;
+
+sub objcommand {
+ my $ret = $objdump[$inobjd];
+ if (!$ret) {
+ die "Host machine type not specified" if $inobjd == 1;
+ die "Target machine type not specified" if $inobjd == 2;
+ die "Internal error";
+ }
+ return $ret;
+}
+
+while (<>) {
+ # Collect the data from the relevant OBJD-* lines ...
+ if (/^OBJD-H: /) {
+ die "Internal error" if $inobjd == 2;
+ $mem = $mem . pack("H*", substr($_, 8, -1));
+ $inobjd = 1;
+ } elsif (/^OBJD-T: /) {
+ die "Internal error" if $inobjd == 1;
+ $mem = $mem . pack("H*", substr($_, 8, -1));
+ $inobjd = 2;
+ }
+ # ... which will always be followed by a blank line,
+ # at which point we should produce our dump.
+ elsif ($inobjd) {
+ # Rewrite the temp file in one go; it will usually be small.
+ sysseek $outh, 0, 0;
+ truncate $outh, 0;
+ syswrite $outh, $mem;
+
+ my $cmd = objcommand();
+ $cmd = $cmd . " --adjust-vma=" . $vma if $vma;
+ $cmd = $cmd . " " . $outname;
+
+ # Pipe from objdump...
+ open IN, "-|", $cmd;
+
+ # ... copying all but the first 7 lines of boilerplate to our stdout.
+ my $i = 0;
+ while (<IN>) {
+ print if (++$i > 7);
+ }
+ close IN;
+ print "\n";
+
+ $mem = "";
+ $inobjd = 0;
+ $vma = 0;
+ }
+ # The line before "OBJD-*" will be of the form "0x<hex>+: +\n".
+ # Extract the value for passing to --adjust-vma.
+ elsif (/^(0x[0-9a-fA-F]+):\s*$/) {
+ $vma = $1;
+ print;
+ } else {
+ print;
+ }
+}
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index ddcfed9..5ee46ea 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -150,7 +150,48 @@
return lookup_decl + enum_decl
-def generate_union(name, typeinfo):
+def generate_anon_union_qtypes(expr):
+
+ name = expr['union']
+ members = expr['data']
+
+ ret = mcgen('''
+const int %(name)s_qtypes[QTYPE_MAX] = {
+''',
+ name=name)
+
+ for key in members:
+ qapi_type = members[key]
+ if builtin_type_qtypes.has_key(qapi_type):
+ qtype = builtin_type_qtypes[qapi_type]
+ elif find_struct(qapi_type):
+ qtype = "QTYPE_QDICT"
+ elif find_union(qapi_type):
+ qtype = "QTYPE_QDICT"
+ else:
+ assert False, "Invalid anonymous union member"
+
+ ret += mcgen('''
+ [ %(qtype)s ] = %(abbrev)s_KIND_%(enum)s,
+''',
+ qtype = qtype,
+ abbrev = de_camel_case(name).upper(),
+ enum = c_fun(de_camel_case(key),False).upper())
+
+ ret += mcgen('''
+};
+''')
+ return ret
+
+
+def generate_union(expr):
+
+ name = expr['union']
+ typeinfo = expr['data']
+
+ base = expr.get('base')
+ discriminator = expr.get('discriminator')
+
ret = mcgen('''
struct %(name)s
{
@@ -169,8 +210,26 @@
ret += mcgen('''
};
+''')
+
+ if base:
+ base_fields = find_struct(base)['data']
+ if discriminator:
+ base_fields = base_fields.copy()
+ del base_fields[discriminator]
+ ret += generate_struct_fields(base_fields)
+ else:
+ assert not discriminator
+
+ ret += mcgen('''
};
''')
+ if discriminator == {}:
+ ret += mcgen('''
+extern const int %(name)s_qtypes[];
+''',
+ name=name)
+
return ret
@@ -323,6 +382,8 @@
ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys()))
+ if expr.get('discriminator') == {}:
+ fdef.write(generate_anon_union_qtypes(expr))
else:
continue
fdecl.write(ret)
@@ -352,7 +413,7 @@
ret += generate_type_cleanup_decl(expr['type'])
fdef.write(generate_type_cleanup(expr['type']) + "\n")
elif expr.has_key('union'):
- ret += generate_union(expr['union'], expr['data'])
+ ret += generate_union(expr)
ret += generate_type_cleanup_decl(expr['union'] + "List")
fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
ret += generate_type_cleanup_decl(expr['union'])
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 6cac05a..597cca4 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -17,34 +17,31 @@
import getopt
import errno
-def generate_visit_struct_body(field_prefix, name, members):
- ret = mcgen('''
-if (!error_is_set(errp)) {
-''')
- push_indent()
+def generate_visit_struct_fields(name, field_prefix, fn_prefix, members):
+ substructs = []
+ ret = ''
+ full_name = name if not fn_prefix else "%s_%s" % (name, fn_prefix)
- if len(field_prefix):
- field_prefix = field_prefix + "."
- ret += mcgen('''
-Error **errp = &err; /* from outer scope */
-Error *err = NULL;
-visit_start_struct(m, NULL, "", "%(name)s", 0, &err);
-''',
- name=name)
- else:
- ret += mcgen('''
-Error *err = NULL;
-visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
-''',
- name=name)
+ for argname, argentry, optional, structured in parse_args(members):
+ if structured:
+ if not fn_prefix:
+ nested_fn_prefix = argname
+ else:
+ nested_fn_prefix = "%s_%s" % (fn_prefix, argname)
+
+ nested_field_prefix = "%s%s." % (field_prefix, argname)
+ ret += generate_visit_struct_fields(name, nested_field_prefix,
+ nested_fn_prefix, argentry)
ret += mcgen('''
-if (!err) {
- if (!obj || *obj) {
-''')
+static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error **errp)
+{
+ Error *err = NULL;
+''',
+ name=name, full_name=full_name)
push_indent()
- push_indent()
+
for argname, argentry, optional, structured in parse_args(members):
if optional:
ret += mcgen('''
@@ -56,7 +53,7 @@
push_indent()
if structured:
- ret += generate_visit_struct_body(field_prefix + argname, argname, argentry)
+ ret += generate_visit_struct_body(full_name, argname, argentry)
else:
ret += mcgen('''
visit_type_%(type)s(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", &err);
@@ -76,11 +73,43 @@
ret += mcgen('''
error_propagate(errp, err);
- err = NULL;
}
''')
+ return ret
- pop_indent()
+
+def generate_visit_struct_body(field_prefix, name, members):
+ ret = mcgen('''
+if (!error_is_set(errp)) {
+''')
+ push_indent()
+
+ full_name = name if not field_prefix else "%s_%s" % (field_prefix, name)
+
+ if len(field_prefix):
+ ret += mcgen('''
+Error **errp = &err; /* from outer scope */
+Error *err = NULL;
+visit_start_struct(m, NULL, "", "%(name)s", 0, &err);
+''',
+ name=name)
+ else:
+ ret += mcgen('''
+Error *err = NULL;
+visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
+''',
+ name=name)
+
+ ret += mcgen('''
+if (!err) {
+ if (!obj || *obj) {
+ visit_type_%(name)s_fields(m, obj, &err);
+ error_propagate(errp, err);
+ err = NULL;
+ }
+''',
+ name=full_name)
+
pop_indent()
ret += mcgen('''
/* Always call end_struct if start_struct succeeded. */
@@ -92,7 +121,9 @@
return ret
def generate_visit_struct(name, members):
- ret = mcgen('''
+ ret = generate_visit_struct_fields(name, "", "", members)
+
+ ret += mcgen('''
void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
{
@@ -145,9 +176,70 @@
''',
name=name)
-def generate_visit_union(name, members):
+def generate_visit_anon_union(name, members):
+ ret = mcgen('''
+
+void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
+{
+ Error *err = NULL;
+
+ if (!error_is_set(errp)) {
+ visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err);
+ visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err);
+ switch ((*obj)->kind) {
+''',
+ name=name)
+
+ for key in members:
+ assert (members[key] in builtin_types
+ or find_struct(members[key])
+ or find_union(members[key])), "Invalid anonymous union member"
+
+ ret += mcgen('''
+ case %(abbrev)s_KIND_%(enum)s:
+ visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err);
+ break;
+''',
+ abbrev = de_camel_case(name).upper(),
+ enum = c_fun(de_camel_case(key),False).upper(),
+ c_type = type_name(members[key]),
+ c_name = c_fun(key))
+
+ ret += mcgen('''
+ default:
+ abort();
+ }
+ error_propagate(errp, err);
+ err = NULL;
+ visit_end_implicit_struct(m, &err);
+ }
+}
+''')
+
+ return ret
+
+
+def generate_visit_union(expr):
+
+ name = expr['union']
+ members = expr['data']
+
+ base = expr.get('base')
+ discriminator = expr.get('discriminator')
+
+ if discriminator == {}:
+ assert not base
+ return generate_visit_anon_union(name, members)
+
ret = generate_visit_enum('%sKind' % name, members.keys())
+ if base:
+ base_fields = find_struct(base)['data']
+ if discriminator:
+ base_fields = base_fields.copy()
+ del base_fields[discriminator]
+ ret += generate_visit_struct_fields(name, "", "", base_fields)
+
ret += mcgen('''
void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
@@ -158,18 +250,43 @@
visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
if (!err) {
if (obj && *obj) {
- visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err);
- if (!err) {
- switch ((*obj)->kind) {
''',
name=name)
+
push_indent()
push_indent()
+ push_indent()
+
+ if base:
+ ret += mcgen('''
+ visit_type_%(name)s_fields(m, obj, &err);
+''',
+ name=name)
+
+ pop_indent()
+ ret += mcgen('''
+ visit_type_%(name)sKind(m, &(*obj)->kind, "%(type)s", &err);
+ if (!err) {
+ switch ((*obj)->kind) {
+''',
+ name=name, type="type" if not discriminator else discriminator)
+
for key in members:
+ if not discriminator:
+ fmt = 'visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);'
+ else:
+ fmt = '''visit_start_implicit_struct(m, (void**) &(*obj)->%(c_name)s, sizeof(%(c_type)s), &err);
+ if (!err) {
+ visit_type_%(c_type)s_fields(m, &(*obj)->%(c_name)s, &err);
+ error_propagate(errp, err);
+ err = NULL;
+ visit_end_implicit_struct(m, &err);
+ }'''
+
ret += mcgen('''
case %(abbrev)s_KIND_%(enum)s:
- visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);
+ ''' + fmt + '''
break;
''',
abbrev = de_camel_case(name).upper(),
@@ -362,7 +479,7 @@
ret = generate_declaration(expr['type'], expr['data'])
fdecl.write(ret)
elif expr.has_key('union'):
- ret = generate_visit_union(expr['union'], expr['data'])
+ ret = generate_visit_union(expr)
ret += generate_visit_list(expr['union'], expr['data'])
fdef.write(ret)
diff --git a/scripts/qapi.py b/scripts/qapi.py
index baf1321..1069310 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -2,14 +2,17 @@
# QAPI helper library
#
# Copyright IBM, Corp. 2011
+# Copyright (c) 2013 Red Hat Inc.
#
# Authors:
# Anthony Liguori <aliguori@us.ibm.com>
+# Markus Armbruster <armbru@redhat.com>
#
# This work is licensed under the terms of the GNU GPLv2.
# See the COPYING.LIB file in the top-level directory.
from ordereddict import OrderedDict
+import sys
builtin_types = [
'str', 'int', 'number', 'bool',
@@ -17,98 +20,162 @@
'uint8', 'uint16', 'uint32', 'uint64'
]
-def tokenize(data):
- while len(data):
- ch = data[0]
- data = data[1:]
- if ch in ['{', '}', ':', ',', '[', ']']:
- yield ch
- elif ch in ' \n':
- None
- elif ch == "'":
- string = ''
- esc = False
- while True:
- if (data == ''):
- raise Exception("Mismatched quotes")
- ch = data[0]
- data = data[1:]
- if esc:
- string += ch
- esc = False
- elif ch == "\\":
- esc = True
- elif ch == "'":
- break
- else:
- string += ch
- yield string
+builtin_type_qtypes = {
+ 'str': 'QTYPE_QSTRING',
+ 'int': 'QTYPE_QINT',
+ 'number': 'QTYPE_QFLOAT',
+ 'bool': 'QTYPE_QBOOL',
+ 'int8': 'QTYPE_QINT',
+ 'int16': 'QTYPE_QINT',
+ 'int32': 'QTYPE_QINT',
+ 'int64': 'QTYPE_QINT',
+ 'uint8': 'QTYPE_QINT',
+ 'uint16': 'QTYPE_QINT',
+ 'uint32': 'QTYPE_QINT',
+ 'uint64': 'QTYPE_QINT',
+}
-def parse(tokens):
- if tokens[0] == '{':
- ret = OrderedDict()
- tokens = tokens[1:]
- while tokens[0] != '}':
- key = tokens[0]
- tokens = tokens[1:]
+class QAPISchemaError(Exception):
+ def __init__(self, schema, msg):
+ self.fp = schema.fp
+ self.msg = msg
+ self.line = self.col = 1
+ for ch in schema.src[0:schema.pos]:
+ if ch == '\n':
+ self.line += 1
+ self.col = 1
+ elif ch == '\t':
+ self.col = (self.col + 7) % 8 + 1
+ else:
+ self.col += 1
- tokens = tokens[1:] # :
+ def __str__(self):
+ return "%s:%s:%s: %s" % (self.fp.name, self.line, self.col, self.msg)
- value, tokens = parse(tokens)
+class QAPISchema:
- if tokens[0] == ',':
- tokens = tokens[1:]
+ def __init__(self, fp):
+ self.fp = fp
+ self.src = fp.read()
+ if self.src == '' or self.src[-1] != '\n':
+ self.src += '\n'
+ self.cursor = 0
+ self.exprs = []
+ self.accept()
- ret[key] = value
- tokens = tokens[1:]
- return ret, tokens
- elif tokens[0] == '[':
- ret = []
- tokens = tokens[1:]
- while tokens[0] != ']':
- value, tokens = parse(tokens)
- if tokens[0] == ',':
- tokens = tokens[1:]
- ret.append(value)
- tokens = tokens[1:]
- return ret, tokens
- else:
- return tokens[0], tokens[1:]
+ while self.tok != None:
+ self.exprs.append(self.get_expr(False))
-def evaluate(string):
- return parse(map(lambda x: x, tokenize(string)))[0]
+ def accept(self):
+ while True:
+ self.tok = self.src[self.cursor]
+ self.pos = self.cursor
+ self.cursor += 1
+ self.val = None
-def get_expr(fp):
- expr = ''
+ if self.tok == '#':
+ self.cursor = self.src.find('\n', self.cursor)
+ elif self.tok in ['{', '}', ':', ',', '[', ']']:
+ return
+ elif self.tok == "'":
+ string = ''
+ esc = False
+ while True:
+ ch = self.src[self.cursor]
+ self.cursor += 1
+ if ch == '\n':
+ raise QAPISchemaError(self,
+ 'Missing terminating "\'"')
+ if esc:
+ string += ch
+ esc = False
+ elif ch == "\\":
+ esc = True
+ elif ch == "'":
+ self.val = string
+ return
+ else:
+ string += ch
+ elif self.tok == '\n':
+ if self.cursor == len(self.src):
+ self.tok = None
+ return
+ elif not self.tok.isspace():
+ raise QAPISchemaError(self, 'Stray "%s"' % self.tok)
- for line in fp:
- if line.startswith('#') or line == '\n':
- continue
+ def get_members(self):
+ expr = OrderedDict()
+ if self.tok == '}':
+ self.accept()
+ return expr
+ if self.tok != "'":
+ raise QAPISchemaError(self, 'Expected string or "}"')
+ while True:
+ key = self.val
+ self.accept()
+ if self.tok != ':':
+ raise QAPISchemaError(self, 'Expected ":"')
+ self.accept()
+ expr[key] = self.get_expr(True)
+ if self.tok == '}':
+ self.accept()
+ return expr
+ if self.tok != ',':
+ raise QAPISchemaError(self, 'Expected "," or "}"')
+ self.accept()
+ if self.tok != "'":
+ raise QAPISchemaError(self, 'Expected string')
- if line.startswith(' '):
- expr += line
- elif expr:
- yield expr
- expr = line
+ def get_values(self):
+ expr = []
+ if self.tok == ']':
+ self.accept()
+ return expr
+ if not self.tok in [ '{', '[', "'" ]:
+ raise QAPISchemaError(self, 'Expected "{", "[", "]" or string')
+ while True:
+ expr.append(self.get_expr(True))
+ if self.tok == ']':
+ self.accept()
+ return expr
+ if self.tok != ',':
+ raise QAPISchemaError(self, 'Expected "," or "]"')
+ self.accept()
+
+ def get_expr(self, nested):
+ if self.tok != '{' and not nested:
+ raise QAPISchemaError(self, 'Expected "{"')
+ if self.tok == '{':
+ self.accept()
+ expr = self.get_members()
+ elif self.tok == '[':
+ self.accept()
+ expr = self.get_values()
+ elif self.tok == "'":
+ expr = self.val
+ self.accept()
else:
- expr += line
-
- if expr:
- yield expr
+ raise QAPISchemaError(self, 'Expected "{", "[" or string')
+ return expr
def parse_schema(fp):
+ try:
+ schema = QAPISchema(fp)
+ except QAPISchemaError, e:
+ print >>sys.stderr, e
+ exit(1)
+
exprs = []
- for expr in get_expr(fp):
- expr_eval = evaluate(expr)
-
- if expr_eval.has_key('enum'):
- add_enum(expr_eval['enum'])
- elif expr_eval.has_key('union'):
- add_enum('%sKind' % expr_eval['union'])
- elif expr_eval.has_key('type'):
- add_struct(expr_eval)
- exprs.append(expr_eval)
+ for expr in schema.exprs:
+ if expr.has_key('enum'):
+ add_enum(expr['enum'])
+ elif expr.has_key('union'):
+ add_union(expr)
+ add_enum('%sKind' % expr['union'])
+ elif expr.has_key('type'):
+ add_struct(expr)
+ exprs.append(expr)
return exprs
@@ -188,6 +255,7 @@
enum_types = []
struct_types = []
+union_types = []
def add_struct(definition):
global struct_types
@@ -200,6 +268,17 @@
return struct
return None
+def add_union(definition):
+ global union_types
+ union_types.append(definition)
+
+def find_union(name):
+ global union_types
+ for union in union_types:
+ if union['union'] == name:
+ return union
+ return None
+
def add_enum(name):
global enum_types
enum_types.append(name)
diff --git a/scripts/switch-timer-api b/scripts/switch-timer-api
new file mode 100755
index 0000000..a369a08
--- /dev/null
+++ b/scripts/switch-timer-api
@@ -0,0 +1,178 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Getopt::Long;
+use FindBin;
+
+my @legacy = qw(qemu_clock_ptr qemu_get_clock_ns qemu_get_clock_ms qemu_register_clock_reset_notifier qemu_unregister_clock_reset_notifier qemu_new_timer qemu_free_timer qemu_del_timer qemu_mod_timer_ns qemu_mod_timer qemu_run_timers qemu_new_timer_ns qemu_new_timer_us qemu_new_timer_ms);
+my $legacyre = '\b('.join('|', @legacy).')\b';
+my $option_git;
+my $option_dryrun;
+my $option_quiet;
+my $option_rtc;
+my $suffix=".tmp.$$";
+my @files;
+my $getfiles = 'git grep -l -E \'\b((host|rt|vm|rtc)_clock\b|qemu_\w*timer)\' | egrep \'\.[ch]$\' | egrep -v \'qemu-timer\.c$|include/qemu/timer\.h$\'';
+
+sub Syntax
+{
+ print STDERR <<STOP;
+Usage: $FindBin::Script [options] FILE ...
+
+Translate each FILE to the new Qemu timer API. If no files
+are passed, a reasonable guess is taken.
+
+Options:
+ -q, --quiet Do not show warnings etc
+ -d, --dry-run Do a dry run
+ -g, --git Generate a git commit for each change
+ -r, --rtc Only fix up rtc usage
+ -h, --help Print this message
+
+STOP
+return;
+}
+
+sub ParseOptions
+{
+ if (!GetOptions (
+ "dry-run|d" => \$option_dryrun,
+ "git|g" => \$option_git,
+ "quiet|q" => \$option_quiet,
+ "rtc|r" => \$option_rtc,
+ "help|h" => sub { Syntax(); exit(0); }
+ ))
+ {
+ Syntax();
+ die "Bad options";
+ }
+
+ if ($#ARGV >=0)
+ {
+ @files = @ARGV;
+ }
+ else
+ {
+ @files = split(/\s+/, `$getfiles`);
+ }
+
+ foreach my $file (@files)
+ {
+ die "Cannot find $file" unless (-f $file && -r $file);
+ }
+}
+
+sub DoWarn
+{
+ my $text = shift @_;
+ my $line = shift @_;
+ return if ($option_quiet);
+ chomp ($line);
+ print STDERR "$text\n";
+ print STDERR "$line\n\n";
+}
+
+sub Process
+{
+ my $ifn = shift @_;
+ my $ofn = $ifn.$suffix;
+
+ my $intext;
+ my $outtext;
+ my $linenum = 0;
+
+ open my $input, "<", $ifn || die "Cannot open $ifn for read: $!";
+
+ while (<$input>)
+ {
+ my $line = $_;
+ $intext .= $line;
+ $linenum++;
+
+ # fix the specific uses
+ unless ($option_rtc)
+ {
+ $line =~ s/\bqemu_new_timer(_[num]s)\s*\((vm_|rt_|host_)clock\b/timer_new$1(XXX_$2clock/g;
+ $line =~ s/\bqemu_new_timer\s*\((vm_|rt_|host_)clock\b/timer_new(XXX_$1clock/g;
+ $line =~ s/\bqemu_get_clock(_[num]s)\s*\((vm_|rt_|host_)clock\b/qemu_clock_get$1(XXX_$2clock/g;
+ }
+
+ # rtc is different
+ $line =~ s/\bqemu_new_timer(_[num]s)\s*\(rtc_clock\b/timer_new$1(rtc_clock/g;
+ $line =~ s/\bqemu_new_timer\s*\(rtc_clock\b/timer_new(rtc_clock/g;
+ $line =~ s/\bqemu_get_clock(_[num]s)\s*\(rtc_clock\b/qemu_clock_get$1(rtc_clock/g;
+ $line =~ s/\bqemu_register_clock_reset_notifier\s*\(rtc_clock\b/qemu_register_clock_reset_notifier(qemu_clock_ptr(rtc_clock)/g;
+
+ unless ($option_rtc)
+ {
+ # fix up comments
+ $line =~ s/\b(vm_|rt_|host_)clock\b/XXX_$1clock/g if ($line =~ m,^[/ ]+\*,);
+
+ # spurious fprintf error reporting
+ $line =~ s/: qemu_new_timer_ns failed/: timer_new_ns failed/g;
+
+ # these have just changed name
+ $line =~ s/\bqemu_mod_timer\b/timer_mod/g;
+ $line =~ s/\bqemu_mod_timer_(ns|us|ms)\b/timer_mod_$1/g;
+ $line =~ s/\bqemu_free_timer\b/timer_free/g;
+ $line =~ s/\bqemu_del_timer\b/timer_del/g;
+ }
+
+ # fix up rtc_clock
+ $line =~ s/QEMUClock \*rtc_clock;/QEMUClockType rtc_clock;/g;
+ $line =~ s/\brtc_clock = (vm_|rt_|host_)clock\b/rtc_clock = XXX_$1clock/g;
+
+ unless ($option_rtc)
+ {
+ # replace any more general uses
+ $line =~ s/\b(vm_|rt_|host_)clock\b/qemu_clock_ptr(XXX_$1clock)/g;
+ }
+
+ # fix up the place holders
+ $line =~ s/\bXXX_vm_clock\b/QEMU_CLOCK_VIRTUAL/g;
+ $line =~ s/\bXXX_rt_clock\b/QEMU_CLOCK_REALTIME/g;
+ $line =~ s/\bXXX_host_clock\b/QEMU_CLOCK_HOST/g;
+
+ unless ($option_rtc)
+ {
+ DoWarn("$ifn:$linenum WARNING: timer $1 not fixed up", $line) if ($line =~ /\b((vm_|rt_|host_)clock)\b/);
+ DoWarn("$ifn:$linenum WARNING: function $1 not fixed up", $line) if ($line =~ /\b(qemu_new_timer\w+)\b/);
+ DoWarn("$ifn:$linenum WARNING: legacy function $1 remains", $line) if ($line =~ /$legacyre/o);
+ }
+
+ $outtext .= $line;
+ }
+
+ close $input;
+
+ if ($intext ne $outtext)
+ {
+ print STDERR "Patching $ifn\n" unless ($option_quiet);
+ unless ($option_dryrun)
+ {
+ open my $output, ">", $ofn || die "Cannot open $ofn for write: $!";
+ print $output $outtext;
+ close $output;
+ rename ($ofn, $ifn) || die "Cannot rename temp file to $ifn: $!";
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub DoCommit
+{
+ my $file = shift @_;
+ open (my $git, "| git commit -F - $file") || die "Cannot run git commit on $file: $!";
+ print $git "timers api: use new timer api in $file\n\nConvert $file to use new timer API.\nThis is an automated commit made by scripts/switch-timer-api\n";
+ close ($git);
+}
+
+ParseOptions;
+
+foreach my $file (@files)
+{
+ my $changed = Process ($file);
+ DoCommit($file) if ($changed && $option_git);
+}
diff --git a/slirp/if.c b/slirp/if.c
index dcd5faf..87ca8a5 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -154,7 +154,7 @@
*/
void if_start(Slirp *slirp)
{
- uint64_t now = qemu_get_clock_ns(rt_clock);
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
bool from_batchq, next_from_batchq;
struct mbuf *ifm, *ifm_next, *ifqt;
diff --git a/slirp/misc.c b/slirp/misc.c
index 0bcc481..c0d4899 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -9,6 +9,7 @@
#include <libslirp.h>
#include "monitor/monitor.h"
+#include "qemu/main-loop.h"
#ifdef DEBUG
int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 80b28ea..5c3dabb 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -448,7 +448,7 @@
return;
}
- curtime = qemu_get_clock_ms(rt_clock);
+ curtime = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
/*
@@ -787,7 +787,7 @@
ifm->arp_requested = true;
/* Expire request and drop outgoing packet after 1 second */
- ifm->expiration_date = qemu_get_clock_ns(rt_clock) + 1000000000ULL;
+ ifm->expiration_date = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 1000000000ULL;
}
return 0;
} else {
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 9b701b4..f306cba 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -7,6 +7,7 @@
stub-obj-y += fdset-find-fd.o
stub-obj-y += fdset-get-fd.o
stub-obj-y += fdset-remove-fd.o
+stub-obj-y += gdbstub.o
stub-obj-y += get-fd.o
stub-obj-y += get-vm-name.o
stub-obj-y += iothread-lock.o
diff --git a/stubs/clock-warp.c b/stubs/clock-warp.c
index b64c462..5565118 100644
--- a/stubs/clock-warp.c
+++ b/stubs/clock-warp.c
@@ -1,7 +1,7 @@
#include "qemu-common.h"
#include "qemu/timer.h"
-void qemu_clock_warp(QEMUClock *clock)
+void qemu_clock_warp(QEMUClockType type)
{
}
diff --git a/stubs/dump.c b/stubs/dump.c
index 43c9a3f..370cd96 100644
--- a/stubs/dump.c
+++ b/stubs/dump.c
@@ -16,7 +16,8 @@
#include "qapi/qmp/qerror.h"
#include "qmp-commands.h"
-int cpu_get_dump_info(ArchDumpInfo *info)
+int cpu_get_dump_info(ArchDumpInfo *info,
+ const struct GuestPhysBlockList *guest_phys_blocks)
{
return -1;
}
diff --git a/stubs/gdbstub.c b/stubs/gdbstub.c
new file mode 100644
index 0000000..c1dbfe7
--- /dev/null
+++ b/stubs/gdbstub.c
@@ -0,0 +1,5 @@
+#include "qemu-common.h"
+
+const char *const xml_builtin[][2] = {
+ { NULL, NULL }
+};
diff --git a/target-alpha/Makefile.objs b/target-alpha/Makefile.objs
index 590304c..b96c5da 100644
--- a/target-alpha/Makefile.objs
+++ b/target-alpha/Makefile.objs
@@ -1,3 +1,4 @@
obj-$(CONFIG_SOFTMMU) += machine.o
obj-y += translate.o helper.o cpu.o
obj-y += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
+obj-y += gdbstub.o
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
index b2eeba3..2ebc9bc 100644
--- a/target-alpha/cpu-qom.h
+++ b/target-alpha/cpu-qom.h
@@ -82,5 +82,7 @@
void alpha_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int flags);
hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int alpha_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#endif
diff --git a/target-alpha/cpu.c b/target-alpha/cpu.c
index c8c8c2c..cfad2ea 100644
--- a/target-alpha/cpu.c
+++ b/target-alpha/cpu.c
@@ -33,8 +33,11 @@
static void alpha_cpu_realizefn(DeviceState *dev, Error **errp)
{
+ CPUState *cs = CPU(dev);
AlphaCPUClass *acc = ALPHA_CPU_GET_CLASS(dev);
+ qemu_init_vcpu(cs);
+
acc->parent_realize(dev, errp);
}
@@ -271,11 +274,14 @@
cc->do_interrupt = alpha_cpu_do_interrupt;
cc->dump_state = alpha_cpu_dump_state;
cc->set_pc = alpha_cpu_set_pc;
+ cc->gdb_read_register = alpha_cpu_gdb_read_register;
+ cc->gdb_write_register = alpha_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->do_unassigned_access = alpha_cpu_unassigned_access;
cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_alpha_cpu;
#endif
+ cc->gdb_num_core_regs = 67;
}
static const TypeInfo alpha_cpu_type_info = {
diff --git a/target-alpha/gdbstub.c b/target-alpha/gdbstub.c
new file mode 100644
index 0000000..980f140
--- /dev/null
+++ b/target-alpha/gdbstub.c
@@ -0,0 +1,93 @@
+/*
+ * Alpha gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+int alpha_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ AlphaCPU *cpu = ALPHA_CPU(cs);
+ CPUAlphaState *env = &cpu->env;
+ uint64_t val;
+ CPU_DoubleU d;
+
+ switch (n) {
+ case 0 ... 30:
+ val = env->ir[n];
+ break;
+ case 32 ... 62:
+ d.d = env->fir[n - 32];
+ val = d.ll;
+ break;
+ case 63:
+ val = cpu_alpha_load_fpcr(env);
+ break;
+ case 64:
+ val = env->pc;
+ break;
+ case 66:
+ val = env->unique;
+ break;
+ case 31:
+ case 65:
+ /* 31 really is the zero register; 65 is unassigned in the
+ gdb protocol, but is still required to occupy 8 bytes. */
+ val = 0;
+ break;
+ default:
+ return 0;
+ }
+ return gdb_get_regl(mem_buf, val);
+}
+
+int alpha_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ AlphaCPU *cpu = ALPHA_CPU(cs);
+ CPUAlphaState *env = &cpu->env;
+ target_ulong tmp = ldtul_p(mem_buf);
+ CPU_DoubleU d;
+
+ switch (n) {
+ case 0 ... 30:
+ env->ir[n] = tmp;
+ break;
+ case 32 ... 62:
+ d.ll = tmp;
+ env->fir[n - 32] = d.d;
+ break;
+ case 63:
+ cpu_alpha_store_fpcr(env, tmp);
+ break;
+ case 64:
+ env->pc = tmp;
+ break;
+ case 66:
+ env->unique = tmp;
+ break;
+ case 31:
+ case 65:
+ /* 31 really is the zero register; 65 is unassigned in the
+ gdb protocol, but is still required to occupy 8 bytes. */
+ break;
+ default:
+ return 0;
+ }
+ return 8;
+}
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 0e425cf..732b701 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -99,6 +99,7 @@
#if !defined (CONFIG_USER_ONLY)
DEF_HELPER_2(hw_ret, void, env, i64)
+DEF_HELPER_3(call_pal, void, env, i64, i64)
DEF_HELPER_1(ldl_phys, i64, i64)
DEF_HELPER_1(ldq_phys, i64, i64)
@@ -111,6 +112,7 @@
DEF_HELPER_FLAGS_1(tbia, TCG_CALL_NO_RWG, void, env)
DEF_HELPER_FLAGS_2(tbis, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_1(tb_flush, TCG_CALL_NO_RWG, void, env)
DEF_HELPER_1(halt, void, i64);
diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c
index bd94597..035810c 100644
--- a/target-alpha/sys_helper.c
+++ b/target-alpha/sys_helper.c
@@ -30,9 +30,9 @@
In order to make OS-level time accounting work with the RPCC,
present it with a well-timed clock fixed at 250MHz. */
return (((uint64_t)env->pcc_ofs << 32)
- | (uint32_t)(qemu_get_clock_ns(vm_clock) >> 2));
+ | (uint32_t)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 2));
#else
- /* In user-mode, vm_clock doesn't exist. Just pass through the host cpu
+ /* In user-mode, QEMU_CLOCK_VIRTUAL doesn't exist. Just pass through the host cpu
clock ticks. Also, don't bother taking PCC_OFS into account. */
return (uint32_t)cpu_get_real_ticks();
#endif
@@ -51,6 +51,17 @@
}
}
+void helper_call_pal(CPUAlphaState *env, uint64_t pc, uint64_t entry_ofs)
+{
+ int pal_mode = env->pal_mode;
+ env->exc_addr = pc | pal_mode;
+ env->pc = env->palbr + entry_ofs;
+ if (!pal_mode) {
+ env->pal_mode = 1;
+ swap_shadow_regs(env);
+ }
+}
+
void helper_tbia(CPUAlphaState *env)
{
tlb_flush(env, 1);
@@ -61,6 +72,11 @@
tlb_flush_page(env, p);
}
+void helper_tb_flush(CPUAlphaState *env)
+{
+ tb_flush(env);
+}
+
void helper_halt(uint64_t restart)
{
if (restart) {
@@ -72,12 +88,12 @@
uint64_t helper_get_vmtime(void)
{
- return qemu_get_clock_ns(vm_clock);
+ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
uint64_t helper_get_walltime(void)
{
- return qemu_get_clock_ns(rtc_clock);
+ return qemu_clock_get_ns(rtc_clock);
}
void helper_set_alarm(CPUAlphaState *env, uint64_t expire)
@@ -86,9 +102,10 @@
if (expire) {
env->alarm_expire = expire;
- qemu_mod_timer(cpu->alarm_timer, expire);
+ timer_mod(cpu->alarm_timer, expire);
} else {
- qemu_del_timer(cpu->alarm_timer);
+ timer_del(cpu->alarm_timer);
}
}
+
#endif /* CONFIG_USER_ONLY */
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 0efd559..309dea6 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -379,13 +379,26 @@
#endif
}
-static int use_goto_tb(DisasContext *ctx, uint64_t dest)
+static bool in_superpage(DisasContext *ctx, int64_t addr)
{
- /* Check for the dest on the same page as the start of the TB. We
- also want to suppress goto_tb in the case of single-steping and IO. */
- return (((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0
- && !ctx->singlestep_enabled
- && !(ctx->tb->cflags & CF_LAST_IO));
+ return ((ctx->tb->flags & TB_FLAGS_USER_MODE) == 0
+ && addr < 0
+ && ((addr >> 41) & 3) == 2
+ && addr >> TARGET_VIRT_ADDR_SPACE_BITS == addr >> 63);
+}
+
+static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
+{
+ /* Suppress goto_tb in the case of single-steping and IO. */
+ if (ctx->singlestep_enabled || (ctx->tb->cflags & CF_LAST_IO)) {
+ return false;
+ }
+ /* If the destination is in the superpage, the page perms can't change. */
+ if (in_superpage(ctx, dest)) {
+ return true;
+ }
+ /* Check for the dest on the same page as the start of the TB. */
+ return ((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0;
}
static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
@@ -1521,7 +1534,8 @@
tcg_gen_mov_i64(cpu_unique, cpu_ir[IR_A0]);
break;
default:
- return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0xbf);
+ palcode &= 0xbf;
+ goto do_call_pal;
}
return NO_EXIT;
}
@@ -1586,13 +1600,42 @@
break;
default:
- return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0x3f);
+ palcode &= 0x3f;
+ goto do_call_pal;
}
return NO_EXIT;
}
#endif
-
return gen_invalid(ctx);
+
+ do_call_pal:
+#ifdef CONFIG_USER_ONLY
+ return gen_excp(ctx, EXCP_CALL_PAL, palcode);
+#else
+ {
+ TCGv pc = tcg_const_i64(ctx->pc);
+ TCGv entry = tcg_const_i64(palcode & 0x80
+ ? 0x2000 + (palcode - 0x80) * 64
+ : 0x1000 + palcode * 64);
+
+ gen_helper_call_pal(cpu_env, pc, entry);
+
+ tcg_temp_free(entry);
+ tcg_temp_free(pc);
+
+ /* Since the destination is running in PALmode, we don't really
+ need the page permissions check. We'll see the existance of
+ the page when we create the TB, and we'll flush all TBs if
+ we change the PAL base register. */
+ if (!ctx->singlestep_enabled && !(ctx->tb->cflags & CF_LAST_IO)) {
+ tcg_gen_goto_tb(0);
+ tcg_gen_exit_tb((tcg_target_long)ctx->tb);
+ return EXIT_GOTO_TB;
+ }
+
+ return EXIT_PC_UPDATED;
+ }
+#endif
}
#ifndef CONFIG_USER_ONLY
@@ -1708,6 +1751,15 @@
gen_helper_set_alarm(cpu_env, tmp);
break;
+ case 7:
+ /* PALBR */
+ tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUAlphaState, palbr));
+ /* Changing the PAL base register implies un-chaining all of the TBs
+ that ended with a CALL_PAL. Since the base register usually only
+ changes during boot, flushing everything works well. */
+ gen_helper_tb_flush(cpu_env);
+ return EXIT_PC_STALE;
+
default:
/* The basic registers are data only, and unknown registers
are read-zero, write-ignore. */
@@ -3392,6 +3444,7 @@
CPUAlphaState *env = &cpu->env;
DisasContext ctx, *ctxp = &ctx;
target_ulong pc_start;
+ target_ulong pc_mask;
uint32_t insn;
uint16_t *gen_opc_end;
CPUBreakpoint *bp;
@@ -3421,8 +3474,15 @@
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+
+ if (in_superpage(&ctx, pc_start)) {
+ pc_mask = (1ULL << 41) - 1;
+ } else {
+ pc_mask = ~TARGET_PAGE_MASK;
+ }
gen_tb_start();
do {
@@ -3460,7 +3520,7 @@
/* If we reach a page boundary, are single stepping,
or exhaust instruction count, stop generation. */
if (ret == NO_EXIT
- && ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
+ && ((ctx.pc & pc_mask) == 0
|| tcg_ctx.gen_opc_ptr >= gen_opc_end
|| num_insns >= max_insns
|| singlestep
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index 4a6e52e..2d9f77f 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -4,3 +4,4 @@
obj-$(CONFIG_NO_KVM) += kvm-stub.o
obj-y += translate.o op_helper.o helper.o cpu.o
obj-y += neon_helper.o iwmmxt_helper.o
+obj-y += gdbstub.o
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 02162c9..9f47bae 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -86,6 +86,11 @@
uint64_t *cpreg_vmstate_values;
int32_t cpreg_vmstate_array_len;
+ /* Timers used by the generic (architected) timer */
+ QEMUTimer *gt_timer[NUM_GTIMERS];
+ /* GPIO outputs for generic timer */
+ qemu_irq gt_timer_outputs[NUM_GTIMERS];
+
/* The instance init functions for implementation-specific subclasses
* set these fields to specify the implementation-dependent values of
* various constant registers and reset values of non-constant
@@ -149,4 +154,11 @@
hwaddr arm_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int arm_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int arm_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
+/* Callback functions for the generic timer's timers. */
+void arm_gt_ptimer_cb(void *opaque);
+void arm_gt_vtimer_cb(void *opaque);
+
#endif
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index d3906a4..b2556c6 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -23,7 +23,9 @@
#if !defined(CONFIG_USER_ONLY)
#include "hw/loader.h"
#endif
+#include "hw/arm/arm.h"
#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
{
@@ -129,6 +131,55 @@
tb_flush(env);
}
+#ifndef CONFIG_USER_ONLY
+static void arm_cpu_set_irq(void *opaque, int irq, int level)
+{
+ ARMCPU *cpu = opaque;
+ CPUState *cs = CPU(cpu);
+
+ switch (irq) {
+ case ARM_CPU_IRQ:
+ if (level) {
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+ }
+ break;
+ case ARM_CPU_FIQ:
+ if (level) {
+ cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
+ }
+ break;
+ default:
+ hw_error("arm_cpu_set_irq: Bad interrupt line %d\n", irq);
+ }
+}
+
+static void arm_cpu_kvm_set_irq(void *opaque, int irq, int level)
+{
+#ifdef CONFIG_KVM
+ ARMCPU *cpu = opaque;
+ CPUState *cs = CPU(cpu);
+ int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
+
+ switch (irq) {
+ case ARM_CPU_IRQ:
+ kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
+ break;
+ case ARM_CPU_FIQ:
+ kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
+ break;
+ default:
+ hw_error("arm_cpu_kvm_set_irq: Bad interrupt line %d\n", irq);
+ }
+ kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
+ kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
+#endif
+}
+#endif
+
static inline void set_feature(CPUARMState *env, int feature)
{
env->features |= 1ULL << feature;
@@ -145,6 +196,22 @@
cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
g_free, g_free);
+#ifndef CONFIG_USER_ONLY
+ /* Our inbound IRQ and FIQ lines */
+ if (kvm_enabled()) {
+ qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 2);
+ } else {
+ qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 2);
+ }
+
+ cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
+ arm_gt_ptimer_cb, cpu);
+ cpu->gt_timer[GTIMER_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE,
+ arm_gt_vtimer_cb, cpu);
+ qdev_init_gpio_out(DEVICE(cpu), cpu->gt_timer_outputs,
+ ARRAY_SIZE(cpu->gt_timer_outputs));
+#endif
+
if (tcg_enabled() && !inited) {
inited = true;
arm_translate_init();
@@ -159,6 +226,7 @@
static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
{
+ CPUState *cs = CPU(dev);
ARMCPU *cpu = ARM_CPU(dev);
ARMCPUClass *acc = ARM_CPU_GET_CLASS(dev);
CPUARMState *env = &cpu->env;
@@ -214,7 +282,8 @@
init_cpreg_list(cpu);
- cpu_reset(CPU(cpu));
+ cpu_reset(cs);
+ qemu_init_vcpu(cs);
acc->parent_realize(dev, errp);
}
@@ -824,10 +893,14 @@
cc->do_interrupt = arm_cpu_do_interrupt;
cc->dump_state = arm_cpu_dump_state;
cc->set_pc = arm_cpu_set_pc;
+ cc->gdb_read_register = arm_cpu_gdb_read_register;
+ cc->gdb_write_register = arm_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_arm_cpu;
#endif
+ cc->gdb_num_core_regs = 26;
+ cc->gdb_core_xml_file = "arm-core.xml";
}
static void cpu_register(const ARMCPUInfo *info)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index b2dc494..f2abdf3 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -58,6 +58,9 @@
/* ARM-specific interrupt pending bits. */
#define CPU_INTERRUPT_FIQ CPU_INTERRUPT_TGT_EXT_1
+/* Meanings of the ARMCPU object's two inbound GPIO lines */
+#define ARM_CPU_IRQ 0
+#define ARM_CPU_FIQ 1
typedef void ARMWriteCPFunc(void *opaque, int cp_info,
int srcreg, int operand, uint32_t value);
@@ -76,6 +79,21 @@
s<2n+1> maps to the most significant half of d<n>
*/
+/* CPU state for each instance of a generic timer (in cp15 c14) */
+typedef struct ARMGenericTimer {
+ uint64_t cval; /* Timer CompareValue register */
+ uint32_t ctl; /* Timer Control register */
+} ARMGenericTimer;
+
+#define GTIMER_PHYS 0
+#define GTIMER_VIRT 1
+#define NUM_GTIMERS 2
+
+/* Scale factor for generic timers, ie number of ns per tick.
+ * This gives a 62.5MHz timer.
+ */
+#define GTIMER_SCALE 16
+
typedef struct CPUARMState {
/* Regs for current mode. */
uint32_t regs[16];
@@ -143,6 +161,9 @@
uint32_t c13_tls1; /* User RW Thread register. */
uint32_t c13_tls2; /* User RO Thread register. */
uint32_t c13_tls3; /* Privileged Thread register. */
+ uint32_t c14_cntfrq; /* Counter Frequency register */
+ uint32_t c14_cntkctl; /* Timer Control register */
+ ARMGenericTimer c14_timer[NUM_GTIMERS];
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
uint32_t c15_ticonfig; /* TI925T configuration byte. */
uint32_t c15_i_max; /* Maximum D-cache dirty line index. */
@@ -469,6 +490,9 @@
* old must have the OVERRIDE bit set.
* NO_MIGRATE indicates that this register should be ignored for migration;
* (eg because any state is accessed via some other coprocessor register).
+ * IO indicates that this register does I/O and therefore its accesses
+ * need to be surrounded by gen_io_start()/gen_io_end(). In particular,
+ * registers which implement clocks or timers require this.
*/
#define ARM_CP_SPECIAL 1
#define ARM_CP_CONST 2
@@ -476,13 +500,14 @@
#define ARM_CP_SUPPRESS_TB_END 8
#define ARM_CP_OVERRIDE 16
#define ARM_CP_NO_MIGRATE 32
+#define ARM_CP_IO 64
#define ARM_CP_NOP (ARM_CP_SPECIAL | (1 << 8))
#define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
#define ARM_LAST_SPECIAL ARM_CP_WFI
/* Used only as a terminator for ARMCPRegInfo lists */
#define ARM_CP_SENTINEL 0xffff
/* Mask of only the flag bits in a type field */
-#define ARM_CP_FLAG_MASK 0x3f
+#define ARM_CP_FLAG_MASK 0x7f
/* Return true if cptype is a valid type field. This is used to try to
* catch errors where the sentinel has been accidentally left off the end
diff --git a/target-arm/gdbstub.c b/target-arm/gdbstub.c
new file mode 100644
index 0000000..1c34396
--- /dev/null
+++ b/target-arm/gdbstub.c
@@ -0,0 +1,102 @@
+/*
+ * ARM gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+/* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect
+ whatever the target description contains. Due to a historical mishap
+ the FPA registers appear in between core integer regs and the CPSR.
+ We hack round this by giving the FPA regs zero size when talking to a
+ newer gdb. */
+
+int arm_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+
+ if (n < 16) {
+ /* Core integer register. */
+ return gdb_get_reg32(mem_buf, env->regs[n]);
+ }
+ if (n < 24) {
+ /* FPA registers. */
+ if (gdb_has_xml) {
+ return 0;
+ }
+ memset(mem_buf, 0, 12);
+ return 12;
+ }
+ switch (n) {
+ case 24:
+ /* FPA status register. */
+ if (gdb_has_xml) {
+ return 0;
+ }
+ return gdb_get_reg32(mem_buf, 0);
+ case 25:
+ /* CPSR */
+ return gdb_get_reg32(mem_buf, cpsr_read(env));
+ }
+ /* Unknown register. */
+ return 0;
+}
+
+int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+ uint32_t tmp;
+
+ tmp = ldl_p(mem_buf);
+
+ /* Mask out low bit of PC to workaround gdb bugs. This will probably
+ cause problems if we ever implement the Jazelle DBX extensions. */
+ if (n == 15) {
+ tmp &= ~1;
+ }
+
+ if (n < 16) {
+ /* Core integer register. */
+ env->regs[n] = tmp;
+ return 4;
+ }
+ if (n < 24) { /* 16-23 */
+ /* FPA registers (ignored). */
+ if (gdb_has_xml) {
+ return 0;
+ }
+ return 12;
+ }
+ switch (n) {
+ case 24:
+ /* FPA status register (ignored). */
+ if (gdb_has_xml) {
+ return 0;
+ }
+ return 4;
+ case 25:
+ /* CPSR */
+ cpsr_write(env, tmp, 0xffffffff);
+ return 4;
+ }
+ /* Unknown register. */
+ return 0;
+}
diff --git a/target-arm/helper.c b/target-arm/helper.c
index b0c3ca1..e51ef20 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -67,14 +67,22 @@
static int raw_read(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t *value)
{
- *value = CPREG_FIELD32(env, ri);
+ if (ri->type & ARM_CP_64BIT) {
+ *value = CPREG_FIELD64(env, ri);
+ } else {
+ *value = CPREG_FIELD32(env, ri);
+ }
return 0;
}
static int raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
- CPREG_FIELD32(env, ri) = value;
+ if (ri->type & ARM_CP_64BIT) {
+ CPREG_FIELD64(env, ri) = value;
+ } else {
+ CPREG_FIELD32(env, ri) = value;
+ }
return 0;
}
@@ -687,15 +695,261 @@
REGINFO_SENTINEL
};
+#ifndef CONFIG_USER_ONLY
+
+static uint64_t gt_get_countervalue(CPUARMState *env)
+{
+ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE;
+}
+
+static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
+{
+ ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
+
+ if (gt->ctl & 1) {
+ /* Timer enabled: calculate and set current ISTATUS, irq, and
+ * reset timer to when ISTATUS next has to change
+ */
+ uint64_t count = gt_get_countervalue(&cpu->env);
+ /* Note that this must be unsigned 64 bit arithmetic: */
+ int istatus = count >= gt->cval;
+ uint64_t nexttick;
+
+ gt->ctl = deposit32(gt->ctl, 2, 1, istatus);
+ qemu_set_irq(cpu->gt_timer_outputs[timeridx],
+ (istatus && !(gt->ctl & 2)));
+ if (istatus) {
+ /* Next transition is when count rolls back over to zero */
+ nexttick = UINT64_MAX;
+ } else {
+ /* Next transition is when we hit cval */
+ nexttick = gt->cval;
+ }
+ /* Note that the desired next expiry time might be beyond the
+ * signed-64-bit range of a QEMUTimer -- in this case we just
+ * set the timer for as far in the future as possible. When the
+ * timer expires we will reset the timer for any remaining period.
+ */
+ if (nexttick > INT64_MAX / GTIMER_SCALE) {
+ nexttick = INT64_MAX / GTIMER_SCALE;
+ }
+ timer_mod(cpu->gt_timer[timeridx], nexttick);
+ } else {
+ /* Timer disabled: ISTATUS and timer output always clear */
+ gt->ctl &= ~4;
+ qemu_set_irq(cpu->gt_timer_outputs[timeridx], 0);
+ timer_del(cpu->gt_timer[timeridx]);
+ }
+}
+
+static int gt_cntfrq_read(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+ /* Not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero */
+ if (arm_current_pl(env) == 0 && !extract32(env->cp15.c14_cntkctl, 0, 2)) {
+ return EXCP_UDEF;
+ }
+ *value = env->cp15.c14_cntfrq;
+ return 0;
+}
+
+static void gt_cnt_reset(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ ARMCPU *cpu = arm_env_get_cpu(env);
+ int timeridx = ri->opc1 & 1;
+
+ timer_del(cpu->gt_timer[timeridx]);
+}
+
+static int gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+ int timeridx = ri->opc1 & 1;
+
+ if (arm_current_pl(env) == 0 &&
+ !extract32(env->cp15.c14_cntkctl, timeridx, 1)) {
+ return EXCP_UDEF;
+ }
+ *value = gt_get_countervalue(env);
+ return 0;
+}
+
+static int gt_cval_read(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+ int timeridx = ri->opc1 & 1;
+
+ if (arm_current_pl(env) == 0 &&
+ !extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) {
+ return EXCP_UDEF;
+ }
+ *value = env->cp15.c14_timer[timeridx].cval;
+ return 0;
+}
+
+static int gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ int timeridx = ri->opc1 & 1;
+
+ env->cp15.c14_timer[timeridx].cval = value;
+ gt_recalc_timer(arm_env_get_cpu(env), timeridx);
+ return 0;
+}
+static int gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+ int timeridx = ri->crm & 1;
+
+ if (arm_current_pl(env) == 0 &&
+ !extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) {
+ return EXCP_UDEF;
+ }
+ *value = (uint32_t)(env->cp15.c14_timer[timeridx].cval -
+ gt_get_countervalue(env));
+ return 0;
+}
+
+static int gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ int timeridx = ri->crm & 1;
+
+ env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) +
+ + sextract64(value, 0, 32);
+ gt_recalc_timer(arm_env_get_cpu(env), timeridx);
+ return 0;
+}
+
+static int gt_ctl_read(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t *value)
+{
+ int timeridx = ri->crm & 1;
+
+ if (arm_current_pl(env) == 0 &&
+ !extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) {
+ return EXCP_UDEF;
+ }
+ *value = env->cp15.c14_timer[timeridx].ctl;
+ return 0;
+}
+
+static int gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ ARMCPU *cpu = arm_env_get_cpu(env);
+ int timeridx = ri->crm & 1;
+ uint32_t oldval = env->cp15.c14_timer[timeridx].ctl;
+
+ env->cp15.c14_timer[timeridx].ctl = value & 3;
+ if ((oldval ^ value) & 1) {
+ /* Enable toggled */
+ gt_recalc_timer(cpu, timeridx);
+ } else if ((oldval & value) & 2) {
+ /* IMASK toggled: don't need to recalculate,
+ * just set the interrupt line based on ISTATUS
+ */
+ qemu_set_irq(cpu->gt_timer_outputs[timeridx],
+ (oldval & 4) && (value & 2));
+ }
+ return 0;
+}
+
+void arm_gt_ptimer_cb(void *opaque)
+{
+ ARMCPU *cpu = opaque;
+
+ gt_recalc_timer(cpu, GTIMER_PHYS);
+}
+
+void arm_gt_vtimer_cb(void *opaque)
+{
+ ARMCPU *cpu = opaque;
+
+ gt_recalc_timer(cpu, GTIMER_VIRT);
+}
+
static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
- /* Dummy implementation: RAZ/WI the whole crn=14 space */
- { .name = "GENERIC_TIMER", .cp = 15, .crn = 14,
- .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = CP_ANY,
- .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_NO_MIGRATE,
- .resetvalue = 0 },
+ /* Note that CNTFRQ is purely reads-as-written for the benefit
+ * of software; writing it doesn't actually change the timer frequency.
+ * Our reset value matches the fixed frequency we implement the timer at.
+ */
+ { .name = "CNTFRQ", .cp = 15, .crn = 14, .crm = 0, .opc1 = 0, .opc2 = 0,
+ .access = PL1_RW | PL0_R,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
+ .resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE,
+ .readfn = gt_cntfrq_read, .raw_readfn = raw_read,
+ },
+ /* overall control: mostly access permissions */
+ { .name = "CNTKCTL", .cp = 15, .crn = 14, .crm = 1, .opc1 = 0, .opc2 = 0,
+ .access = PL1_RW,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_cntkctl),
+ .resetvalue = 0,
+ },
+ /* per-timer control */
+ { .name = "CNTP_CTL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 1,
+ .type = ARM_CP_IO, .access = PL1_RW | PL0_R,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
+ .resetvalue = 0,
+ .readfn = gt_ctl_read, .writefn = gt_ctl_write,
+ .raw_readfn = raw_read, .raw_writefn = raw_write,
+ },
+ { .name = "CNTV_CTL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 1,
+ .type = ARM_CP_IO, .access = PL1_RW | PL0_R,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
+ .resetvalue = 0,
+ .readfn = gt_ctl_read, .writefn = gt_ctl_write,
+ .raw_readfn = raw_read, .raw_writefn = raw_write,
+ },
+ /* TimerValue views: a 32 bit downcounting view of the underlying state */
+ { .name = "CNTP_TVAL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 0,
+ .type = ARM_CP_NO_MIGRATE | ARM_CP_IO, .access = PL1_RW | PL0_R,
+ .readfn = gt_tval_read, .writefn = gt_tval_write,
+ },
+ { .name = "CNTV_TVAL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 0,
+ .type = ARM_CP_NO_MIGRATE | ARM_CP_IO, .access = PL1_RW | PL0_R,
+ .readfn = gt_tval_read, .writefn = gt_tval_write,
+ },
+ /* The counter itself */
+ { .name = "CNTPCT", .cp = 15, .crm = 14, .opc1 = 0,
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE | ARM_CP_IO,
+ .readfn = gt_cnt_read, .resetfn = gt_cnt_reset,
+ },
+ { .name = "CNTVCT", .cp = 15, .crm = 14, .opc1 = 1,
+ .access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE | ARM_CP_IO,
+ .readfn = gt_cnt_read, .resetfn = gt_cnt_reset,
+ },
+ /* Comparison value, indicating when the timer goes off */
+ { .name = "CNTP_CVAL", .cp = 15, .crm = 14, .opc1 = 2,
+ .access = PL1_RW | PL0_R,
+ .type = ARM_CP_64BIT | ARM_CP_IO,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
+ .resetvalue = 0,
+ .readfn = gt_cval_read, .writefn = gt_cval_write,
+ .raw_readfn = raw_read, .raw_writefn = raw_write,
+ },
+ { .name = "CNTV_CVAL", .cp = 15, .crm = 14, .opc1 = 3,
+ .access = PL1_RW | PL0_R,
+ .type = ARM_CP_64BIT | ARM_CP_IO,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
+ .resetvalue = 0,
+ .readfn = gt_cval_read, .writefn = gt_cval_write,
+ .raw_readfn = raw_read, .raw_writefn = raw_write,
+ },
REGINFO_SENTINEL
};
+#else
+/* In user-mode none of the generic timer registers are accessible,
+ * and their implementation depends on QEMU_CLOCK_VIRTUAL and qdev gpio outputs,
+ * so instead just don't register any of them.
+ */
+static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
+ REGINFO_SENTINEL
+};
+
+#endif
+
static int par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
if (arm_feature(env, ARM_FEATURE_LPAE)) {
@@ -1653,7 +1907,7 @@
"was %s, now %s\n", r2->cp, 32 + 32 * is64,
r2->crn, r2->crm, r2->opc1, r2->opc2,
oldreg->name, r2->name);
- assert(0);
+ g_assert_not_reached();
}
}
g_hash_table_insert(cpu->cp_regs, key, r2);
@@ -1974,6 +2228,37 @@
pointer. */
}
+/* Exception names for debug logging; note that not all of these
+ * precisely correspond to architectural exceptions.
+ */
+static const char * const excnames[] = {
+ [EXCP_UDEF] = "Undefined Instruction",
+ [EXCP_SWI] = "SVC",
+ [EXCP_PREFETCH_ABORT] = "Prefetch Abort",
+ [EXCP_DATA_ABORT] = "Data Abort",
+ [EXCP_IRQ] = "IRQ",
+ [EXCP_FIQ] = "FIQ",
+ [EXCP_BKPT] = "Breakpoint",
+ [EXCP_EXCEPTION_EXIT] = "QEMU v7M exception exit",
+ [EXCP_KERNEL_TRAP] = "QEMU intercept of kernel commpage",
+ [EXCP_STREX] = "QEMU intercept of STREX",
+};
+
+static inline void arm_log_exception(int idx)
+{
+ if (qemu_loglevel_mask(CPU_LOG_INT)) {
+ const char *exc = NULL;
+
+ if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
+ exc = excnames[idx];
+ }
+ if (!exc) {
+ exc = "unknown";
+ }
+ qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc);
+ }
+}
+
void arm_v7m_cpu_do_interrupt(CPUState *cs)
{
ARMCPU *cpu = ARM_CPU(cs);
@@ -1982,6 +2267,8 @@
uint32_t lr;
uint32_t addr;
+ arm_log_exception(env->exception_index);
+
lr = 0xfffffff1;
if (env->v7m.current_sp)
lr |= 4;
@@ -2011,6 +2298,7 @@
if (nr == 0xab) {
env->regs[15] += 2;
env->regs[0] = do_arm_semihosting(env);
+ qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n");
return;
}
}
@@ -2064,6 +2352,8 @@
assert(!IS_M(env));
+ arm_log_exception(env->exception_index);
+
/* TODO: Vectored interrupt controller. */
switch (env->exception_index) {
case EXCP_UDEF:
@@ -2091,6 +2381,7 @@
|| (mask == 0xab && env->thumb))
&& (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
env->regs[0] = do_arm_semihosting(env);
+ qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n");
return;
}
}
@@ -2108,18 +2399,23 @@
&& (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
env->regs[15] += 2;
env->regs[0] = do_arm_semihosting(env);
+ qemu_log_mask(CPU_LOG_INT, "...handled as semihosting call\n");
return;
}
}
env->cp15.c5_insn = 2;
/* Fall through to prefetch abort. */
case EXCP_PREFETCH_ABORT:
+ qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",
+ env->cp15.c5_insn, env->cp15.c6_insn);
new_mode = ARM_CPU_MODE_ABT;
addr = 0x0c;
mask = CPSR_A | CPSR_I;
offset = 4;
break;
case EXCP_DATA_ABORT:
+ qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",
+ env->cp15.c5_data, env->cp15.c6_data);
new_mode = ARM_CPU_MODE_ABT;
addr = 0x10;
mask = CPSR_A | CPSR_I;
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 6d4c2d4..5b6f375 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -222,9 +222,9 @@
const VMStateDescription vmstate_arm_cpu = {
.name = "cpu",
- .version_id = 12,
- .minimum_version_id = 12,
- .minimum_version_id_old = 12,
+ .version_id = 13,
+ .minimum_version_id = 13,
+ .minimum_version_id_old = 13,
.pre_save = cpu_pre_save,
.post_load = cpu_post_load,
.fields = (VMStateField[]) {
@@ -257,6 +257,8 @@
VMSTATE_UINT32(env.exclusive_val, ARMCPU),
VMSTATE_UINT32(env.exclusive_high, ARMCPU),
VMSTATE_UINT64(env.features, ARMCPU),
+ VMSTATE_TIMER(gt_timer[GTIMER_PHYS], ARMCPU),
+ VMSTATE_TIMER(gt_timer[GTIMER_VIRT], ARMCPU),
VMSTATE_END_OF_LIST()
},
.subsections = (VMStateSubsection[]) {
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 6db4c50..d1e8538 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6280,6 +6280,10 @@
break;
}
+ if (use_icount && (ri->type & ARM_CP_IO)) {
+ gen_io_start();
+ }
+
if (isread) {
/* Read */
if (is64) {
@@ -6369,14 +6373,20 @@
store_cpu_offset(tmp, ri->fieldoffset);
}
}
+ }
+
+ if (use_icount && (ri->type & ARM_CP_IO)) {
+ /* I/O operations must end the TB here (whether read or write) */
+ gen_io_end();
+ gen_lookup_tb(s);
+ } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
/* We default to ending the TB on a coprocessor register write,
* but allow this to be suppressed by the register definition
* (usually only necessary to work around guest bugs).
*/
- if (!(ri->type & ARM_CP_SUPPRESS_TB_END)) {
- gen_lookup_tb(s);
- }
+ gen_lookup_tb(s);
}
+
return 0;
}
diff --git a/target-cris/Makefile.objs b/target-cris/Makefile.objs
index afb87bc..7779227 100644
--- a/target-cris/Makefile.objs
+++ b/target-cris/Makefile.objs
@@ -1,2 +1,3 @@
obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
obj-$(CONFIG_SOFTMMU) += mmu.o machine.o
diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h
index d7baf07..7559366 100644
--- a/target-cris/cpu-qom.h
+++ b/target-cris/cpu-qom.h
@@ -81,4 +81,8 @@
hwaddr cris_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int crisv10_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int cris_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int cris_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
#endif
diff --git a/target-cris/cpu.c b/target-cris/cpu.c
index ba095e7..44301a4 100644
--- a/target-cris/cpu.c
+++ b/target-cris/cpu.c
@@ -137,10 +137,11 @@
static void cris_cpu_realizefn(DeviceState *dev, Error **errp)
{
- CRISCPU *cpu = CRIS_CPU(dev);
+ CPUState *cs = CPU(dev);
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(dev);
- cpu_reset(CPU(cpu));
+ cpu_reset(cs);
+ qemu_init_vcpu(cs);
ccc->parent_realize(dev, errp);
}
@@ -175,6 +176,7 @@
ccc->vr = 8;
cc->do_interrupt = crisv10_cpu_do_interrupt;
+ cc->gdb_read_register = crisv10_cpu_gdb_read_register;
}
static void crisv9_cpu_class_init(ObjectClass *oc, void *data)
@@ -184,6 +186,7 @@
ccc->vr = 9;
cc->do_interrupt = crisv10_cpu_do_interrupt;
+ cc->gdb_read_register = crisv10_cpu_gdb_read_register;
}
static void crisv10_cpu_class_init(ObjectClass *oc, void *data)
@@ -193,6 +196,7 @@
ccc->vr = 10;
cc->do_interrupt = crisv10_cpu_do_interrupt;
+ cc->gdb_read_register = crisv10_cpu_gdb_read_register;
}
static void crisv11_cpu_class_init(ObjectClass *oc, void *data)
@@ -202,6 +206,7 @@
ccc->vr = 11;
cc->do_interrupt = crisv10_cpu_do_interrupt;
+ cc->gdb_read_register = crisv10_cpu_gdb_read_register;
}
static void crisv32_cpu_class_init(ObjectClass *oc, void *data)
@@ -255,9 +260,13 @@
cc->do_interrupt = cris_cpu_do_interrupt;
cc->dump_state = cris_cpu_dump_state;
cc->set_pc = cris_cpu_set_pc;
+ cc->gdb_read_register = cris_cpu_gdb_read_register;
+ cc->gdb_write_register = cris_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = cris_cpu_get_phys_page_debug;
#endif
+
+ cc->gdb_num_core_regs = 49;
}
static const TypeInfo cris_cpu_type_info = {
diff --git a/target-cris/gdbstub.c b/target-cris/gdbstub.c
new file mode 100644
index 0000000..5db3683
--- /dev/null
+++ b/target-cris/gdbstub.c
@@ -0,0 +1,130 @@
+/*
+ * CRIS gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+int crisv10_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ CRISCPU *cpu = CRIS_CPU(cs);
+ CPUCRISState *env = &cpu->env;
+
+ if (n < 15) {
+ return gdb_get_reg32(mem_buf, env->regs[n]);
+ }
+
+ if (n == 15) {
+ return gdb_get_reg32(mem_buf, env->pc);
+ }
+
+ if (n < 32) {
+ switch (n) {
+ case 16:
+ return gdb_get_reg8(mem_buf, env->pregs[n - 16]);
+ case 17:
+ return gdb_get_reg8(mem_buf, env->pregs[n - 16]);
+ case 20:
+ case 21:
+ return gdb_get_reg16(mem_buf, env->pregs[n - 16]);
+ default:
+ if (n >= 23) {
+ return gdb_get_reg32(mem_buf, env->pregs[n - 16]);
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+int cris_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ CRISCPU *cpu = CRIS_CPU(cs);
+ CPUCRISState *env = &cpu->env;
+ uint8_t srs;
+
+ srs = env->pregs[PR_SRS];
+ if (n < 16) {
+ return gdb_get_reg32(mem_buf, env->regs[n]);
+ }
+
+ if (n >= 21 && n < 32) {
+ return gdb_get_reg32(mem_buf, env->pregs[n - 16]);
+ }
+ if (n >= 33 && n < 49) {
+ return gdb_get_reg32(mem_buf, env->sregs[srs][n - 33]);
+ }
+ switch (n) {
+ case 16:
+ return gdb_get_reg8(mem_buf, env->pregs[0]);
+ case 17:
+ return gdb_get_reg8(mem_buf, env->pregs[1]);
+ case 18:
+ return gdb_get_reg32(mem_buf, env->pregs[2]);
+ case 19:
+ return gdb_get_reg8(mem_buf, srs);
+ case 20:
+ return gdb_get_reg16(mem_buf, env->pregs[4]);
+ case 32:
+ return gdb_get_reg32(mem_buf, env->pc);
+ }
+
+ return 0;
+}
+
+int cris_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ CRISCPU *cpu = CRIS_CPU(cs);
+ CPUCRISState *env = &cpu->env;
+ uint32_t tmp;
+
+ if (n > 49) {
+ return 0;
+ }
+
+ tmp = ldl_p(mem_buf);
+
+ if (n < 16) {
+ env->regs[n] = tmp;
+ }
+
+ if (n >= 21 && n < 32) {
+ env->pregs[n - 16] = tmp;
+ }
+
+ /* FIXME: Should support function regs be writable? */
+ switch (n) {
+ case 16:
+ return 1;
+ case 17:
+ return 1;
+ case 18:
+ env->pregs[PR_PID] = tmp;
+ break;
+ case 19:
+ return 1;
+ case 20:
+ return 2;
+ case 32:
+ env->pc = tmp;
+ break;
+ }
+
+ return 4;
+}
diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs
index c1d4f05..da1fc40 100644
--- a/target-i386/Makefile.objs
+++ b/target-i386/Makefile.objs
@@ -1,8 +1,9 @@
obj-y += translate.o helper.o cpu.o
obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o
obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o
+obj-y += gdbstub.o
obj-$(CONFIG_SOFTMMU) += machine.o arch_memory_mapping.o arch_dump.o
-obj-$(CONFIG_KVM) += kvm.o hyperv.o
+obj-$(CONFIG_KVM) += kvm.o
obj-$(CONFIG_NO_KVM) += kvm-stub.o
obj-$(CONFIG_LINUX_USER) += ioport-user.o
obj-$(CONFIG_BSD_USER) += ioport-user.o
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index 10dc228..0bbed23 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -15,6 +15,7 @@
#include "exec/cpu-all.h"
#include "sysemu/dump.h"
#include "elf.h"
+#include "sysemu/memory_mapping.h"
#ifdef TARGET_X86_64
typedef struct {
@@ -389,10 +390,11 @@
return cpu_write_qemu_note(f, &cpu->env, opaque, 0);
}
-int cpu_get_dump_info(ArchDumpInfo *info)
+int cpu_get_dump_info(ArchDumpInfo *info,
+ const GuestPhysBlockList *guest_phys_blocks)
{
bool lma = false;
- RAMBlock *block;
+ GuestPhysBlock *block;
#ifdef TARGET_X86_64
X86CPU *first_x86_cpu = X86_CPU(first_cpu);
@@ -412,8 +414,8 @@
} else {
info->d_class = ELFCLASS32;
- QTAILQ_FOREACH(block, &ram_list.blocks, next) {
- if (block->offset + block->length > UINT_MAX) {
+ QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) {
+ if (block->target_end > UINT_MAX) {
/* The memory size is greater than 4G */
info->d_class = ELFCLASS64;
break;
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index d928562..c4447c2 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -66,8 +66,19 @@
CPUX86State env;
+ bool hyperv_vapic;
+ bool hyperv_relaxed_timing;
+ int hyperv_spinlock_attempts;
+
/* Features that were filtered out because of missing host capabilities */
uint32_t filtered_features[FEATURE_WORDS];
+
+ /* Enable PMU CPUID bits. This can't be enabled by default yet because
+ * it doesn't have ABI stability guarantees, as it passes all PMU CPUID
+ * bits returned by GET_SUPPORTED_CPUID (that depend on host CPU and kernel
+ * capabilities) directly to the guest.
+ */
+ bool enable_pmu;
} X86CPU;
static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
@@ -106,4 +117,7 @@
hwaddr x86_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int x86_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int x86_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
#endif
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index cd350cb..42c5de0 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -35,8 +35,6 @@
#include "qapi/visitor.h"
#include "sysemu/arch_init.h"
-#include "hyperv.h"
-
#include "hw/hw.h"
#if defined(CONFIG_KVM)
#include <linux/kvm_para.h>
@@ -1475,9 +1473,11 @@
error_propagate(errp, err);
}
-static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name)
+static int cpu_x86_find_by_name(X86CPU *cpu, x86_def_t *x86_cpu_def,
+ const char *name)
{
x86_def_t *def;
+ Error *err = NULL;
int i;
if (name == NULL) {
@@ -1485,6 +1485,8 @@
}
if (kvm_enabled() && strcmp(name, "host") == 0) {
kvm_cpu_fill_host(x86_cpu_def);
+ object_property_set_bool(OBJECT(cpu), true, "pmu", &err);
+ assert_no_error(err);
return 0;
}
@@ -1587,12 +1589,19 @@
object_property_parse(OBJECT(cpu), num, "tsc-frequency", errp);
} else if (!strcmp(featurestr, "hv-spinlocks")) {
char *err;
+ const int min = 0xFFF;
numvalue = strtoul(val, &err, 0);
if (!*val || *err) {
error_setg(errp, "bad numerical value %s", val);
goto out;
}
- hyperv_set_spinlock_retries(numvalue);
+ if (numvalue < min) {
+ fprintf(stderr, "hv-spinlocks value shall always be >= 0x%x"
+ ", fixup will be removed in future versions\n",
+ min);
+ numvalue = min;
+ }
+ cpu->hyperv_spinlock_attempts = numvalue;
} else {
error_setg(errp, "unrecognized feature %s", featurestr);
goto out;
@@ -1602,9 +1611,9 @@
} else if (!strcmp(featurestr, "enforce")) {
check_cpuid = enforce_cpuid = 1;
} else if (!strcmp(featurestr, "hv_relaxed")) {
- hyperv_enable_relaxed_timing(true);
+ cpu->hyperv_relaxed_timing = true;
} else if (!strcmp(featurestr, "hv_vapic")) {
- hyperv_enable_vapic_recommended(true);
+ cpu->hyperv_vapic = true;
} else {
error_setg(errp, "feature string `%s' not in format (+feature|"
"-feature|feature=xyz)", featurestr);
@@ -1742,7 +1751,7 @@
memset(def, 0, sizeof(*def));
- if (cpu_x86_find_by_name(def, name) < 0) {
+ if (cpu_x86_find_by_name(cpu, def, name) < 0) {
error_setg(errp, "Unable to find CPU definition: %s", name);
return;
}
@@ -1820,7 +1829,11 @@
}
out:
- error_propagate(errp, error);
+ if (error != NULL) {
+ error_propagate(errp, error);
+ object_unref(OBJECT(cpu));
+ cpu = NULL;
+ }
g_strfreev(model_pieces);
return cpu;
}
@@ -1839,7 +1852,7 @@
out:
if (error) {
- fprintf(stderr, "%s\n", error_get_pretty(error));
+ error_report("%s", error_get_pretty(error));
error_free(error);
if (cpu != NULL) {
object_unref(OBJECT(cpu));
@@ -2016,7 +2029,7 @@
break;
case 0xA:
/* Architectural Performance Monitoring Leaf */
- if (kvm_enabled()) {
+ if (kvm_enabled() && cpu->enable_pmu) {
KVMState *s = cs->kvm_state;
*eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
@@ -2333,6 +2346,7 @@
static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
{
+ CPUState *cs = CPU(dev);
X86CPU *cpu = X86_CPU(dev);
X86CPUClass *xcc = X86_CPU_GET_CLASS(dev);
CPUX86State *env = &cpu->env;
@@ -2387,12 +2401,13 @@
#endif
mce_init(cpu);
+ qemu_init_vcpu(cs);
x86_cpu_apic_realize(cpu, &local_err);
if (local_err != NULL) {
goto out;
}
- cpu_reset(CPU(cpu));
+ cpu_reset(cs);
xcc->parent_realize(dev, &local_err);
out:
@@ -2479,6 +2494,7 @@
x86_cpu_get_feature_words,
NULL, NULL, (void *)cpu->filtered_features, NULL);
+ cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index);
/* init various static tables used in TCG mode */
@@ -2520,6 +2536,11 @@
cpu->env.eip = tb->pc - tb->cs_base;
}
+static Property x86_cpu_properties[] = {
+ DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
+ DEFINE_PROP_END_OF_LIST()
+};
+
static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
{
X86CPUClass *xcc = X86_CPU_CLASS(oc);
@@ -2529,6 +2550,7 @@
xcc->parent_realize = dc->realize;
dc->realize = x86_cpu_realizefn;
dc->bus_type = TYPE_ICC_BUS;
+ dc->props = x86_cpu_properties;
xcc->parent_reset = cc->reset;
cc->reset = x86_cpu_reset;
@@ -2538,6 +2560,8 @@
cc->dump_state = x86_cpu_dump_state;
cc->set_pc = x86_cpu_set_pc;
cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
+ cc->gdb_read_register = x86_cpu_gdb_read_register;
+ cc->gdb_write_register = x86_cpu_gdb_write_register;
cc->get_arch_id = x86_cpu_get_arch_id;
cc->get_paging_enabled = x86_cpu_get_paging_enabled;
#ifndef CONFIG_USER_ONLY
@@ -2549,6 +2573,7 @@
cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote;
cc->vmsd = &vmstate_x86_cpu;
#endif
+ cc->gdb_num_core_regs = CPU_NB_REGS * 2 + 25;
}
static const TypeInfo x86_cpu_type_info = {
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 31de265..5723eff 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -562,24 +562,28 @@
#define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */
#define CPUID_MWAIT_EMX (1 << 0) /* enumeration supported */
-#define EXCP00_DIVZ 0
-#define EXCP01_DB 1
-#define EXCP02_NMI 2
-#define EXCP03_INT3 3
-#define EXCP04_INTO 4
-#define EXCP05_BOUND 5
-#define EXCP06_ILLOP 6
-#define EXCP07_PREX 7
-#define EXCP08_DBLE 8
-#define EXCP09_XERR 9
-#define EXCP0A_TSS 10
-#define EXCP0B_NOSEG 11
-#define EXCP0C_STACK 12
-#define EXCP0D_GPF 13
-#define EXCP0E_PAGE 14
-#define EXCP10_COPR 16
-#define EXCP11_ALGN 17
-#define EXCP12_MCHK 18
+#ifndef HYPERV_SPINLOCK_NEVER_RETRY
+#define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF
+#endif
+
+#define EXCP00_DIVZ 0
+#define EXCP01_DB 1
+#define EXCP02_NMI 2
+#define EXCP03_INT3 3
+#define EXCP04_INTO 4
+#define EXCP05_BOUND 5
+#define EXCP06_ILLOP 6
+#define EXCP07_PREX 7
+#define EXCP08_DBLE 8
+#define EXCP09_XERR 9
+#define EXCP0A_TSS 10
+#define EXCP0B_NOSEG 11
+#define EXCP0C_STACK 12
+#define EXCP0D_GPF 13
+#define EXCP0E_PAGE 14
+#define EXCP10_COPR 16
+#define EXCP11_ALGN 17
+#define EXCP12_MCHK 18
#define EXCP_SYSCALL 0x100 /* only happens in user only emulation
for syscall instruction */
diff --git a/target-i386/gdbstub.c b/target-i386/gdbstub.c
new file mode 100644
index 0000000..15bebef
--- /dev/null
+++ b/target-i386/gdbstub.c
@@ -0,0 +1,231 @@
+/*
+ * x86 gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+#ifdef TARGET_X86_64
+static const int gpr_map[16] = {
+ R_EAX, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP, R_ESP,
+ 8, 9, 10, 11, 12, 13, 14, 15
+};
+#else
+#define gpr_map gpr_map32
+#endif
+static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+
+#define IDX_IP_REG CPU_NB_REGS
+#define IDX_FLAGS_REG (IDX_IP_REG + 1)
+#define IDX_SEG_REGS (IDX_FLAGS_REG + 1)
+#define IDX_FP_REGS (IDX_SEG_REGS + 6)
+#define IDX_XMM_REGS (IDX_FP_REGS + 16)
+#define IDX_MXCSR_REG (IDX_XMM_REGS + CPU_NB_REGS)
+
+int x86_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+
+ if (n < CPU_NB_REGS) {
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ return gdb_get_reg64(mem_buf, env->regs[gpr_map[n]]);
+ } else if (n < CPU_NB_REGS32) {
+ return gdb_get_reg32(mem_buf, env->regs[gpr_map32[n]]);
+ }
+ } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
+#ifdef USE_X86LDOUBLE
+ /* FIXME: byteswap float values - after fixing fpregs layout. */
+ memcpy(mem_buf, &env->fpregs[n - IDX_FP_REGS], 10);
+#else
+ memset(mem_buf, 0, 10);
+#endif
+ return 10;
+ } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
+ n -= IDX_XMM_REGS;
+ if (n < CPU_NB_REGS32 ||
+ (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
+ stq_p(mem_buf, env->xmm_regs[n].XMM_Q(0));
+ stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1));
+ return 16;
+ }
+ } else {
+ switch (n) {
+ case IDX_IP_REG:
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ return gdb_get_reg64(mem_buf, env->eip);
+ } else {
+ return gdb_get_reg32(mem_buf, env->eip);
+ }
+ case IDX_FLAGS_REG:
+ return gdb_get_reg32(mem_buf, env->eflags);
+
+ case IDX_SEG_REGS:
+ return gdb_get_reg32(mem_buf, env->segs[R_CS].selector);
+ case IDX_SEG_REGS + 1:
+ return gdb_get_reg32(mem_buf, env->segs[R_SS].selector);
+ case IDX_SEG_REGS + 2:
+ return gdb_get_reg32(mem_buf, env->segs[R_DS].selector);
+ case IDX_SEG_REGS + 3:
+ return gdb_get_reg32(mem_buf, env->segs[R_ES].selector);
+ case IDX_SEG_REGS + 4:
+ return gdb_get_reg32(mem_buf, env->segs[R_FS].selector);
+ case IDX_SEG_REGS + 5:
+ return gdb_get_reg32(mem_buf, env->segs[R_GS].selector);
+
+ case IDX_FP_REGS + 8:
+ return gdb_get_reg32(mem_buf, env->fpuc);
+ case IDX_FP_REGS + 9:
+ return gdb_get_reg32(mem_buf, (env->fpus & ~0x3800) |
+ (env->fpstt & 0x7) << 11);
+ case IDX_FP_REGS + 10:
+ return gdb_get_reg32(mem_buf, 0); /* ftag */
+ case IDX_FP_REGS + 11:
+ return gdb_get_reg32(mem_buf, 0); /* fiseg */
+ case IDX_FP_REGS + 12:
+ return gdb_get_reg32(mem_buf, 0); /* fioff */
+ case IDX_FP_REGS + 13:
+ return gdb_get_reg32(mem_buf, 0); /* foseg */
+ case IDX_FP_REGS + 14:
+ return gdb_get_reg32(mem_buf, 0); /* fooff */
+ case IDX_FP_REGS + 15:
+ return gdb_get_reg32(mem_buf, 0); /* fop */
+
+ case IDX_MXCSR_REG:
+ return gdb_get_reg32(mem_buf, env->mxcsr);
+ }
+ }
+ return 0;
+}
+
+static int x86_cpu_gdb_load_seg(X86CPU *cpu, int sreg, uint8_t *mem_buf)
+{
+ CPUX86State *env = &cpu->env;
+ uint16_t selector = ldl_p(mem_buf);
+
+ if (selector != env->segs[sreg].selector) {
+#if defined(CONFIG_USER_ONLY)
+ cpu_x86_load_seg(env, sreg, selector);
+#else
+ unsigned int limit, flags;
+ target_ulong base;
+
+ if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
+ base = selector << 4;
+ limit = 0xffff;
+ flags = 0;
+ } else {
+ if (!cpu_x86_get_descr_debug(env, selector, &base, &limit,
+ &flags)) {
+ return 4;
+ }
+ }
+ cpu_x86_load_seg_cache(env, sreg, selector, base, limit, flags);
+#endif
+ }
+ return 4;
+}
+
+int x86_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+ uint32_t tmp;
+
+ if (n < CPU_NB_REGS) {
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ env->regs[gpr_map[n]] = ldtul_p(mem_buf);
+ return sizeof(target_ulong);
+ } else if (n < CPU_NB_REGS32) {
+ n = gpr_map32[n];
+ env->regs[n] &= ~0xffffffffUL;
+ env->regs[n] |= (uint32_t)ldl_p(mem_buf);
+ return 4;
+ }
+ } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
+#ifdef USE_X86LDOUBLE
+ /* FIXME: byteswap float values - after fixing fpregs layout. */
+ memcpy(&env->fpregs[n - IDX_FP_REGS], mem_buf, 10);
+#endif
+ return 10;
+ } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
+ n -= IDX_XMM_REGS;
+ if (n < CPU_NB_REGS32 ||
+ (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
+ env->xmm_regs[n].XMM_Q(0) = ldq_p(mem_buf);
+ env->xmm_regs[n].XMM_Q(1) = ldq_p(mem_buf + 8);
+ return 16;
+ }
+ } else {
+ switch (n) {
+ case IDX_IP_REG:
+ if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+ env->eip = ldq_p(mem_buf);
+ return 8;
+ } else {
+ env->eip &= ~0xffffffffUL;
+ env->eip |= (uint32_t)ldl_p(mem_buf);
+ return 4;
+ }
+ case IDX_FLAGS_REG:
+ env->eflags = ldl_p(mem_buf);
+ return 4;
+
+ case IDX_SEG_REGS:
+ return x86_cpu_gdb_load_seg(cpu, R_CS, mem_buf);
+ case IDX_SEG_REGS + 1:
+ return x86_cpu_gdb_load_seg(cpu, R_SS, mem_buf);
+ case IDX_SEG_REGS + 2:
+ return x86_cpu_gdb_load_seg(cpu, R_DS, mem_buf);
+ case IDX_SEG_REGS + 3:
+ return x86_cpu_gdb_load_seg(cpu, R_ES, mem_buf);
+ case IDX_SEG_REGS + 4:
+ return x86_cpu_gdb_load_seg(cpu, R_FS, mem_buf);
+ case IDX_SEG_REGS + 5:
+ return x86_cpu_gdb_load_seg(cpu, R_GS, mem_buf);
+
+ case IDX_FP_REGS + 8:
+ env->fpuc = ldl_p(mem_buf);
+ return 4;
+ case IDX_FP_REGS + 9:
+ tmp = ldl_p(mem_buf);
+ env->fpstt = (tmp >> 11) & 7;
+ env->fpus = tmp & ~0x3800;
+ return 4;
+ case IDX_FP_REGS + 10: /* ftag */
+ return 4;
+ case IDX_FP_REGS + 11: /* fiseg */
+ return 4;
+ case IDX_FP_REGS + 12: /* fioff */
+ return 4;
+ case IDX_FP_REGS + 13: /* foseg */
+ return 4;
+ case IDX_FP_REGS + 14: /* fooff */
+ return 4;
+ case IDX_FP_REGS + 15: /* fop */
+ return 4;
+
+ case IDX_MXCSR_REG:
+ env->mxcsr = ldl_p(mem_buf);
+ return 4;
+ }
+ }
+ /* Unrecognised register. */
+ return 0;
+}
diff --git a/target-i386/hyperv.c b/target-i386/hyperv.c
deleted file mode 100644
index f284e99..0000000
--- a/target-i386/hyperv.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * QEMU Hyper-V support
- *
- * Copyright Red Hat, Inc. 2011
- *
- * Author: Vadim Rozenfeld <vrozenfe@redhat.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 "hyperv.h"
-
-static bool hyperv_vapic;
-static bool hyperv_relaxed_timing;
-static int hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
-
-void hyperv_enable_vapic_recommended(bool val)
-{
- hyperv_vapic = val;
-}
-
-void hyperv_enable_relaxed_timing(bool val)
-{
- hyperv_relaxed_timing = val;
-}
-
-void hyperv_set_spinlock_retries(int val)
-{
- hyperv_spinlock_attempts = val;
- if (hyperv_spinlock_attempts < 0xFFF) {
- hyperv_spinlock_attempts = 0xFFF;
- }
-}
-
-bool hyperv_enabled(void)
-{
- return hyperv_hypercall_available() || hyperv_relaxed_timing_enabled();
-}
-
-bool hyperv_hypercall_available(void)
-{
- if (hyperv_vapic ||
- (hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_RETRY)) {
- return true;
- }
- return false;
-}
-
-bool hyperv_vapic_recommended(void)
-{
- return hyperv_vapic;
-}
-
-bool hyperv_relaxed_timing_enabled(void)
-{
- return hyperv_relaxed_timing;
-}
-
-int hyperv_get_spinlock_retries(void)
-{
- return hyperv_spinlock_attempts;
-}
diff --git a/target-i386/hyperv.h b/target-i386/hyperv.h
deleted file mode 100644
index bacb1d4..0000000
--- a/target-i386/hyperv.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * QEMU Hyper-V support
- *
- * Copyright Red Hat, Inc. 2011
- *
- * Author: Vadim Rozenfeld <vrozenfe@redhat.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.
- *
- */
-
-#ifndef QEMU_HW_HYPERV_H
-#define QEMU_HW_HYPERV_H 1
-
-#include "qemu-common.h"
-#ifdef CONFIG_KVM
-#include <asm/hyperv.h>
-#endif
-
-#ifndef HYPERV_SPINLOCK_NEVER_RETRY
-#define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF
-#endif
-
-#ifndef KVM_CPUID_SIGNATURE_NEXT
-#define KVM_CPUID_SIGNATURE_NEXT 0x40000100
-#endif
-
-#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_KVM)
-void hyperv_enable_vapic_recommended(bool val);
-void hyperv_enable_relaxed_timing(bool val);
-void hyperv_set_spinlock_retries(int val);
-#else
-static inline void hyperv_enable_vapic_recommended(bool val) { }
-static inline void hyperv_enable_relaxed_timing(bool val) { }
-static inline void hyperv_set_spinlock_retries(int val) { }
-#endif
-
-bool hyperv_enabled(void);
-bool hyperv_hypercall_available(void);
-bool hyperv_vapic_recommended(void);
-bool hyperv_relaxed_timing_enabled(void);
-int hyperv_get_spinlock_retries(void);
-
-#endif /* QEMU_HW_HYPERV_H */
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 58f7bb7..749aa09 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -31,7 +31,7 @@
#include "hw/i386/pc.h"
#include "hw/i386/apic.h"
#include "exec/ioport.h"
-#include "hyperv.h"
+#include <asm/hyperv.h>
#include "hw/pci/pci.h"
//#define DEBUG_KVM
@@ -424,6 +424,22 @@
return cpu->env.cpuid_apic_id;
}
+#ifndef KVM_CPUID_SIGNATURE_NEXT
+#define KVM_CPUID_SIGNATURE_NEXT 0x40000100
+#endif
+
+static bool hyperv_hypercall_available(X86CPU *cpu)
+{
+ return cpu->hyperv_vapic ||
+ (cpu->hyperv_spinlock_attempts != HYPERV_SPINLOCK_NEVER_RETRY);
+}
+
+static bool hyperv_enabled(X86CPU *cpu)
+{
+ return hyperv_hypercall_available(cpu) ||
+ cpu->hyperv_relaxed_timing;
+}
+
#define KVM_MAX_CPUID_ENTRIES 100
int kvm_arch_init_vcpu(CPUState *cs)
@@ -446,7 +462,7 @@
c = &cpuid_data.entries[cpuid_i++];
memset(c, 0, sizeof(*c));
c->function = KVM_CPUID_SIGNATURE;
- if (!hyperv_enabled()) {
+ if (!hyperv_enabled(cpu)) {
memcpy(signature, "KVMKVMKVM\0\0\0", 12);
c->eax = 0;
} else {
@@ -462,7 +478,7 @@
c->function = KVM_CPUID_FEATURES;
c->eax = env->features[FEAT_KVM];
- if (hyperv_enabled()) {
+ if (hyperv_enabled(cpu)) {
memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12);
c->eax = signature[0];
@@ -475,10 +491,10 @@
c = &cpuid_data.entries[cpuid_i++];
memset(c, 0, sizeof(*c));
c->function = HYPERV_CPUID_FEATURES;
- if (hyperv_relaxed_timing_enabled()) {
+ if (cpu->hyperv_relaxed_timing) {
c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
}
- if (hyperv_vapic_recommended()) {
+ if (cpu->hyperv_vapic) {
c->eax |= HV_X64_MSR_HYPERCALL_AVAILABLE;
c->eax |= HV_X64_MSR_APIC_ACCESS_AVAILABLE;
}
@@ -486,13 +502,13 @@
c = &cpuid_data.entries[cpuid_i++];
memset(c, 0, sizeof(*c));
c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
- if (hyperv_relaxed_timing_enabled()) {
+ if (cpu->hyperv_relaxed_timing) {
c->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
}
- if (hyperv_vapic_recommended()) {
+ if (cpu->hyperv_vapic) {
c->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
}
- c->ebx = hyperv_get_spinlock_retries();
+ c->ebx = cpu->hyperv_spinlock_attempts;
c = &cpuid_data.entries[cpuid_i++];
memset(c, 0, sizeof(*c));
@@ -1186,11 +1202,11 @@
kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_CTRL,
env->msr_global_ctrl);
}
- if (hyperv_hypercall_available()) {
+ if (hyperv_hypercall_available(cpu)) {
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0);
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0);
}
- if (hyperv_vapic_recommended()) {
+ if (cpu->hyperv_vapic) {
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0);
}
if (has_msr_feature_control) {
@@ -1735,7 +1751,7 @@
*/
if (reinject_trap ||
(!kvm_has_robust_singlestep() && cs->singlestep_enabled)) {
- ret = kvm_update_guest_debug(env, reinject_trap);
+ ret = kvm_update_guest_debug(cs, reinject_trap);
}
return ret;
}
diff --git a/target-lm32/Makefile.objs b/target-lm32/Makefile.objs
index ca20f21..4023687 100644
--- a/target-lm32/Makefile.objs
+++ b/target-lm32/Makefile.objs
@@ -1,2 +1,3 @@
obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h
index 9e27329..723f604 100644
--- a/target-lm32/cpu-qom.h
+++ b/target-lm32/cpu-qom.h
@@ -79,5 +79,7 @@
void lm32_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags);
hwaddr lm32_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int lm32_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int lm32_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#endif
diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c
index ce55e48..869878c 100644
--- a/target-lm32/cpu.c
+++ b/target-lm32/cpu.c
@@ -46,10 +46,12 @@
static void lm32_cpu_realizefn(DeviceState *dev, Error **errp)
{
- LM32CPU *cpu = LM32_CPU(dev);
+ CPUState *cs = CPU(dev);
LM32CPUClass *lcc = LM32_CPU_GET_CLASS(dev);
- cpu_reset(CPU(cpu));
+ cpu_reset(cs);
+
+ qemu_init_vcpu(cs);
lcc->parent_realize(dev, errp);
}
@@ -87,10 +89,13 @@
cc->do_interrupt = lm32_cpu_do_interrupt;
cc->dump_state = lm32_cpu_dump_state;
cc->set_pc = lm32_cpu_set_pc;
+ cc->gdb_read_register = lm32_cpu_gdb_read_register;
+ cc->gdb_write_register = lm32_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = lm32_cpu_get_phys_page_debug;
cc->vmsd = &vmstate_lm32_cpu;
#endif
+ cc->gdb_num_core_regs = 32 + 7;
}
static const TypeInfo lm32_cpu_type_info = {
diff --git a/target-lm32/gdbstub.c b/target-lm32/gdbstub.c
new file mode 100644
index 0000000..4979a98
--- /dev/null
+++ b/target-lm32/gdbstub.c
@@ -0,0 +1,92 @@
+/*
+ * LM32 gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+#include "hw/lm32/lm32_pic.h"
+
+int lm32_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ LM32CPU *cpu = LM32_CPU(cs);
+ CPULM32State *env = &cpu->env;
+
+ if (n < 32) {
+ return gdb_get_reg32(mem_buf, env->regs[n]);
+ } else {
+ switch (n) {
+ case 32:
+ return gdb_get_reg32(mem_buf, env->pc);
+ /* FIXME: put in right exception ID */
+ case 33:
+ return gdb_get_reg32(mem_buf, 0);
+ case 34:
+ return gdb_get_reg32(mem_buf, env->eba);
+ case 35:
+ return gdb_get_reg32(mem_buf, env->deba);
+ case 36:
+ return gdb_get_reg32(mem_buf, env->ie);
+ case 37:
+ return gdb_get_reg32(mem_buf, lm32_pic_get_im(env->pic_state));
+ case 38:
+ return gdb_get_reg32(mem_buf, lm32_pic_get_ip(env->pic_state));
+ }
+ }
+ return 0;
+}
+
+int lm32_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ LM32CPU *cpu = LM32_CPU(cs);
+ CPUClass *cc = CPU_GET_CLASS(cs);
+ CPULM32State *env = &cpu->env;
+ uint32_t tmp;
+
+ if (n > cc->gdb_num_core_regs) {
+ return 0;
+ }
+
+ tmp = ldl_p(mem_buf);
+
+ if (n < 32) {
+ env->regs[n] = tmp;
+ } else {
+ switch (n) {
+ case 32:
+ env->pc = tmp;
+ break;
+ case 34:
+ env->eba = tmp;
+ break;
+ case 35:
+ env->deba = tmp;
+ break;
+ case 36:
+ env->ie = tmp;
+ break;
+ case 37:
+ lm32_pic_set_im(env->pic_state, tmp);
+ break;
+ case 38:
+ lm32_pic_set_ip(env->pic_state, tmp);
+ break;
+ }
+ }
+ return 4;
+}
diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c
index f106873..2dab9f2 100644
--- a/target-lm32/op_helper.c
+++ b/target-lm32/op_helper.c
@@ -4,7 +4,7 @@
#include "qemu/host-utils.h"
#include "hw/lm32/lm32_pic.h"
-#include "hw/lm32/lm32_juart.h"
+#include "hw/char/lm32_juart.h"
#if !defined(CONFIG_USER_ONLY)
#define MMUSUFFIX _mmu
diff --git a/target-m68k/Makefile.objs b/target-m68k/Makefile.objs
index 2e2b850..02cf616 100644
--- a/target-m68k/Makefile.objs
+++ b/target-m68k/Makefile.objs
@@ -1,2 +1,3 @@
obj-y += m68k-semi.o
obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h
index 7115707..7f388ed 100644
--- a/target-m68k/cpu-qom.h
+++ b/target-m68k/cpu-qom.h
@@ -74,5 +74,7 @@
void m68k_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags);
hwaddr m68k_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int m68k_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int m68k_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#endif
diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c
index 988f476..008d8db 100644
--- a/target-m68k/cpu.c
+++ b/target-m68k/cpu.c
@@ -143,12 +143,14 @@
static void m68k_cpu_realizefn(DeviceState *dev, Error **errp)
{
+ CPUState *cs = CPU(dev);
M68kCPU *cpu = M68K_CPU(dev);
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(dev);
m68k_cpu_init_gdb(cpu);
- cpu_reset(CPU(cpu));
+ cpu_reset(cs);
+ qemu_init_vcpu(cs);
mcc->parent_realize(dev, errp);
}
@@ -190,10 +192,14 @@
cc->do_interrupt = m68k_cpu_do_interrupt;
cc->dump_state = m68k_cpu_dump_state;
cc->set_pc = m68k_cpu_set_pc;
+ cc->gdb_read_register = m68k_cpu_gdb_read_register;
+ cc->gdb_write_register = m68k_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
#endif
dc->vmsd = &vmstate_m68k_cpu;
+ cc->gdb_num_core_regs = 18;
+ cc->gdb_core_xml_file = "cf-core.xml";
}
static void register_cpu_type(const M68kCPUInfo *info)
diff --git a/target-m68k/gdbstub.c b/target-m68k/gdbstub.c
new file mode 100644
index 0000000..ae8179c
--- /dev/null
+++ b/target-m68k/gdbstub.c
@@ -0,0 +1,75 @@
+/*
+ * m68k gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+int m68k_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ M68kCPU *cpu = M68K_CPU(cs);
+ CPUM68KState *env = &cpu->env;
+
+ if (n < 8) {
+ /* D0-D7 */
+ return gdb_get_reg32(mem_buf, env->dregs[n]);
+ } else if (n < 16) {
+ /* A0-A7 */
+ return gdb_get_reg32(mem_buf, env->aregs[n - 8]);
+ } else {
+ switch (n) {
+ case 16:
+ return gdb_get_reg32(mem_buf, env->sr);
+ case 17:
+ return gdb_get_reg32(mem_buf, env->pc);
+ }
+ }
+ /* FP registers not included here because they vary between
+ ColdFire and m68k. Use XML bits for these. */
+ return 0;
+}
+
+int m68k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ M68kCPU *cpu = M68K_CPU(cs);
+ CPUM68KState *env = &cpu->env;
+ uint32_t tmp;
+
+ tmp = ldl_p(mem_buf);
+
+ if (n < 8) {
+ /* D0-D7 */
+ env->dregs[n] = tmp;
+ } else if (n < 16) {
+ /* A0-A7 */
+ env->aregs[n - 8] = tmp;
+ } else {
+ switch (n) {
+ case 16:
+ env->sr = tmp;
+ break;
+ case 17:
+ env->pc = tmp;
+ break;
+ default:
+ return 0;
+ }
+ }
+ return 4;
+}
diff --git a/target-microblaze/Makefile.objs b/target-microblaze/Makefile.objs
index 985330e..f3d7b44 100644
--- a/target-microblaze/Makefile.objs
+++ b/target-microblaze/Makefile.objs
@@ -1,2 +1,3 @@
obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
obj-$(CONFIG_SOFTMMU) += mmu.o
diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h
index 1318a36..35a12b4 100644
--- a/target-microblaze/cpu-qom.h
+++ b/target-microblaze/cpu-qom.h
@@ -75,5 +75,7 @@
void mb_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags);
hwaddr mb_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int mb_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int mb_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#endif
diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c
index 9f10c8c..0ef9aa4 100644
--- a/target-microblaze/cpu.c
+++ b/target-microblaze/cpu.c
@@ -90,10 +90,11 @@
static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
{
- MicroBlazeCPU *cpu = MICROBLAZE_CPU(dev);
+ CPUState *cs = CPU(dev);
MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(dev);
- cpu_reset(CPU(cpu));
+ cpu_reset(cs);
+ qemu_init_vcpu(cs);
mcc->parent_realize(dev, errp);
}
@@ -141,12 +142,15 @@
cc->do_interrupt = mb_cpu_do_interrupt;
cc->dump_state = mb_cpu_dump_state;
cc->set_pc = mb_cpu_set_pc;
+ cc->gdb_read_register = mb_cpu_gdb_read_register;
+ cc->gdb_write_register = mb_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->do_unassigned_access = mb_cpu_unassigned_access;
cc->get_phys_page_debug = mb_cpu_get_phys_page_debug;
#endif
dc->vmsd = &vmstate_mb_cpu;
dc->props = mb_properties;
+ cc->gdb_num_core_regs = 32 + 5;
}
static const TypeInfo mb_cpu_type_info = {
diff --git a/target-microblaze/gdbstub.c b/target-microblaze/gdbstub.c
new file mode 100644
index 0000000..a70e2ee
--- /dev/null
+++ b/target-microblaze/gdbstub.c
@@ -0,0 +1,56 @@
+/*
+ * MicroBlaze gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+int mb_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+ CPUMBState *env = &cpu->env;
+
+ if (n < 32) {
+ return gdb_get_reg32(mem_buf, env->regs[n]);
+ } else {
+ return gdb_get_reg32(mem_buf, env->sregs[n - 32]);
+ }
+ return 0;
+}
+
+int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+ CPUClass *cc = CPU_GET_CLASS(cs);
+ CPUMBState *env = &cpu->env;
+ uint32_t tmp;
+
+ if (n > cc->gdb_num_core_regs) {
+ return 0;
+ }
+
+ tmp = ldl_p(mem_buf);
+
+ if (n < 32) {
+ env->regs[n] = tmp;
+ } else {
+ env->sregs[n - 32] = tmp;
+ }
+ return 4;
+}
diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
index 119c816..0277d56 100644
--- a/target-mips/Makefile.objs
+++ b/target-mips/Makefile.objs
@@ -1,2 +1,3 @@
obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o
+obj-y += gdbstub.o
obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h
index 7c8e616..8877f81 100644
--- a/target-mips/cpu-qom.h
+++ b/target-mips/cpu-qom.h
@@ -78,5 +78,7 @@
void mips_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags);
hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#endif
diff --git a/target-mips/cpu.c b/target-mips/cpu.c
index 4834c86..9dd47e8 100644
--- a/target-mips/cpu.c
+++ b/target-mips/cpu.c
@@ -62,10 +62,11 @@
static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
{
- MIPSCPU *cpu = MIPS_CPU(dev);
+ CPUState *cs = CPU(dev);
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev);
- cpu_reset(CPU(cpu));
+ cpu_reset(cs);
+ qemu_init_vcpu(cs);
mcc->parent_realize(dev, errp);
}
@@ -100,10 +101,14 @@
cc->dump_state = mips_cpu_dump_state;
cc->set_pc = mips_cpu_set_pc;
cc->synchronize_from_tb = mips_cpu_synchronize_from_tb;
+ cc->gdb_read_register = mips_cpu_gdb_read_register;
+ cc->gdb_write_register = mips_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->do_unassigned_access = mips_cpu_unassigned_access;
cc->get_phys_page_debug = mips_cpu_get_phys_page_debug;
#endif
+
+ cc->gdb_num_core_regs = 73;
}
static const TypeInfo mips_cpu_type_info = {
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 4116de9..b088a25 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -390,7 +390,7 @@
temp = 0x7FFFFFFF;
set_DSPControl_overflow_flag(1, 21, env);
} else {
- temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1;
+ temp = ((int16_t)a * (int16_t)b) << 1;
}
return temp;
@@ -583,7 +583,7 @@
temp = (0x01ull << 63) - 1;
set_DSPControl_overflow_flag(1, 16 + ac, env);
} else {
- temp = ((uint64_t)a * (uint64_t)b) << 1;
+ temp = ((int64_t)(int32_t)a * (int32_t)b) << 1;
}
return temp;
@@ -622,7 +622,7 @@
temp = 0x7FFF0000;
set_DSPControl_overflow_flag(1, 21, env);
} else {
- temp = (a * b) << 1;
+ temp = ((int16_t)a * (int16_t)b) << 1;
temp = temp + 0x00008000;
}
@@ -648,16 +648,22 @@
static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a,
CPUMIPSState *env)
{
- int64_t temp;
+ uint16_t temp;
- temp = (int32_t)a + 0x00008000;
- if (a > (int)0x7fff8000) {
- temp = 0x7FFFFFFF;
+ /*
+ * The value 0x00008000 will be added to the input Q31 value, and the code
+ * needs to check if the addition causes an overflow. Since a positive value
+ * is added, overflow can happen in one direction only.
+ */
+ if (a > 0x7FFF7FFF) {
+ temp = 0x7FFF;
set_DSPControl_overflow_flag(1, 22, env);
+ } else {
+ temp = ((a + 0x8000) >> 16) & 0xFFFF;
}
- return (temp >> 16) & 0xFFFF;
+ return temp;
}
static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
diff --git a/target-mips/gdbstub.c b/target-mips/gdbstub.c
new file mode 100644
index 0000000..5b72d58
--- /dev/null
+++ b/target-mips/gdbstub.c
@@ -0,0 +1,155 @@
+/*
+ * MIPS gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ MIPSCPU *cpu = MIPS_CPU(cs);
+ CPUMIPSState *env = &cpu->env;
+
+ if (n < 32) {
+ return gdb_get_regl(mem_buf, env->active_tc.gpr[n]);
+ }
+ if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+ if (n >= 38 && n < 70) {
+ if (env->CP0_Status & (1 << CP0St_FR)) {
+ return gdb_get_regl(mem_buf,
+ env->active_fpu.fpr[n - 38].d);
+ } else {
+ return gdb_get_regl(mem_buf,
+ env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]);
+ }
+ }
+ switch (n) {
+ case 70:
+ return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr31);
+ case 71:
+ return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr0);
+ }
+ }
+ switch (n) {
+ case 32:
+ return gdb_get_regl(mem_buf, (int32_t)env->CP0_Status);
+ case 33:
+ return gdb_get_regl(mem_buf, env->active_tc.LO[0]);
+ case 34:
+ return gdb_get_regl(mem_buf, env->active_tc.HI[0]);
+ case 35:
+ return gdb_get_regl(mem_buf, env->CP0_BadVAddr);
+ case 36:
+ return gdb_get_regl(mem_buf, (int32_t)env->CP0_Cause);
+ case 37:
+ return gdb_get_regl(mem_buf, env->active_tc.PC |
+ !!(env->hflags & MIPS_HFLAG_M16));
+ case 72:
+ return gdb_get_regl(mem_buf, 0); /* fp */
+ case 89:
+ return gdb_get_regl(mem_buf, (int32_t)env->CP0_PRid);
+ }
+ if (n >= 73 && n <= 88) {
+ /* 16 embedded regs. */
+ return gdb_get_regl(mem_buf, 0);
+ }
+
+ return 0;
+}
+
+/* convert MIPS rounding mode in FCR31 to IEEE library */
+static unsigned int ieee_rm[] = {
+ float_round_nearest_even,
+ float_round_to_zero,
+ float_round_up,
+ float_round_down
+};
+#define RESTORE_ROUNDING_MODE \
+ set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], \
+ &env->active_fpu.fp_status)
+
+int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ MIPSCPU *cpu = MIPS_CPU(cs);
+ CPUMIPSState *env = &cpu->env;
+ target_ulong tmp;
+
+ tmp = ldtul_p(mem_buf);
+
+ if (n < 32) {
+ env->active_tc.gpr[n] = tmp;
+ return sizeof(target_ulong);
+ }
+ if (env->CP0_Config1 & (1 << CP0C1_FP)
+ && n >= 38 && n < 73) {
+ if (n < 70) {
+ if (env->CP0_Status & (1 << CP0St_FR)) {
+ env->active_fpu.fpr[n - 38].d = tmp;
+ } else {
+ env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp;
+ }
+ }
+ switch (n) {
+ case 70:
+ env->active_fpu.fcr31 = tmp & 0xFF83FFFF;
+ /* set rounding mode */
+ RESTORE_ROUNDING_MODE;
+ break;
+ case 71:
+ env->active_fpu.fcr0 = tmp;
+ break;
+ }
+ return sizeof(target_ulong);
+ }
+ switch (n) {
+ case 32:
+ env->CP0_Status = tmp;
+ break;
+ case 33:
+ env->active_tc.LO[0] = tmp;
+ break;
+ case 34:
+ env->active_tc.HI[0] = tmp;
+ break;
+ case 35:
+ env->CP0_BadVAddr = tmp;
+ break;
+ case 36:
+ env->CP0_Cause = tmp;
+ break;
+ case 37:
+ env->active_tc.PC = tmp & ~(target_ulong)1;
+ if (tmp & 1) {
+ env->hflags |= MIPS_HFLAG_M16;
+ } else {
+ env->hflags &= ~(MIPS_HFLAG_M16);
+ }
+ break;
+ case 72: /* fp, ignored */
+ break;
+ default:
+ if (n > 89) {
+ return 0;
+ }
+ /* Other registers are readonly. Ignore writes. */
+ break;
+ }
+
+ return sizeof(target_ulong);
+}
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 6feef7b..33e0e88 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -193,7 +193,7 @@
}
}
#if 0
- qemu_log(TARGET_FMT_lx " %d %d => " TARGET_FMT_lx " %d (%d)\n",
+ qemu_log(TARGET_FMT_lx " %d %d => %" HWADDR_PRIx " %d (%d)\n",
address, rw, access_type, *physical, *prot, ret);
#endif
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 5cf1c3f..b828375 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1735,7 +1735,6 @@
void helper_fork(target_ulong arg1, target_ulong arg2)
{
// arg1 = rt, arg2 = rs
- arg1 = 0;
// TODO: store to TC register
}
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 877f8df..e2eb908 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -9571,8 +9571,7 @@
}
#endif
-static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
- int *is_branch)
+static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
{
int extend = cpu_lduw_code(env, ctx->pc + 2);
int op, rx, ry, funct, sa;
@@ -9763,8 +9762,7 @@
return 4;
}
-static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
- int *is_branch)
+static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
{
int rx, ry;
int sa;
@@ -9807,7 +9805,6 @@
op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
gen_compute_branch(ctx, op, 4, rx, ry, offset);
n_bytes = 4;
- *is_branch = 1;
break;
case M16_OPC_BEQZ:
gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
@@ -10046,9 +10043,6 @@
}
gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
- if (!nd) {
- *is_branch = 1;
- }
}
break;
case RR_SDBBP:
@@ -10193,7 +10187,7 @@
}
break;
case M16_OPC_EXTEND:
- decode_extended_mips16_opc(env, ctx, is_branch);
+ decode_extended_mips16_opc(env, ctx);
n_bytes = 4;
break;
#if defined(TARGET_MIPS64)
@@ -10802,7 +10796,7 @@
}
-static void gen_pool16c_insn(DisasContext *ctx, int *is_branch)
+static void gen_pool16c_insn(DisasContext *ctx)
{
int rd = mmreg((ctx->opcode >> 3) & 0x7);
int rs = mmreg(ctx->opcode & 0x7);
@@ -10864,7 +10858,6 @@
gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
}
- *is_branch = 1;
break;
case JRC16 + 0:
case JRC16 + 1:
@@ -10889,7 +10882,6 @@
gen_compute_branch(ctx, opc, 2, reg, 31, 0);
}
- *is_branch = 1;
break;
case MFHI16 + 0:
case MFHI16 + 1:
@@ -11020,8 +11012,7 @@
tcg_temp_free(t1);
}
-static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
- int *is_branch)
+static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
{
int extension = (ctx->opcode >> 6) & 0x3f;
int minor = (ctx->opcode >> 12) & 0xf;
@@ -11070,6 +11061,36 @@
}
break;
#endif
+ case 0x2a:
+ switch (minor & 3) {
+ case MADD_ACC:
+ gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
+ break;
+ case MADDU_ACC:
+ gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
+ break;
+ case MSUB_ACC:
+ gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
+ break;
+ case MSUBU_ACC:
+ gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
+ break;
+ default:
+ goto pool32axf_invalid;
+ }
+ break;
+ case 0x32:
+ switch (minor & 3) {
+ case MULT_ACC:
+ gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
+ break;
+ case MULTU_ACC:
+ gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
+ break;
+ default:
+ goto pool32axf_invalid;
+ }
+ break;
case 0x2c:
switch (minor) {
case SEB:
@@ -11122,7 +11143,7 @@
mips32_op = OPC_MSUBU;
do_mul:
check_insn(ctx, ISA_MIPS32);
- gen_muldiv(ctx, mips32_op, (ctx->opcode >> 14) & 3, rs, rt);
+ gen_muldiv(ctx, mips32_op, 0, rs, rt);
break;
default:
goto pool32axf_invalid;
@@ -11147,12 +11168,10 @@
case JALR:
case JALR_HB:
gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
- *is_branch = 1;
break;
case JALRS:
case JALRS_HB:
gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
- *is_branch = 1;
break;
default:
goto pool32axf_invalid;
@@ -11258,24 +11277,42 @@
goto pool32axf_invalid;
}
break;
- case 0x35:
+ case 0x01:
switch (minor & 3) {
- case MFHI32:
+ case MFHI_ACC:
gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
break;
- case MFLO32:
+ case MFLO_ACC:
gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
break;
- case MTHI32:
+ case MTHI_ACC:
gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
break;
- case MTLO32:
+ case MTLO_ACC:
gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
break;
default:
goto pool32axf_invalid;
}
break;
+ case 0x35:
+ switch (minor) {
+ case MFHI32:
+ gen_HILO(ctx, OPC_MFHI, 0, rs);
+ break;
+ case MFLO32:
+ gen_HILO(ctx, OPC_MFLO, 0, rs);
+ break;
+ case MTHI32:
+ gen_HILO(ctx, OPC_MTHI, 0, rs);
+ break;
+ case MTLO32:
+ gen_HILO(ctx, OPC_MTLO, 0, rs);
+ break;
+ default:
+ goto pool32axf_invalid;
+ }
+ break;
default:
pool32axf_invalid:
MIPS_INVAL("pool32axf");
@@ -11551,7 +11588,7 @@
}
static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
- uint16_t insn_hw1, int *is_branch)
+ uint16_t insn_hw1)
{
int32_t offset;
uint16_t insn;
@@ -11685,7 +11722,7 @@
gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
return;
case POOL32AXF:
- gen_pool32axf(env, ctx, rt, rs, is_branch);
+ gen_pool32axf(env, ctx, rt, rs);
break;
case 0x07:
generate_exception(ctx, EXCP_BREAK);
@@ -12048,7 +12085,6 @@
mips32_op = OPC_BGTZ;
do_branch:
gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
- *is_branch = 1;
break;
/* Traps */
@@ -12109,7 +12145,6 @@
do_cp1branch:
gen_compute_branch1(ctx, mips32_op,
(ctx->opcode >> 18) & 0x7, imm << 1);
- *is_branch = 1;
break;
case BPOSGE64:
case BPOSGE32:
@@ -12216,30 +12251,24 @@
case JALX32:
offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
- *is_branch = 1;
break;
case JALS32:
offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
- *is_branch = 1;
break;
case BEQ32:
gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
- *is_branch = 1;
break;
case BNE32:
gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
- *is_branch = 1;
break;
case J32:
gen_compute_branch(ctx, OPC_J, 4, rt, rs,
(int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
- *is_branch = 1;
break;
case JAL32:
gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
(int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
- *is_branch = 1;
break;
/* Floating point (COP1) */
case LWC132:
@@ -12309,7 +12338,7 @@
}
}
-static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
+static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
{
uint32_t op;
@@ -12442,7 +12471,7 @@
}
break;
case POOL16C:
- gen_pool16c_insn(ctx, is_branch);
+ gen_pool16c_insn(ctx);
break;
case LWGP16:
{
@@ -12582,14 +12611,12 @@
case B16:
gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
SIMM(ctx->opcode, 0, 10) << 1);
- *is_branch = 1;
break;
case BNEZ16:
case BEQZ16:
gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
mmreg(uMIPS_RD(ctx->opcode)),
0, SIMM(ctx->opcode, 0, 7) << 1);
- *is_branch = 1;
break;
case LI16:
{
@@ -12610,7 +12637,7 @@
generate_exception(ctx, EXCP_RI);
break;
default:
- decode_micromips32_opc (env, ctx, op, is_branch);
+ decode_micromips32_opc (env, ctx, op);
return 4;
}
@@ -14346,7 +14373,7 @@
/* End MIPSDSP functions. */
-static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
+static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
{
int32_t offset;
int rs, rt, rd, sa;
@@ -14460,7 +14487,6 @@
break;
case OPC_JR ... OPC_JALR:
gen_compute_branch(ctx, op1, 4, rs, rd, sa);
- *is_branch = 1;
break;
case OPC_TGE ... OPC_TEQ: /* Traps */
case OPC_TNE:
@@ -15227,7 +15253,6 @@
case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
case OPC_BLTZAL ... OPC_BGEZALL:
gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
- *is_branch = 1;
break;
case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
case OPC_TNEI:
@@ -15243,7 +15268,6 @@
#endif
check_dsp(ctx);
gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
- *is_branch = 1;
break;
default: /* Invalid */
MIPS_INVAL("regimm");
@@ -15355,12 +15379,10 @@
case OPC_J ... OPC_JAL: /* Jump */
offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
gen_compute_branch(ctx, op, 4, rs, rt, offset);
- *is_branch = 1;
break;
case OPC_BEQ ... OPC_BGTZ: /* Branch */
case OPC_BEQL ... OPC_BGTZL:
gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
- *is_branch = 1;
break;
case OPC_LB ... OPC_LWR: /* Load and stores */
case OPC_LL:
@@ -15420,7 +15442,6 @@
case OPC_BC1:
gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
(rt >> 2) & 0x7, imm << 2);
- *is_branch = 1;
break;
case OPC_S_FMT:
case OPC_D_FMT:
@@ -15527,7 +15548,6 @@
check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
gen_compute_branch(ctx, op, 4, rs, rt, offset);
- *is_branch = 1;
break;
case OPC_MDMX:
check_insn(ctx, ASE_MDMX);
@@ -15553,7 +15573,7 @@
int num_insns;
int max_insns;
int insn_bytes;
- int is_branch;
+ int is_delay;
if (search_pc)
qemu_log("search pc %d\n", search_pc);
@@ -15611,23 +15631,23 @@
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
- is_branch = 0;
+ is_delay = ctx.hflags & MIPS_HFLAG_BMASK;
if (!(ctx.hflags & MIPS_HFLAG_M16)) {
ctx.opcode = cpu_ldl_code(env, ctx.pc);
insn_bytes = 4;
- decode_opc(env, &ctx, &is_branch);
+ decode_opc(env, &ctx);
} else if (ctx.insn_flags & ASE_MICROMIPS) {
ctx.opcode = cpu_lduw_code(env, ctx.pc);
- insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
+ insn_bytes = decode_micromips_opc(env, &ctx);
} else if (ctx.insn_flags & ASE_MIPS16) {
ctx.opcode = cpu_lduw_code(env, ctx.pc);
- insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
+ insn_bytes = decode_mips16_opc(env, &ctx);
} else {
generate_exception(&ctx, EXCP_RI);
ctx.bstate = BS_STOP;
break;
}
- if (!is_branch) {
+ if (is_delay) {
handle_delay_slot(&ctx, insn_bytes);
}
ctx.pc += insn_bytes;
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 7cf238f..c45b1b2 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -274,14 +274,13 @@
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
(1 << CP0C1_CA),
.CP0_Config2 = MIPS_CONFIG2,
- .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_MT),
+ .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_VInt) | (1 << CP0C3_MT) |
+ (1 << CP0C3_DSPP),
.CP0_LLAddr_rw_bitmask = 0,
.CP0_LLAddr_shift = 0,
.SYNCI_Step = 32,
.CCRes = 2,
- /* No DSP implemented. */
- .CP0_Status_rw_bitmask = 0x3678FF1F,
- /* No DSP implemented. */
+ .CP0_Status_rw_bitmask = 0x3778FF1F,
.CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) |
(1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) |
(0 << CP0TCSt_TMX) | (1 << CP0TCSt_DT) |
diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c
index 6550be5..d97a091 100644
--- a/target-moxie/cpu.c
+++ b/target-moxie/cpu.c
@@ -45,10 +45,11 @@
static void moxie_cpu_realizefn(DeviceState *dev, Error **errp)
{
- MoxieCPU *cpu = MOXIE_CPU(dev);
+ CPUState *cs = CPU(dev);
MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(dev);
- cpu_reset(CPU(cpu));
+ qemu_init_vcpu(cs);
+ cpu_reset(cs);
mcc->parent_realize(dev, errp);
}
diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
index 44dc539..397d016 100644
--- a/target-openrisc/Makefile.objs
+++ b/target-openrisc/Makefile.objs
@@ -2,3 +2,4 @@
obj-y += cpu.o exception.o interrupt.o mmu.o translate.o
obj-y += exception_helper.o fpu_helper.o int_helper.o \
interrupt_helper.o mmu_helper.o sys_helper.o
+obj-y += gdbstub.o
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
index 3da5a7a..075f00a 100644
--- a/target-openrisc/cpu.c
+++ b/target-openrisc/cpu.c
@@ -66,10 +66,11 @@
static void openrisc_cpu_realizefn(DeviceState *dev, Error **errp)
{
- OpenRISCCPU *cpu = OPENRISC_CPU(dev);
+ CPUState *cs = CPU(dev);
OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(dev);
- cpu_reset(CPU(cpu));
+ qemu_init_vcpu(cs);
+ cpu_reset(cs);
occ->parent_realize(dev, errp);
}
@@ -106,6 +107,7 @@
typename = g_strdup_printf("%s-" TYPE_OPENRISC_CPU, cpu_model);
oc = object_class_by_name(typename);
+ g_free(typename);
if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_OPENRISC_CPU) ||
object_class_is_abstract(oc))) {
return NULL;
@@ -154,10 +156,13 @@
cc->do_interrupt = openrisc_cpu_do_interrupt;
cc->dump_state = openrisc_cpu_dump_state;
cc->set_pc = openrisc_cpu_set_pc;
+ cc->gdb_read_register = openrisc_cpu_gdb_read_register;
+ cc->gdb_write_register = openrisc_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_openrisc_cpu;
#endif
+ cc->gdb_num_core_regs = 32 + 3;
}
static void cpu_register(const OpenRISCCPUInfo *info)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 3ddb767..8fd0bc0 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -350,6 +350,8 @@
void openrisc_cpu_dump_state(CPUState *cpu, FILE *f,
fprintf_function cpu_fprintf, int flags);
hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int openrisc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void openrisc_translate_init(void);
int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
target_ulong address,
diff --git a/target-openrisc/gdbstub.c b/target-openrisc/gdbstub.c
new file mode 100644
index 0000000..18bcc46
--- /dev/null
+++ b/target-openrisc/gdbstub.c
@@ -0,0 +1,83 @@
+/*
+ * OpenRISC gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+int openrisc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ OpenRISCCPU *cpu = OPENRISC_CPU(cs);
+ CPUOpenRISCState *env = &cpu->env;
+
+ if (n < 32) {
+ return gdb_get_reg32(mem_buf, env->gpr[n]);
+ } else {
+ switch (n) {
+ case 32: /* PPC */
+ return gdb_get_reg32(mem_buf, env->ppc);
+
+ case 33: /* NPC */
+ return gdb_get_reg32(mem_buf, env->npc);
+
+ case 34: /* SR */
+ return gdb_get_reg32(mem_buf, env->sr);
+
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+int openrisc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ OpenRISCCPU *cpu = OPENRISC_CPU(cs);
+ CPUClass *cc = CPU_GET_CLASS(cs);
+ CPUOpenRISCState *env = &cpu->env;
+ uint32_t tmp;
+
+ if (n > cc->gdb_num_core_regs) {
+ return 0;
+ }
+
+ tmp = ldl_p(mem_buf);
+
+ if (n < 32) {
+ env->gpr[n] = tmp;
+ } else {
+ switch (n) {
+ case 32: /* PPC */
+ env->ppc = tmp;
+ break;
+
+ case 33: /* NPC */
+ env->npc = tmp;
+ break;
+
+ case 34: /* SR */
+ env->sr = tmp;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return 4;
+}
diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs
index 6e78cb3..f72e399 100644
--- a/target-ppc/Makefile.objs
+++ b/target-ppc/Makefile.objs
@@ -13,3 +13,4 @@
obj-y += misc_helper.o
obj-y += mem_helper.o
obj-$(CONFIG_USER_ONLY) += user_only_helper.o
+obj-y += gdbstub.o
diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c
index 9578ed8..8dea560 100644
--- a/target-ppc/cpu-models.c
+++ b/target-ppc/cpu-models.c
@@ -1120,15 +1120,11 @@
#if defined(TODO)
POWERPC_DEF("POWER5", CPU_POWERPC_POWER5, POWER5,
"POWER5")
- POWERPC_DEF("POWER5gr", CPU_POWERPC_POWER5GR, POWER5,
- "POWER5GR")
#endif
-#if defined(TODO)
POWERPC_DEF("POWER5+", CPU_POWERPC_POWER5P, POWER5P,
"POWER5+")
- POWERPC_DEF("POWER5gs", CPU_POWERPC_POWER5GS, POWER5P,
- "POWER5GS")
-#endif
+ POWERPC_DEF("POWER5+_v2.1", CPU_POWERPC_POWER5P_v21, POWER5P,
+ "POWER5+ v2.1")
#if defined(TODO)
POWERPC_DEF("POWER6", CPU_POWERPC_POWER6, POWER6,
"POWER6")
@@ -1143,6 +1139,8 @@
"POWER7 v2.1")
POWERPC_DEF("POWER7_v2.3", CPU_POWERPC_POWER7_v23, POWER7,
"POWER7 v2.3")
+ POWERPC_DEF("POWER7+_v2.1", CPU_POWERPC_POWER7P_v21, POWER7,
+ "POWER7+ v2.1")
POWERPC_DEF("POWER8_v1.0", CPU_POWERPC_POWER8_v10, POWER8,
"POWER8 v1.0")
POWERPC_DEF("970", CPU_POWERPC_970, 970,
@@ -1389,7 +1387,10 @@
{ "Boxer", "POWER3" },
{ "Dino", "POWER3" },
{ "POWER3+", "631" },
+ { "POWER5gr", "POWER5" },
+ { "POWER5gs", "POWER5+" },
{ "POWER7", "POWER7_v2.3" },
+ { "POWER7+", "POWER7+_v2.1" },
{ "POWER8", "POWER8_v1.0" },
{ "970fx", "970fx_v3.1" },
{ "970mp", "970mp_v1.1" },
diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h
index 01e488f..d9145d1 100644
--- a/target-ppc/cpu-models.h
+++ b/target-ppc/cpu-models.h
@@ -547,15 +547,15 @@
CPU_POWERPC_POWER4P = 0x00380000,
/* XXX: missing 0x003A0201 */
CPU_POWERPC_POWER5 = 0x003A0203,
-#define CPU_POWERPC_POWER5GR CPU_POWERPC_POWER5
CPU_POWERPC_POWER5P = 0x003B0000,
-#define CPU_POWERPC_POWER5GS CPU_POWERPC_POWER5P
+ CPU_POWERPC_POWER5P_v21 = 0x003B0201,
CPU_POWERPC_POWER6 = 0x003E0000,
CPU_POWERPC_POWER6_5 = 0x0F000001, /* POWER6 in POWER5 mode */
CPU_POWERPC_POWER6A = 0x0F000002,
CPU_POWERPC_POWER7_v20 = 0x003F0200,
CPU_POWERPC_POWER7_v21 = 0x003F0201,
CPU_POWERPC_POWER7_v23 = 0x003F0203,
+ CPU_POWERPC_POWER7P_v21 = 0x004A0201,
CPU_POWERPC_POWER8_v10 = 0x004B0100,
CPU_POWERPC_970 = 0x00390202,
CPU_POWERPC_970FX_v10 = 0x00391100,
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index 3341c51..f3c710a 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -106,5 +106,11 @@
void ppc_cpu_dump_statistics(CPUState *cpu, FILE *f,
fprintf_function cpu_fprintf, int flags);
hwaddr ppc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int ppc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int ppc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+
+#ifndef CONFIG_USER_ONLY
+extern const struct VMStateDescription vmstate_ppc_cpu;
+#endif
#endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 6f51e1f..711db08 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -948,7 +948,7 @@
#if defined(TARGET_PPC64)
/* PowerPC 64 SLB area */
ppc_slb_t slb[64];
- int slb_nr;
+ int32_t slb_nr;
#endif
/* segment registers */
hwaddr htab_base;
@@ -957,11 +957,11 @@
/* externally stored hash table */
uint8_t *external_htab;
/* BATs */
- int nb_BATs;
+ uint32_t nb_BATs;
target_ulong DBAT[2][8];
target_ulong IBAT[2][8];
/* PowerPC TLB registers (for 4xx, e500 and 60x software driven TLBs) */
- int nb_tlb; /* Total number of TLB */
+ int32_t nb_tlb; /* Total number of TLB */
int tlb_per_way; /* Speed-up helper: used to avoid divisions at run time */
int nb_ways; /* Number of ways in the TLB set */
int last_way; /* Last used way used to allocate TLB in a LRU way */
@@ -1176,8 +1176,6 @@
#define cpu_signal_handler cpu_ppc_signal_handler
#define cpu_list ppc_cpu_list
-#define CPU_SAVE_VERSION 4
-
/* MMU modes definitions */
#define MMU_MODE0_SUFFIX _user
#define MMU_MODE1_SUFFIX _kernel
diff --git a/target-ppc/gdbstub.c b/target-ppc/gdbstub.c
new file mode 100644
index 0000000..1c91090
--- /dev/null
+++ b/target-ppc/gdbstub.c
@@ -0,0 +1,131 @@
+/*
+ * PowerPC gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+/* Old gdb always expects FP registers. Newer (xml-aware) gdb only
+ * expects whatever the target description contains. Due to a
+ * historical mishap the FP registers appear in between core integer
+ * regs and PC, MSR, CR, and so forth. We hack round this by giving the
+ * FP regs zero size when talking to a newer gdb.
+ */
+
+int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+
+ if (n < 32) {
+ /* gprs */
+ return gdb_get_regl(mem_buf, env->gpr[n]);
+ } else if (n < 64) {
+ /* fprs */
+ if (gdb_has_xml) {
+ return 0;
+ }
+ stfq_p(mem_buf, env->fpr[n-32]);
+ return 8;
+ } else {
+ switch (n) {
+ case 64:
+ return gdb_get_regl(mem_buf, env->nip);
+ case 65:
+ return gdb_get_regl(mem_buf, env->msr);
+ case 66:
+ {
+ uint32_t cr = 0;
+ int i;
+ for (i = 0; i < 8; i++) {
+ cr |= env->crf[i] << (32 - ((i + 1) * 4));
+ }
+ return gdb_get_reg32(mem_buf, cr);
+ }
+ case 67:
+ return gdb_get_regl(mem_buf, env->lr);
+ case 68:
+ return gdb_get_regl(mem_buf, env->ctr);
+ case 69:
+ return gdb_get_regl(mem_buf, env->xer);
+ case 70:
+ {
+ if (gdb_has_xml) {
+ return 0;
+ }
+ return gdb_get_reg32(mem_buf, env->fpscr);
+ }
+ }
+ }
+ return 0;
+}
+
+int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ CPUPPCState *env = &cpu->env;
+
+ if (n < 32) {
+ /* gprs */
+ env->gpr[n] = ldtul_p(mem_buf);
+ return sizeof(target_ulong);
+ } else if (n < 64) {
+ /* fprs */
+ if (gdb_has_xml) {
+ return 0;
+ }
+ env->fpr[n-32] = ldfq_p(mem_buf);
+ return 8;
+ } else {
+ switch (n) {
+ case 64:
+ env->nip = ldtul_p(mem_buf);
+ return sizeof(target_ulong);
+ case 65:
+ ppc_store_msr(env, ldtul_p(mem_buf));
+ return sizeof(target_ulong);
+ case 66:
+ {
+ uint32_t cr = ldl_p(mem_buf);
+ int i;
+ for (i = 0; i < 8; i++) {
+ env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF;
+ }
+ return 4;
+ }
+ case 67:
+ env->lr = ldtul_p(mem_buf);
+ return sizeof(target_ulong);
+ case 68:
+ env->ctr = ldtul_p(mem_buf);
+ return sizeof(target_ulong);
+ case 69:
+ env->xer = ldtul_p(mem_buf);
+ return sizeof(target_ulong);
+ case 70:
+ /* fpscr */
+ if (gdb_has_xml) {
+ return 0;
+ }
+ store_fpscr(env, ldtul_p(mem_buf), 0xffffffff);
+ return sizeof(target_ulong);
+ }
+ }
+ return 0;
+}
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index b0099e1..8a196c6 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -40,10 +40,10 @@
//#define DEBUG_KVM
#ifdef DEBUG_KVM
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
#else
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { } while (0)
#endif
@@ -65,6 +65,7 @@
static int cap_epr;
static int cap_ppc_watchdog;
static int cap_papr;
+static int cap_htab_fd;
/* XXX We have a race condition where we actually have a level triggered
* interrupt, but the infrastructure can't expose that yet, so the guest
@@ -101,6 +102,7 @@
cap_ppc_watchdog = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_WATCHDOG);
/* Note: we don't set cap_papr here, because this capability is
* only activated after this by kvmppc_set_papr() */
+ cap_htab_fd = kvm_check_extension(s, KVM_CAP_PPC_HTAB_FD);
if (!cap_interrupt_level) {
fprintf(stderr, "KVM: Couldn't find level irq capability. Expect the "
@@ -417,7 +419,7 @@
return ret;
}
- idle_timer = qemu_new_timer_ns(vm_clock, kvm_kick_cpu, cpu);
+ idle_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, kvm_kick_cpu, cpu);
/* Some targets support access to KVM's guest TLB. */
switch (cenv->mmu_model) {
@@ -548,7 +550,7 @@
reg.addr = (uintptr_t)&fpscr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to set FPSCR to KVM: %s\n", strerror(errno));
+ DPRINTF("Unable to set FPSCR to KVM: %s\n", strerror(errno));
return ret;
}
@@ -562,7 +564,7 @@
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to set %s%d to KVM: %s\n", vsx ? "VSR" : "FPR",
+ DPRINTF("Unable to set %s%d to KVM: %s\n", vsx ? "VSR" : "FPR",
i, strerror(errno));
return ret;
}
@@ -574,7 +576,7 @@
reg.addr = (uintptr_t)&env->vscr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to set VSCR to KVM: %s\n", strerror(errno));
+ DPRINTF("Unable to set VSCR to KVM: %s\n", strerror(errno));
return ret;
}
@@ -583,7 +585,7 @@
reg.addr = (uintptr_t)&env->avr[i];
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to set VR%d to KVM: %s\n", i, strerror(errno));
+ DPRINTF("Unable to set VR%d to KVM: %s\n", i, strerror(errno));
return ret;
}
}
@@ -608,7 +610,7 @@
reg.addr = (uintptr_t)&fpscr;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to get FPSCR from KVM: %s\n", strerror(errno));
+ DPRINTF("Unable to get FPSCR from KVM: %s\n", strerror(errno));
return ret;
} else {
env->fpscr = fpscr;
@@ -622,7 +624,7 @@
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to get %s%d from KVM: %s\n",
+ DPRINTF("Unable to get %s%d from KVM: %s\n",
vsx ? "VSR" : "FPR", i, strerror(errno));
return ret;
} else {
@@ -639,7 +641,7 @@
reg.addr = (uintptr_t)&env->vscr;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to get VSCR from KVM: %s\n", strerror(errno));
+ DPRINTF("Unable to get VSCR from KVM: %s\n", strerror(errno));
return ret;
}
@@ -648,7 +650,7 @@
reg.addr = (uintptr_t)&env->avr[i];
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to get VR%d from KVM: %s\n",
+ DPRINTF("Unable to get VR%d from KVM: %s\n",
i, strerror(errno));
return ret;
}
@@ -670,7 +672,7 @@
reg.addr = (uintptr_t)&env->vpa_addr;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to get VPA address from KVM: %s\n", strerror(errno));
+ DPRINTF("Unable to get VPA address from KVM: %s\n", strerror(errno));
return ret;
}
@@ -680,7 +682,7 @@
reg.addr = (uintptr_t)&env->slb_shadow_addr;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to get SLB shadow state from KVM: %s\n",
+ DPRINTF("Unable to get SLB shadow state from KVM: %s\n",
strerror(errno));
return ret;
}
@@ -690,7 +692,7 @@
reg.addr = (uintptr_t)&env->dtl_addr;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to get dispatch trace log state from KVM: %s\n",
+ DPRINTF("Unable to get dispatch trace log state from KVM: %s\n",
strerror(errno));
return ret;
}
@@ -716,7 +718,7 @@
reg.addr = (uintptr_t)&env->vpa_addr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to set VPA address to KVM: %s\n", strerror(errno));
+ DPRINTF("Unable to set VPA address to KVM: %s\n", strerror(errno));
return ret;
}
}
@@ -727,7 +729,7 @@
reg.addr = (uintptr_t)&env->slb_shadow_addr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to set SLB shadow state to KVM: %s\n", strerror(errno));
+ DPRINTF("Unable to set SLB shadow state to KVM: %s\n", strerror(errno));
return ret;
}
@@ -736,7 +738,7 @@
reg.addr = (uintptr_t)&env->dtl_addr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to set dispatch trace log state to KVM: %s\n",
+ DPRINTF("Unable to set dispatch trace log state to KVM: %s\n",
strerror(errno));
return ret;
}
@@ -746,7 +748,7 @@
reg.addr = (uintptr_t)&env->vpa_addr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
if (ret < 0) {
- dprintf("Unable to set VPA address to KVM: %s\n", strerror(errno));
+ DPRINTF("Unable to set VPA address to KVM: %s\n", strerror(errno));
return ret;
}
}
@@ -864,7 +866,7 @@
#ifdef TARGET_PPC64
if (cap_papr) {
if (kvm_put_vpa(cs) < 0) {
- dprintf("Warning: Unable to set VPA information to KVM\n");
+ DPRINTF("Warning: Unable to set VPA information to KVM\n");
}
}
#endif /* TARGET_PPC64 */
@@ -1073,7 +1075,7 @@
#ifdef TARGET_PPC64
if (cap_papr) {
if (kvm_get_vpa(cs) < 0) {
- dprintf("Warning: Unable to get VPA information from KVM\n");
+ DPRINTF("Warning: Unable to get VPA information from KVM\n");
}
}
#endif
@@ -1127,14 +1129,14 @@
*/
irq = KVM_INTERRUPT_SET;
- dprintf("injected interrupt %d\n", irq);
+ DPRINTF("injected interrupt %d\n", irq);
r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &irq);
if (r < 0) {
printf("cpu %d fail inject %x\n", cs->cpu_index, irq);
}
/* Always wake up soon in case the interrupt was level based */
- qemu_mod_timer(idle_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(idle_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
(get_ticks_per_sec() / 50));
}
@@ -1191,20 +1193,20 @@
switch (run->exit_reason) {
case KVM_EXIT_DCR:
if (run->dcr.is_write) {
- dprintf("handle dcr write\n");
+ DPRINTF("handle dcr write\n");
ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data);
} else {
- dprintf("handle dcr read\n");
+ DPRINTF("handle dcr read\n");
ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data);
}
break;
case KVM_EXIT_HLT:
- dprintf("handle halt\n");
+ DPRINTF("handle halt\n");
ret = kvmppc_handle_halt(cpu);
break;
#if defined(TARGET_PPC64)
case KVM_EXIT_PAPR_HCALL:
- dprintf("handle PAPR hypercall\n");
+ DPRINTF("handle PAPR hypercall\n");
run->papr_hcall.ret = spapr_hypercall(cpu,
run->papr_hcall.nr,
run->papr_hcall.args);
@@ -1212,12 +1214,12 @@
break;
#endif
case KVM_EXIT_EPR:
- dprintf("handle epr\n");
+ DPRINTF("handle epr\n");
run->epr.epr = ldl_phys(env->mpic_iack);
ret = 0;
break;
case KVM_EXIT_WATCHDOG:
- dprintf("handle watchdog expiry\n");
+ DPRINTF("handle watchdog expiry\n");
watchdog_perform_action();
ret = 0;
break;
@@ -1626,7 +1628,7 @@
return NULL;
}
- len = (window_size / SPAPR_TCE_PAGE_SIZE) * sizeof(sPAPRTCE);
+ len = (window_size / SPAPR_TCE_PAGE_SIZE) * sizeof(uint64_t);
/* FIXME: round this up to page size */
table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
@@ -1649,7 +1651,7 @@
return -1;
}
- len = (window_size / SPAPR_TCE_PAGE_SIZE)*sizeof(sPAPRTCE);
+ len = (window_size / SPAPR_TCE_PAGE_SIZE)*sizeof(uint64_t);
if ((munmap(table, len) < 0) ||
(close(fd) < 0)) {
fprintf(stderr, "KVM: Unexpected error removing TCE table: %s",
@@ -1788,6 +1790,73 @@
}
+int kvmppc_get_htab_fd(bool write)
+{
+ struct kvm_get_htab_fd s = {
+ .flags = write ? KVM_GET_HTAB_WRITE : 0,
+ .start_index = 0,
+ };
+
+ if (!cap_htab_fd) {
+ fprintf(stderr, "KVM version doesn't support saving the hash table\n");
+ return -1;
+ }
+
+ return kvm_vm_ioctl(kvm_state, KVM_PPC_GET_HTAB_FD, &s);
+}
+
+int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns)
+{
+ int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
+ uint8_t buf[bufsize];
+ ssize_t rc;
+
+ do {
+ rc = read(fd, buf, bufsize);
+ if (rc < 0) {
+ fprintf(stderr, "Error reading data from KVM HTAB fd: %s\n",
+ strerror(errno));
+ return rc;
+ } else if (rc) {
+ /* Kernel already retuns data in BE format for the file */
+ qemu_put_buffer(f, buf, rc);
+ }
+ } while ((rc != 0)
+ && ((max_ns < 0)
+ || ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) < max_ns)));
+
+ return (rc == 0) ? 1 : 0;
+}
+
+int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index,
+ uint16_t n_valid, uint16_t n_invalid)
+{
+ struct kvm_get_htab_header *buf;
+ size_t chunksize = sizeof(*buf) + n_valid*HASH_PTE_SIZE_64;
+ ssize_t rc;
+
+ buf = alloca(chunksize);
+ /* This is KVM on ppc, so this is all big-endian */
+ buf->index = index;
+ buf->n_valid = n_valid;
+ buf->n_invalid = n_invalid;
+
+ qemu_get_buffer(f, (void *)(buf + 1), HASH_PTE_SIZE_64*n_valid);
+
+ rc = write(fd, buf, chunksize);
+ if (rc < 0) {
+ fprintf(stderr, "Error writing KVM hash table: %s\n",
+ strerror(errno));
+ return rc;
+ }
+ if (rc != chunksize) {
+ /* We should never get a short write on a single chunk */
+ fprintf(stderr, "Short write, restoring KVM hash table\n");
+ return -1;
+ }
+ return 0;
+}
+
bool kvm_arch_stop_on_emulation_error(CPUState *cpu)
{
return true;
diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c
index 1b192a8..9b83655 100644
--- a/target-ppc/kvm_ppc.c
+++ b/target-ppc/kvm_ppc.c
@@ -24,7 +24,7 @@
static void kvmppc_timer_hack(void *opaque)
{
qemu_notify_event();
- qemu_mod_timer(kvmppc_timer, qemu_get_clock_ns(vm_clock) + kvmppc_timer_rate);
+ timer_mod(kvmppc_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + kvmppc_timer_rate);
}
void kvmppc_init(void)
@@ -34,7 +34,7 @@
* run. So, until QEMU gains IO threads, we create this timer to ensure
* that the device model gets a chance to run. */
kvmppc_timer_rate = get_ticks_per_sec() / 10;
- kvmppc_timer = qemu_new_timer_ns(vm_clock, &kvmppc_timer_hack, NULL);
- qemu_mod_timer(kvmppc_timer, qemu_get_clock_ns(vm_clock) + kvmppc_timer_rate);
+ kvmppc_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &kvmppc_timer_hack, NULL);
+ timer_mod(kvmppc_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + kvmppc_timer_rate);
}
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 771cfbe..4ae7bf2 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -38,6 +38,10 @@
#endif /* !CONFIG_USER_ONLY */
int kvmppc_fixup_cpu(PowerPCCPU *cpu);
bool kvmppc_has_cap_epr(void);
+int kvmppc_get_htab_fd(bool write);
+int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns);
+int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index,
+ uint16_t n_valid, uint16_t n_invalid);
#else
@@ -159,6 +163,24 @@
{
return false;
}
+
+static inline int kvmppc_get_htab_fd(bool write)
+{
+ return -1;
+}
+
+static inline int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize,
+ int64_t max_ns)
+{
+ abort();
+}
+
+static inline int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index,
+ uint16_t n_valid, uint16_t n_invalid)
+{
+ abort();
+}
+
#endif
#ifndef CONFIG_KVM
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 2d10adb..12e1512 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -1,96 +1,12 @@
#include "hw/hw.h"
#include "hw/boards.h"
#include "sysemu/kvm.h"
+#include "helper_regs.h"
-void cpu_save(QEMUFile *f, void *opaque)
+static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
{
- CPUPPCState *env = (CPUPPCState *)opaque;
- unsigned int i, j;
- uint32_t fpscr;
- target_ulong xer;
-
- for (i = 0; i < 32; i++)
- qemu_put_betls(f, &env->gpr[i]);
-#if !defined(TARGET_PPC64)
- for (i = 0; i < 32; i++)
- qemu_put_betls(f, &env->gprh[i]);
-#endif
- qemu_put_betls(f, &env->lr);
- qemu_put_betls(f, &env->ctr);
- for (i = 0; i < 8; i++)
- qemu_put_be32s(f, &env->crf[i]);
- xer = cpu_read_xer(env);
- qemu_put_betls(f, &xer);
- qemu_put_betls(f, &env->reserve_addr);
- qemu_put_betls(f, &env->msr);
- for (i = 0; i < 4; i++)
- qemu_put_betls(f, &env->tgpr[i]);
- for (i = 0; i < 32; i++) {
- union {
- float64 d;
- uint64_t l;
- } u;
- u.d = env->fpr[i];
- qemu_put_be64(f, u.l);
- }
- fpscr = env->fpscr;
- qemu_put_be32s(f, &fpscr);
- qemu_put_sbe32s(f, &env->access_type);
-#if defined(TARGET_PPC64)
- qemu_put_betls(f, &env->spr[SPR_ASR]);
- qemu_put_sbe32s(f, &env->slb_nr);
-#endif
- qemu_put_betls(f, &env->spr[SPR_SDR1]);
- for (i = 0; i < 32; i++)
- qemu_put_betls(f, &env->sr[i]);
- for (i = 0; i < 2; i++)
- for (j = 0; j < 8; j++)
- qemu_put_betls(f, &env->DBAT[i][j]);
- for (i = 0; i < 2; i++)
- for (j = 0; j < 8; j++)
- qemu_put_betls(f, &env->IBAT[i][j]);
- qemu_put_sbe32s(f, &env->nb_tlb);
- qemu_put_sbe32s(f, &env->tlb_per_way);
- qemu_put_sbe32s(f, &env->nb_ways);
- qemu_put_sbe32s(f, &env->last_way);
- qemu_put_sbe32s(f, &env->id_tlbs);
- qemu_put_sbe32s(f, &env->nb_pids);
- if (env->tlb.tlb6) {
- // XXX assumes 6xx
- for (i = 0; i < env->nb_tlb; i++) {
- qemu_put_betls(f, &env->tlb.tlb6[i].pte0);
- qemu_put_betls(f, &env->tlb.tlb6[i].pte1);
- qemu_put_betls(f, &env->tlb.tlb6[i].EPN);
- }
- }
- for (i = 0; i < 4; i++)
- qemu_put_betls(f, &env->pb[i]);
- for (i = 0; i < 1024; i++)
- qemu_put_betls(f, &env->spr[i]);
- qemu_put_be32s(f, &env->vscr);
- qemu_put_be64s(f, &env->spe_acc);
- qemu_put_be32s(f, &env->spe_fscr);
- qemu_put_betls(f, &env->msr_mask);
- qemu_put_be32s(f, &env->flags);
- qemu_put_sbe32s(f, &env->error_code);
- qemu_put_be32s(f, &env->pending_interrupts);
- qemu_put_be32s(f, &env->irq_input_state);
- for (i = 0; i < POWERPC_EXCP_NB; i++)
- qemu_put_betls(f, &env->excp_vectors[i]);
- qemu_put_betls(f, &env->excp_prefix);
- qemu_put_betls(f, &env->ivor_mask);
- qemu_put_betls(f, &env->ivpr_mask);
- qemu_put_betls(f, &env->hreset_vector);
- qemu_put_betls(f, &env->nip);
- qemu_put_betls(f, &env->hflags);
- qemu_put_betls(f, &env->hflags_nmsr);
- qemu_put_sbe32s(f, &env->mmu_idx);
- qemu_put_sbe32(f, 0);
-}
-
-int cpu_load(QEMUFile *f, void *opaque, int version_id)
-{
- CPUPPCState *env = (CPUPPCState *)opaque;
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
unsigned int i, j;
target_ulong sdr1;
uint32_t fpscr;
@@ -177,3 +93,442 @@
return 0;
}
+
+static int get_avr(QEMUFile *f, void *pv, size_t size)
+{
+ ppc_avr_t *v = pv;
+
+ v->u64[0] = qemu_get_be64(f);
+ v->u64[1] = qemu_get_be64(f);
+
+ return 0;
+}
+
+static void put_avr(QEMUFile *f, void *pv, size_t size)
+{
+ ppc_avr_t *v = pv;
+
+ qemu_put_be64(f, v->u64[0]);
+ qemu_put_be64(f, v->u64[1]);
+}
+
+const VMStateInfo vmstate_info_avr = {
+ .name = "avr",
+ .get = get_avr,
+ .put = put_avr,
+};
+
+#define VMSTATE_AVR_ARRAY_V(_f, _s, _n, _v) \
+ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_avr, ppc_avr_t)
+
+#define VMSTATE_AVR_ARRAY(_f, _s, _n) \
+ VMSTATE_AVR_ARRAY_V(_f, _s, _n, 0)
+
+static void cpu_pre_save(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
+ int i;
+
+ env->spr[SPR_LR] = env->lr;
+ env->spr[SPR_CTR] = env->ctr;
+ env->spr[SPR_XER] = env->xer;
+#if defined(TARGET_PPC64)
+ env->spr[SPR_CFAR] = env->cfar;
+#endif
+ env->spr[SPR_BOOKE_SPEFSCR] = env->spe_fscr;
+
+ for (i = 0; (i < 4) && (i < env->nb_BATs); i++) {
+ env->spr[SPR_DBAT0U + 2*i] = env->DBAT[0][i];
+ env->spr[SPR_DBAT0U + 2*i + 1] = env->DBAT[1][i];
+ env->spr[SPR_IBAT0U + 2*i] = env->IBAT[0][i];
+ env->spr[SPR_IBAT0U + 2*i + 1] = env->IBAT[1][i];
+ }
+ for (i = 0; (i < 4) && ((i+4) < env->nb_BATs); i++) {
+ env->spr[SPR_DBAT4U + 2*i] = env->DBAT[0][i+4];
+ env->spr[SPR_DBAT4U + 2*i + 1] = env->DBAT[1][i+4];
+ env->spr[SPR_IBAT4U + 2*i] = env->IBAT[0][i+4];
+ env->spr[SPR_IBAT4U + 2*i + 1] = env->IBAT[1][i+4];
+ }
+}
+
+static int cpu_post_load(void *opaque, int version_id)
+{
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
+ int i;
+
+ env->lr = env->spr[SPR_LR];
+ env->ctr = env->spr[SPR_CTR];
+ env->xer = env->spr[SPR_XER];
+#if defined(TARGET_PPC64)
+ env->cfar = env->spr[SPR_CFAR];
+#endif
+ env->spe_fscr = env->spr[SPR_BOOKE_SPEFSCR];
+
+ for (i = 0; (i < 4) && (i < env->nb_BATs); i++) {
+ env->DBAT[0][i] = env->spr[SPR_DBAT0U + 2*i];
+ env->DBAT[1][i] = env->spr[SPR_DBAT0U + 2*i + 1];
+ env->IBAT[0][i] = env->spr[SPR_IBAT0U + 2*i];
+ env->IBAT[1][i] = env->spr[SPR_IBAT0U + 2*i + 1];
+ }
+ for (i = 0; (i < 4) && ((i+4) < env->nb_BATs); i++) {
+ env->DBAT[0][i+4] = env->spr[SPR_DBAT4U + 2*i];
+ env->DBAT[1][i+4] = env->spr[SPR_DBAT4U + 2*i + 1];
+ env->IBAT[0][i+4] = env->spr[SPR_IBAT4U + 2*i];
+ env->IBAT[1][i+4] = env->spr[SPR_IBAT4U + 2*i + 1];
+ }
+
+ /* Restore htab_base and htab_mask variables */
+ ppc_store_sdr1(env, env->spr[SPR_SDR1]);
+
+ hreg_compute_hflags(env);
+ hreg_compute_mem_idx(env);
+
+ return 0;
+}
+
+static bool fpu_needed(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+
+ return (cpu->env.insns_flags & PPC_FLOAT);
+}
+
+static const VMStateDescription vmstate_fpu = {
+ .name = "cpu/fpu",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_FLOAT64_ARRAY(env.fpr, PowerPCCPU, 32),
+ VMSTATE_UINTTL(env.fpscr, PowerPCCPU),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static bool altivec_needed(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+
+ return (cpu->env.insns_flags & PPC_ALTIVEC);
+}
+
+static const VMStateDescription vmstate_altivec = {
+ .name = "cpu/altivec",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_AVR_ARRAY(env.avr, PowerPCCPU, 32),
+ VMSTATE_UINT32(env.vscr, PowerPCCPU),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static bool vsx_needed(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+
+ return (cpu->env.insns_flags2 & PPC2_VSX);
+}
+
+static const VMStateDescription vmstate_vsx = {
+ .name = "cpu/vsx",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT64_ARRAY(env.vsr, PowerPCCPU, 32),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static bool sr_needed(void *opaque)
+{
+#ifdef TARGET_PPC64
+ PowerPCCPU *cpu = opaque;
+
+ return !(cpu->env.mmu_model & POWERPC_MMU_64);
+#else
+ return true;
+#endif
+}
+
+static const VMStateDescription vmstate_sr = {
+ .name = "cpu/sr",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINTTL_ARRAY(env.sr, PowerPCCPU, 32),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+#ifdef TARGET_PPC64
+static int get_slbe(QEMUFile *f, void *pv, size_t size)
+{
+ ppc_slb_t *v = pv;
+
+ v->esid = qemu_get_be64(f);
+ v->vsid = qemu_get_be64(f);
+
+ return 0;
+}
+
+static void put_slbe(QEMUFile *f, void *pv, size_t size)
+{
+ ppc_slb_t *v = pv;
+
+ qemu_put_be64(f, v->esid);
+ qemu_put_be64(f, v->vsid);
+}
+
+const VMStateInfo vmstate_info_slbe = {
+ .name = "slbe",
+ .get = get_slbe,
+ .put = put_slbe,
+};
+
+#define VMSTATE_SLB_ARRAY_V(_f, _s, _n, _v) \
+ VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_slbe, ppc_slb_t)
+
+#define VMSTATE_SLB_ARRAY(_f, _s, _n) \
+ VMSTATE_SLB_ARRAY_V(_f, _s, _n, 0)
+
+static bool slb_needed(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+
+ /* We don't support any of the old segment table based 64-bit CPUs */
+ return (cpu->env.mmu_model & POWERPC_MMU_64);
+}
+
+static const VMStateDescription vmstate_slb = {
+ .name = "cpu/slb",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_INT32_EQUAL(env.slb_nr, PowerPCCPU),
+ VMSTATE_SLB_ARRAY(env.slb, PowerPCCPU, 64),
+ VMSTATE_END_OF_LIST()
+ }
+};
+#endif /* TARGET_PPC64 */
+
+static const VMStateDescription vmstate_tlb6xx_entry = {
+ .name = "cpu/tlb6xx_entry",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINTTL(pte0, ppc6xx_tlb_t),
+ VMSTATE_UINTTL(pte1, ppc6xx_tlb_t),
+ VMSTATE_UINTTL(EPN, ppc6xx_tlb_t),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static bool tlb6xx_needed(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
+
+ return env->nb_tlb && (env->tlb_type == TLB_6XX);
+}
+
+static const VMStateDescription vmstate_tlb6xx = {
+ .name = "cpu/tlb6xx",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU),
+ VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlb6, PowerPCCPU,
+ env.nb_tlb,
+ vmstate_tlb6xx_entry,
+ ppc6xx_tlb_t),
+ VMSTATE_UINTTL_ARRAY(env.tgpr, PowerPCCPU, 4),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_tlbemb_entry = {
+ .name = "cpu/tlbemb_entry",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT64(RPN, ppcemb_tlb_t),
+ VMSTATE_UINTTL(EPN, ppcemb_tlb_t),
+ VMSTATE_UINTTL(PID, ppcemb_tlb_t),
+ VMSTATE_UINTTL(size, ppcemb_tlb_t),
+ VMSTATE_UINT32(prot, ppcemb_tlb_t),
+ VMSTATE_UINT32(attr, ppcemb_tlb_t),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static bool tlbemb_needed(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
+
+ return env->nb_tlb && (env->tlb_type == TLB_EMB);
+}
+
+static bool pbr403_needed(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+ uint32_t pvr = cpu->env.spr[SPR_PVR];
+
+ return (pvr & 0xffff0000) == 0x00200000;
+}
+
+static const VMStateDescription vmstate_pbr403 = {
+ .name = "cpu/pbr403",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINTTL_ARRAY(env.pb, PowerPCCPU, 4),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static const VMStateDescription vmstate_tlbemb = {
+ .name = "cpu/tlb6xx",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU),
+ VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlbe, PowerPCCPU,
+ env.nb_tlb,
+ vmstate_tlbemb_entry,
+ ppcemb_tlb_t),
+ /* 403 protection registers */
+ VMSTATE_END_OF_LIST()
+ },
+ .subsections = (VMStateSubsection []) {
+ {
+ .vmsd = &vmstate_pbr403,
+ .needed = pbr403_needed,
+ } , {
+ /* empty */
+ }
+ }
+};
+
+static const VMStateDescription vmstate_tlbmas_entry = {
+ .name = "cpu/tlbmas_entry",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(mas8, ppcmas_tlb_t),
+ VMSTATE_UINT32(mas1, ppcmas_tlb_t),
+ VMSTATE_UINT64(mas2, ppcmas_tlb_t),
+ VMSTATE_UINT64(mas7_3, ppcmas_tlb_t),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static bool tlbmas_needed(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+ CPUPPCState *env = &cpu->env;
+
+ return env->nb_tlb && (env->tlb_type == TLB_MAS);
+}
+
+static const VMStateDescription vmstate_tlbmas = {
+ .name = "cpu/tlbmas",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_INT32_EQUAL(env.nb_tlb, PowerPCCPU),
+ VMSTATE_STRUCT_VARRAY_POINTER_INT32(env.tlb.tlbm, PowerPCCPU,
+ env.nb_tlb,
+ vmstate_tlbmas_entry,
+ ppcmas_tlb_t),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+const VMStateDescription vmstate_ppc_cpu = {
+ .name = "cpu",
+ .version_id = 5,
+ .minimum_version_id = 5,
+ .minimum_version_id_old = 4,
+ .load_state_old = cpu_load_old,
+ .pre_save = cpu_pre_save,
+ .post_load = cpu_post_load,
+ .fields = (VMStateField []) {
+ /* Verify we haven't changed the pvr */
+ VMSTATE_UINTTL_EQUAL(env.spr[SPR_PVR], PowerPCCPU),
+
+ /* User mode architected state */
+ VMSTATE_UINTTL_ARRAY(env.gpr, PowerPCCPU, 32),
+#if !defined(TARGET_PPC64)
+ VMSTATE_UINTTL_ARRAY(env.gprh, PowerPCCPU, 32),
+#endif
+ VMSTATE_UINT32_ARRAY(env.crf, PowerPCCPU, 8),
+ VMSTATE_UINTTL(env.nip, PowerPCCPU),
+
+ /* SPRs */
+ VMSTATE_UINTTL_ARRAY(env.spr, PowerPCCPU, 1024),
+ VMSTATE_UINT64(env.spe_acc, PowerPCCPU),
+
+ /* Reservation */
+ VMSTATE_UINTTL(env.reserve_addr, PowerPCCPU),
+
+ /* Supervisor mode architected state */
+ VMSTATE_UINTTL(env.msr, PowerPCCPU),
+
+ /* Internal state */
+ VMSTATE_UINTTL(env.hflags_nmsr, PowerPCCPU),
+ /* FIXME: access_type? */
+
+ /* Sanity checking */
+ VMSTATE_UINTTL_EQUAL(env.msr_mask, PowerPCCPU),
+ VMSTATE_UINT64_EQUAL(env.insns_flags, PowerPCCPU),
+ VMSTATE_UINT64_EQUAL(env.insns_flags2, PowerPCCPU),
+ VMSTATE_UINT32_EQUAL(env.nb_BATs, PowerPCCPU),
+ VMSTATE_END_OF_LIST()
+ },
+ .subsections = (VMStateSubsection []) {
+ {
+ .vmsd = &vmstate_fpu,
+ .needed = fpu_needed,
+ } , {
+ .vmsd = &vmstate_altivec,
+ .needed = altivec_needed,
+ } , {
+ .vmsd = &vmstate_vsx,
+ .needed = vsx_needed,
+ } , {
+ .vmsd = &vmstate_sr,
+ .needed = sr_needed,
+ } , {
+#ifdef TARGET_PPC64
+ .vmsd = &vmstate_slb,
+ .needed = slb_needed,
+ } , {
+#endif /* TARGET_PPC64 */
+ .vmsd = &vmstate_tlb6xx,
+ .needed = tlb6xx_needed,
+ } , {
+ .vmsd = &vmstate_tlbemb,
+ .needed = tlbemb_needed,
+ } , {
+ .vmsd = &vmstate_tlbmas,
+ .needed = tlbmas_needed,
+ } , {
+ /* empty */
+ }
+ }
+};
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 0b0844f..609f797 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -27,6 +27,7 @@
#include "cpu-models.h"
#include "mmu-hash32.h"
#include "mmu-hash64.h"
+#include "qemu/error-report.h"
//#define PPC_DUMP_CPU
//#define PPC_DEBUG_SPR
@@ -7023,6 +7024,110 @@
POWERPC_FLAG_BUS_CLK;
}
+static void init_proc_power5plus(CPUPPCState *env)
+{
+ gen_spr_ne_601(env);
+ gen_spr_7xx(env);
+ /* Time base */
+ gen_tbl(env);
+ /* Hardware implementation registers */
+ /* XXX : not implemented */
+ spr_register(env, SPR_HID0, "HID0",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_clear,
+ 0x60000000);
+ /* XXX : not implemented */
+ spr_register(env, SPR_HID1, "HID1",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* XXX : not implemented */
+ spr_register(env, SPR_750FX_HID2, "HID2",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ /* XXX : not implemented */
+ spr_register(env, SPR_970_HID5, "HID5",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ POWERPC970_HID5_INIT);
+ /* XXX : not implemented */
+ spr_register(env, SPR_L2CR, "L2CR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, NULL,
+ 0x00000000);
+ /* Memory management */
+ /* XXX: not correct */
+ gen_low_BATs(env);
+ /* XXX : not implemented */
+ spr_register(env, SPR_MMUCFG, "MMUCFG",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, SPR_NOACCESS,
+ 0x00000000); /* TOFIX */
+ /* XXX : not implemented */
+ spr_register(env, SPR_MMUCSR0, "MMUCSR0",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000); /* TOFIX */
+ spr_register(env, SPR_HIOR, "SPR_HIOR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_hior, &spr_write_hior,
+ 0x00000000);
+ spr_register(env, SPR_CTRL, "SPR_CTRL",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_UCTRL, "SPR_UCTRL",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+ spr_register(env, SPR_VRSAVE, "SPR_VRSAVE",
+ &spr_read_generic, &spr_write_generic,
+ &spr_read_generic, &spr_write_generic,
+ 0x00000000);
+#if !defined(CONFIG_USER_ONLY)
+ env->slb_nr = 64;
+#endif
+ init_excp_970(env);
+ env->dcache_line_size = 128;
+ env->icache_line_size = 128;
+ /* Allocate hardware IRQ controller */
+ ppc970_irq_init(env);
+ /* Can't find information on what this should be on reset. This
+ * value is the one used by 74xx processors. */
+ vscr_init(env, 0x00010000);
+}
+
+POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc);
+
+ dc->desc = "POWER5+";
+ pcc->init_proc = init_proc_power5plus;
+ pcc->check_pow = check_pow_970FX;
+ pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB |
+ PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
+ PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
+ PPC_FLOAT_STFIWX |
+ PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
+ PPC_MEM_SYNC | PPC_MEM_EIEIO |
+ PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
+ PPC_64B |
+ PPC_SEGMENT_64B | PPC_SLBI;
+ pcc->msr_mask = 0x800000000204FF36ULL;
+ pcc->mmu_model = POWERPC_MMU_64B;
+#if defined(CONFIG_SOFTMMU)
+ pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
+#endif
+ pcc->excp_model = POWERPC_EXCP_970;
+ pcc->bus_model = PPC_FLAGS_INPUT_970;
+ pcc->bfd_mach = bfd_mach_ppc64;
+ pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
+ POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
+ POWERPC_FLAG_BUS_CLK;
+}
+
static void init_proc_POWER7 (CPUPPCState *env)
{
gen_spr_ne_601(env);
@@ -7825,7 +7930,7 @@
error_setg(errp, "Unable to virtualize selected CPU with KVM");
return;
}
- } else {
+ } else if (tcg_enabled()) {
if (ppc_fixup_cpu(cpu) != 0) {
error_setg(errp, "Unable to emulate selected CPU with TCG");
return;
@@ -7861,6 +7966,8 @@
34, "power-spe.xml", 0);
}
+ qemu_init_vcpu(cs);
+
pcc->parent_realize(dev, errp);
#if defined(PPC_DUMP_CPU)
@@ -8175,7 +8282,7 @@
object_property_set_bool(OBJECT(cpu), true, "realized", &err);
if (err != NULL) {
- fprintf(stderr, "%s\n", error_get_pretty(err));
+ error_report("%s", error_get_pretty(err));
error_free(err);
object_unref(OBJECT(cpu));
return NULL;
@@ -8458,8 +8565,18 @@
cc->dump_state = ppc_cpu_dump_state;
cc->dump_statistics = ppc_cpu_dump_statistics;
cc->set_pc = ppc_cpu_set_pc;
+ cc->gdb_read_register = ppc_cpu_gdb_read_register;
+ cc->gdb_write_register = ppc_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug;
+ cc->vmsd = &vmstate_ppc_cpu;
+#endif
+
+ cc->gdb_num_core_regs = 71;
+#if defined(TARGET_PPC64)
+ cc->gdb_core_xml_file = "power64-core.xml";
+#else
+ cc->gdb_core_xml_file = "power-core.xml";
#endif
}
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
index 4e63417..f873146 100644
--- a/target-s390x/Makefile.objs
+++ b/target-s390x/Makefile.objs
@@ -1,4 +1,5 @@
obj-y += translate.o helper.o cpu.o interrupt.o
obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
-obj-$(CONFIG_SOFTMMU) += ioinst.o
+obj-y += gdbstub.o
+obj-$(CONFIG_SOFTMMU) += ioinst.o arch_dump.o
obj-$(CONFIG_KVM) += kvm.o
diff --git a/target-s390x/arch_dump.c b/target-s390x/arch_dump.c
new file mode 100644
index 0000000..9d36116
--- /dev/null
+++ b/target-s390x/arch_dump.c
@@ -0,0 +1,213 @@
+/*
+ * writing ELF notes for s390x arch
+ *
+ *
+ * Copyright IBM Corp. 2012, 2013
+ *
+ * Ekaterina Tumanova <tumanova@linux.vnet.ibm.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 "cpu.h"
+#include "elf.h"
+#include "exec/cpu-all.h"
+#include "sysemu/dump.h"
+#include "sysemu/kvm.h"
+
+
+struct S390xUserRegsStruct {
+ uint64_t psw[2];
+ uint64_t gprs[16];
+ uint32_t acrs[16];
+} QEMU_PACKED;
+
+typedef struct S390xUserRegsStruct S390xUserRegs;
+
+struct S390xElfPrstatusStruct {
+ uint8_t pad1[32];
+ uint32_t pid;
+ uint8_t pad2[76];
+ S390xUserRegs regs;
+ uint8_t pad3[16];
+} QEMU_PACKED;
+
+typedef struct S390xElfPrstatusStruct S390xElfPrstatus;
+
+struct S390xElfFpregsetStruct {
+ uint32_t fpc;
+ uint32_t pad;
+ uint64_t fprs[16];
+} QEMU_PACKED;
+
+typedef struct S390xElfFpregsetStruct S390xElfFpregset;
+
+typedef struct noteStruct {
+ Elf64_Nhdr hdr;
+ char name[5];
+ char pad3[3];
+ union {
+ S390xElfPrstatus prstatus;
+ S390xElfFpregset fpregset;
+ uint32_t prefix;
+ uint64_t timer;
+ uint64_t todcmp;
+ uint32_t todpreg;
+ uint64_t ctrs[16];
+ } contents;
+} QEMU_PACKED Note;
+
+static void s390x_write_elf64_prstatus(Note *note, S390CPU *cpu)
+{
+ int i;
+ S390xUserRegs *regs;
+
+ note->hdr.n_type = cpu_to_be32(NT_PRSTATUS);
+
+ regs = &(note->contents.prstatus.regs);
+ regs->psw[0] = cpu_to_be64(cpu->env.psw.mask);
+ regs->psw[1] = cpu_to_be64(cpu->env.psw.addr);
+ for (i = 0; i <= 15; i++) {
+ regs->acrs[i] = cpu_to_be32(cpu->env.aregs[i]);
+ regs->gprs[i] = cpu_to_be64(cpu->env.regs[i]);
+ }
+}
+
+static void s390x_write_elf64_fpregset(Note *note, S390CPU *cpu)
+{
+ int i;
+
+ note->hdr.n_type = cpu_to_be32(NT_FPREGSET);
+ note->contents.fpregset.fpc = cpu_to_be32(cpu->env.fpc);
+ for (i = 0; i <= 15; i++) {
+ note->contents.fpregset.fprs[i] = cpu_to_be64(cpu->env.fregs[i].ll);
+ }
+}
+
+
+static void s390x_write_elf64_timer(Note *note, S390CPU *cpu)
+{
+ note->hdr.n_type = cpu_to_be32(NT_S390_TIMER);
+ note->contents.timer = cpu_to_be64((uint64_t)(cpu->env.cputm));
+}
+
+static void s390x_write_elf64_todcmp(Note *note, S390CPU *cpu)
+{
+ note->hdr.n_type = cpu_to_be32(NT_S390_TODCMP);
+ note->contents.todcmp = cpu_to_be64((uint64_t)(cpu->env.ckc));
+}
+
+static void s390x_write_elf64_todpreg(Note *note, S390CPU *cpu)
+{
+ note->hdr.n_type = cpu_to_be32(NT_S390_TODPREG);
+ note->contents.todpreg = cpu_to_be32((uint32_t)(cpu->env.todpr));
+}
+
+static void s390x_write_elf64_ctrs(Note *note, S390CPU *cpu)
+{
+ int i;
+
+ note->hdr.n_type = cpu_to_be32(NT_S390_CTRS);
+
+ for (i = 0; i <= 15; i++) {
+ note->contents.ctrs[i] = cpu_to_be64(cpu->env.cregs[i]);
+ }
+}
+
+static void s390x_write_elf64_prefix(Note *note, S390CPU *cpu)
+{
+ note->hdr.n_type = cpu_to_be32(NT_S390_PREFIX);
+ note->contents.prefix = cpu_to_be32((uint32_t)(cpu->env.psa));
+}
+
+
+struct NoteFuncDescStruct {
+ int contents_size;
+ void (*note_contents_func)(Note *note, S390CPU *cpu);
+} note_func[] = {
+ {sizeof(((Note *)0)->contents.prstatus), s390x_write_elf64_prstatus},
+ {sizeof(((Note *)0)->contents.prefix), s390x_write_elf64_prefix},
+ {sizeof(((Note *)0)->contents.fpregset), s390x_write_elf64_fpregset},
+ {sizeof(((Note *)0)->contents.ctrs), s390x_write_elf64_ctrs},
+ {sizeof(((Note *)0)->contents.timer), s390x_write_elf64_timer},
+ {sizeof(((Note *)0)->contents.todcmp), s390x_write_elf64_todcmp},
+ {sizeof(((Note *)0)->contents.todpreg), s390x_write_elf64_todpreg},
+ { 0, NULL}
+};
+
+typedef struct NoteFuncDescStruct NoteFuncDesc;
+
+
+static int s390x_write_all_elf64_notes(const char *note_name,
+ WriteCoreDumpFunction f,
+ S390CPU *cpu, int id,
+ void *opaque)
+{
+ Note note;
+ NoteFuncDesc *nf;
+ int note_size;
+ int ret = -1;
+
+ for (nf = note_func; nf->note_contents_func; nf++) {
+ note.hdr.n_namesz = cpu_to_be32(sizeof(note.name));
+ note.hdr.n_descsz = cpu_to_be32(nf->contents_size);
+ strncpy(note.name, note_name, sizeof(note.name));
+ (*nf->note_contents_func)(¬e, cpu);
+
+ note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size;
+ ret = f(¬e, note_size, opaque);
+
+ if (ret < 0) {
+ return -1;
+ }
+
+ }
+
+ return 0;
+}
+
+
+int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
+ int cpuid, void *opaque)
+{
+ S390CPU *cpu = S390_CPU(cs);
+ return s390x_write_all_elf64_notes("CORE", f, cpu, cpuid, opaque);
+}
+
+int cpu_get_dump_info(ArchDumpInfo *info,
+ const struct GuestPhysBlockList *guest_phys_blocks)
+{
+ info->d_machine = EM_S390;
+ info->d_endian = ELFDATA2MSB;
+ info->d_class = ELFCLASS64;
+
+ return 0;
+}
+
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+ int name_size = 8; /* "CORE" or "QEMU" rounded */
+ size_t elf_note_size = 0;
+ int note_head_size;
+ NoteFuncDesc *nf;
+
+ assert(class == ELFCLASS64);
+ assert(machine == EM_S390);
+
+ note_head_size = sizeof(Elf64_Nhdr);
+
+ for (nf = note_func; nf->note_contents_func; nf++) {
+ elf_note_size = elf_note_size + note_head_size + name_size +
+ nf->contents_size;
+ }
+
+ return (elf_note_size) * nr_cpus;
+}
+
+int s390_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,
+ CPUState *cpu, void *opaque)
+{
+ return 0;
+}
diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h
index a4fe8fb..cbe2341 100644
--- a/target-s390x/cpu-qom.h
+++ b/target-s390x/cpu-qom.h
@@ -74,6 +74,13 @@
void s390_cpu_do_interrupt(CPUState *cpu);
void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
int flags);
+int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
+ int cpuid, void *opaque);
+
+int s390_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,
+ CPUState *cpu, void *opaque);
hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#endif
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index cb89d1a..5cc9938 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -101,10 +101,11 @@
static void s390_cpu_realizefn(DeviceState *dev, Error **errp)
{
- S390CPU *cpu = S390_CPU(dev);
+ CPUState *cs = CPU(dev);
S390CPUClass *scc = S390_CPU_GET_CLASS(dev);
- cpu_reset(CPU(cpu));
+ qemu_init_vcpu(cs);
+ cpu_reset(cs);
scc->parent_realize(dev, errp);
}
@@ -128,8 +129,8 @@
env->tod_offset = TOD_UNIX_EPOCH +
(time2tod(mktimegm(&tm)) * 1000000000ULL);
env->tod_basetime = 0;
- env->tod_timer = qemu_new_timer_ns(vm_clock, s390x_tod_timer, cpu);
- env->cpu_timer = qemu_new_timer_ns(vm_clock, s390x_cpu_timer, cpu);
+ env->tod_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_tod_timer, cpu);
+ env->cpu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_cpu_timer, cpu);
/* set CPUState::halted state to 1 to avoid decrementing the running
* cpu counter in s390_cpu_reset to a negative number at
* initial ipl */
@@ -173,10 +174,15 @@
cc->do_interrupt = s390_cpu_do_interrupt;
cc->dump_state = s390_cpu_dump_state;
cc->set_pc = s390_cpu_set_pc;
+ cc->gdb_read_register = s390_cpu_gdb_read_register;
+ cc->gdb_write_register = s390_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = s390_cpu_get_phys_page_debug;
+ cc->write_elf64_note = s390_cpu_write_elf64_note;
+ cc->write_elf64_qemunote = s390_cpu_write_elf64_qemunote;
#endif
dc->vmsd = &vmstate_s390_cpu;
+ cc->gdb_num_core_regs = S390_NUM_REGS;
}
static const TypeInfo s390_cpu_type_info = {
diff --git a/target-s390x/gdbstub.c b/target-s390x/gdbstub.c
new file mode 100644
index 0000000..a129742
--- /dev/null
+++ b/target-s390x/gdbstub.c
@@ -0,0 +1,88 @@
+/*
+ * s390x gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+#include "qemu/bitops.h"
+
+int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ S390CPU *cpu = S390_CPU(cs);
+ CPUS390XState *env = &cpu->env;
+ uint64_t val;
+ int cc_op;
+
+ switch (n) {
+ case S390_PSWM_REGNUM:
+ cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr);
+ val = deposit64(env->psw.mask, 44, 2, cc_op);
+ return gdb_get_regl(mem_buf, val);
+ case S390_PSWA_REGNUM:
+ return gdb_get_regl(mem_buf, env->psw.addr);
+ case S390_R0_REGNUM ... S390_R15_REGNUM:
+ return gdb_get_regl(mem_buf, env->regs[n-S390_R0_REGNUM]);
+ case S390_A0_REGNUM ... S390_A15_REGNUM:
+ return gdb_get_reg32(mem_buf, env->aregs[n-S390_A0_REGNUM]);
+ case S390_FPC_REGNUM:
+ return gdb_get_reg32(mem_buf, env->fpc);
+ case S390_F0_REGNUM ... S390_F15_REGNUM:
+ return gdb_get_reg64(mem_buf, env->fregs[n-S390_F0_REGNUM].ll);
+ }
+
+ return 0;
+}
+
+int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ S390CPU *cpu = S390_CPU(cs);
+ CPUS390XState *env = &cpu->env;
+ target_ulong tmpl;
+ uint32_t tmp32;
+ int r = 8;
+ tmpl = ldtul_p(mem_buf);
+ tmp32 = ldl_p(mem_buf);
+
+ switch (n) {
+ case S390_PSWM_REGNUM:
+ env->psw.mask = tmpl;
+ env->cc_op = extract64(tmpl, 44, 2);
+ break;
+ case S390_PSWA_REGNUM:
+ env->psw.addr = tmpl;
+ break;
+ case S390_R0_REGNUM ... S390_R15_REGNUM:
+ env->regs[n-S390_R0_REGNUM] = tmpl;
+ break;
+ case S390_A0_REGNUM ... S390_A15_REGNUM:
+ env->aregs[n-S390_A0_REGNUM] = tmp32;
+ r = 4;
+ break;
+ case S390_FPC_REGNUM:
+ env->fpc = tmp32;
+ r = 4;
+ break;
+ case S390_F0_REGNUM ... S390_F15_REGNUM:
+ env->fregs[n-S390_F0_REGNUM].ll = tmpl;
+ break;
+ default:
+ return 0;
+ }
+ return r;
+}
diff --git a/target-s390x/ioinst.c b/target-s390x/ioinst.c
index 28c508d..85fd285 100644
--- a/target-s390x/ioinst.c
+++ b/target-s390x/ioinst.c
@@ -151,23 +151,24 @@
int cc;
hwaddr len = sizeof(*schib);
- if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
- program_interrupt(env, PGM_OPERAND, 2);
+ addr = decode_basedisp_s(env, ipb);
+ if (addr & 3) {
+ program_interrupt(env, PGM_SPECIFICATION, 2);
return -EIO;
}
- trace_ioinst_sch_id("msch", cssid, ssid, schid);
- addr = decode_basedisp_s(env, ipb);
schib = s390_cpu_physical_memory_map(env, addr, &len, 0);
if (!schib || len != sizeof(*schib)) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
+ program_interrupt(env, PGM_ADDRESSING, 2);
cc = -EIO;
goto out;
}
- if (!ioinst_schib_valid(schib)) {
+ if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
+ !ioinst_schib_valid(schib)) {
program_interrupt(env, PGM_OPERAND, 2);
cc = -EIO;
goto out;
}
+ trace_ioinst_sch_id("msch", cssid, ssid, schid);
sch = css_find_subch(m, cssid, ssid, schid);
if (sch && css_subch_visible(sch)) {
ret = css_do_msch(sch, schib);
@@ -222,24 +223,25 @@
int cc;
hwaddr len = sizeof(*orig_orb);
- if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
- program_interrupt(env, PGM_OPERAND, 2);
+ addr = decode_basedisp_s(env, ipb);
+ if (addr & 3) {
+ program_interrupt(env, PGM_SPECIFICATION, 2);
return -EIO;
}
- trace_ioinst_sch_id("ssch", cssid, ssid, schid);
- addr = decode_basedisp_s(env, ipb);
orig_orb = s390_cpu_physical_memory_map(env, addr, &len, 0);
if (!orig_orb || len != sizeof(*orig_orb)) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
+ program_interrupt(env, PGM_ADDRESSING, 2);
cc = -EIO;
goto out;
}
copy_orb_from_guest(&orb, orig_orb);
- if (!ioinst_orb_valid(&orb)) {
+ if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
+ !ioinst_orb_valid(&orb)) {
program_interrupt(env, PGM_OPERAND, 2);
cc = -EIO;
goto out;
}
+ trace_ioinst_sch_id("ssch", cssid, ssid, schid);
sch = css_find_subch(m, cssid, ssid, schid);
if (sch && css_subch_visible(sch)) {
ret = css_do_ssch(sch, &orb);
@@ -272,9 +274,13 @@
hwaddr len = sizeof(*crw);
addr = decode_basedisp_s(env, ipb);
+ if (addr & 3) {
+ program_interrupt(env, PGM_SPECIFICATION, 2);
+ return -EIO;
+ }
crw = s390_cpu_physical_memory_map(env, addr, &len, 1);
if (!crw || len != sizeof(*crw)) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
+ program_interrupt(env, PGM_ADDRESSING, 2);
cc = -EIO;
goto out;
}
@@ -294,18 +300,24 @@
SCHIB *schib;
hwaddr len = sizeof(*schib);
- if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
- program_interrupt(env, PGM_OPERAND, 2);
+ addr = decode_basedisp_s(env, ipb);
+ if (addr & 3) {
+ program_interrupt(env, PGM_SPECIFICATION, 2);
return -EIO;
}
- trace_ioinst_sch_id("stsch", cssid, ssid, schid);
- addr = decode_basedisp_s(env, ipb);
schib = s390_cpu_physical_memory_map(env, addr, &len, 1);
if (!schib || len != sizeof(*schib)) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
+ program_interrupt(env, PGM_ADDRESSING, 2);
cc = -EIO;
goto out;
}
+
+ if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
+ program_interrupt(env, PGM_OPERAND, 2);
+ cc = -EIO;
+ goto out;
+ }
+ trace_ioinst_sch_id("stsch", cssid, ssid, schid);
sch = css_find_subch(m, cssid, ssid, schid);
if (sch) {
if (css_subch_visible(sch)) {
@@ -345,9 +357,13 @@
}
trace_ioinst_sch_id("tsch", cssid, ssid, schid);
addr = decode_basedisp_s(env, ipb);
+ if (addr & 3) {
+ program_interrupt(env, PGM_SPECIFICATION, 2);
+ return -EIO;
+ }
irb = s390_cpu_physical_memory_map(env, addr, &len, 1);
if (!irb || len != sizeof(*irb)) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
+ program_interrupt(env, PGM_ADDRESSING, 2);
cc = -EIO;
goto out;
}
@@ -580,7 +596,7 @@
}
req = s390_cpu_physical_memory_map(env, addr, &map_size, 1);
if (!req || map_size != TARGET_PAGE_SIZE) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
+ program_interrupt(env, PGM_ADDRESSING, 2);
ret = -EIO;
goto out;
}
@@ -625,12 +641,17 @@
trace_ioinst("tpi");
addr = decode_basedisp_s(env, ipb);
+ if (addr & 3) {
+ program_interrupt(env, PGM_SPECIFICATION, 2);
+ return -EIO;
+ }
+
lowcore = addr ? 0 : 1;
len = lowcore ? 8 /* two words */ : 12 /* three words */;
orig_len = len;
int_code = s390_cpu_physical_memory_map(env, addr, &len, 1);
if (!int_code || (len != orig_len)) {
- program_interrupt(env, PGM_SPECIFICATION, 2);
+ program_interrupt(env, PGM_ADDRESSING, 2);
ret = -EIO;
goto out;
}
@@ -663,7 +684,7 @@
update = SCHM_REG1_UPD(reg1);
dct = SCHM_REG1_DCT(reg1);
- if (update && (reg2 & 0x0000000000000fff)) {
+ if (update && (reg2 & 0x000000000000001f)) {
program_interrupt(env, PGM_OPERAND, 2);
return -EIO;
}
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 60e94f8..26d18e3 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -40,10 +40,10 @@
/* #define DEBUG_KVM */
#ifdef DEBUG_KVM
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
#else
-#define dprintf(fmt, ...) \
+#define DPRINTF(fmt, ...) \
do { } while (0)
#endif
@@ -345,12 +345,10 @@
int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
- if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) ||
- cpu_memory_rw_debug(env, bp->pc, (uint8_t *)diag_501, 4, 1)) {
+ if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) ||
+ cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)diag_501, 4, 1)) {
return -EINVAL;
}
return 0;
@@ -358,16 +356,14 @@
int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
{
- S390CPU *cpu = S390_CPU(cs);
- CPUS390XState *env = &cpu->env;
uint8_t t[4];
static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
- if (cpu_memory_rw_debug(env, bp->pc, t, 4, 0)) {
+ if (cpu_memory_rw_debug(cs, bp->pc, t, 4, 0)) {
return -EINVAL;
} else if (memcmp(t, diag_501, 4)) {
return -EINVAL;
- } else if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1)) {
+ } else if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1)) {
return -EINVAL;
}
@@ -532,50 +528,19 @@
no_cc = 1;
r = ioinst_handle_sal(env, env->regs[1]);
break;
+ case PRIV_SIGA:
+ /* Not provided, set CC = 3 for subchannel not operational */
+ r = 3;
+ break;
default:
- r = -1;
- break;
+ return -1;
}
- if (r >= 0) {
- if (!no_cc) {
- setcc(cpu, r);
- }
- r = 0;
- } else if (r < -1) {
- r = 0;
- }
- return r;
-}
-
-static int is_ioinst(uint8_t ipa0, uint8_t ipa1, uint8_t ipb)
-{
- int ret = 0;
- uint16_t ipa = (ipa0 << 8) | ipa1;
-
- switch (ipa) {
- case IPA0_B2 | PRIV_CSCH:
- case IPA0_B2 | PRIV_HSCH:
- case IPA0_B2 | PRIV_MSCH:
- case IPA0_B2 | PRIV_SSCH:
- case IPA0_B2 | PRIV_STSCH:
- case IPA0_B2 | PRIV_TPI:
- case IPA0_B2 | PRIV_SAL:
- case IPA0_B2 | PRIV_RSCH:
- case IPA0_B2 | PRIV_STCRW:
- case IPA0_B2 | PRIV_STCPS:
- case IPA0_B2 | PRIV_RCHP:
- case IPA0_B2 | PRIV_SCHM:
- case IPA0_B2 | PRIV_CHSC:
- case IPA0_B2 | PRIV_SIGA:
- case IPA0_B2 | PRIV_XSCH:
- case IPA0_B9 | PRIV_EQBS:
- case IPA0_EB | PRIV_SQBS:
- ret = 1;
- break;
+ if (r >= 0 && !no_cc) {
+ setcc(cpu, r);
}
- return ret;
+ return 0;
}
static int handle_priv(S390CPU *cpu, struct kvm_run *run,
@@ -585,21 +550,15 @@
uint16_t ipbh0 = (run->s390_sieic.ipb & 0xffff0000) >> 16;
uint8_t ipb = run->s390_sieic.ipb & 0xff;
- dprintf("KVM: PRIV: %d\n", ipa1);
+ DPRINTF("KVM: PRIV: %d\n", ipa1);
switch (ipa1) {
case PRIV_SCLP_CALL:
r = kvm_sclp_service_call(cpu, run, ipbh0);
break;
default:
- if (is_ioinst(ipa0, ipa1, ipb)) {
- r = kvm_handle_css_inst(cpu, run, ipa0, ipa1, ipb);
- if (r == -1) {
- setcc(cpu, 3);
- r = 0;
- }
- } else {
- dprintf("KVM: unknown PRIV: 0x%x\n", ipa1);
- r = -1;
+ r = kvm_handle_css_inst(cpu, run, ipa0, ipa1, ipb);
+ if (r == -1) {
+ DPRINTF("KVM: unhandled PRIV: 0x%x\n", ipa1);
}
break;
}
@@ -631,7 +590,7 @@
sleep(10);
break;
default:
- dprintf("KVM: unknown DIAG: 0x%x\n", ipb_code);
+ DPRINTF("KVM: unknown DIAG: 0x%x\n", ipb_code);
r = -1;
break;
}
@@ -644,7 +603,7 @@
kvm_s390_interrupt(cpu, KVM_S390_RESTART, 0);
s390_add_running_cpu(cpu);
qemu_cpu_kick(CPU(cpu));
- dprintf("DONE: SIGP cpu restart: %p\n", &cpu->env);
+ DPRINTF("DONE: SIGP cpu restart: %p\n", &cpu->env);
return 0;
}
@@ -672,7 +631,7 @@
env->regs[i] = 0;
}
- dprintf("DONE: SIGP initial reset: %p\n", env);
+ DPRINTF("DONE: SIGP initial reset: %p\n", env);
return 0;
}
@@ -734,14 +693,15 @@
return 0;
}
-static int handle_instruction(S390CPU *cpu, struct kvm_run *run)
+static void handle_instruction(S390CPU *cpu, struct kvm_run *run)
{
unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00);
uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff;
int ipb_code = (run->s390_sieic.ipb & 0x0fff0000) >> 16;
int r = -1;
- dprintf("handle_instruction 0x%x 0x%x\n", run->s390_sieic.ipa, run->s390_sieic.ipb);
+ DPRINTF("handle_instruction 0x%x 0x%x\n",
+ run->s390_sieic.ipa, run->s390_sieic.ipb);
switch (ipa0) {
case IPA0_B2:
case IPA0_B9:
@@ -759,7 +719,6 @@
if (r < 0) {
enter_pgmcheck(cpu, 0x0001);
}
- return 0;
}
static bool is_special_wait_psw(CPUState *cs)
@@ -775,11 +734,11 @@
int icpt_code = run->s390_sieic.icptcode;
int r = 0;
- dprintf("intercept: 0x%x (at 0x%lx)\n", icpt_code,
+ DPRINTF("intercept: 0x%x (at 0x%lx)\n", icpt_code,
(long)cs->kvm_run->psw_addr);
switch (icpt_code) {
case ICPT_INSTRUCTION:
- r = handle_instruction(cpu, run);
+ handle_instruction(cpu, run);
break;
case ICPT_WAITPSW:
/* disabled wait, since enabled wait is handled in kernel */
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 09301d0..454960a 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -225,7 +225,7 @@
uint64_t time;
time = env->tod_offset +
- time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
+ time2tod(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - env->tod_basetime);
return time;
}
@@ -248,7 +248,7 @@
/* nanoseconds */
time = (time * 125) >> 9;
- qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
+ timer_mod(env->tod_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + time);
}
/* Store Clock Comparator */
@@ -268,7 +268,7 @@
/* nanoseconds */
time = (time * 125) >> 9;
- qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
+ timer_mod(env->cpu_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + time);
}
/* Store CPU Timer */
diff --git a/target-sh4/Makefile.objs b/target-sh4/Makefile.objs
index cb448a8..a285358 100644
--- a/target-sh4/Makefile.objs
+++ b/target-sh4/Makefile.objs
@@ -1 +1,2 @@
obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h
index 7c9160b..c04e786 100644
--- a/target-sh4/cpu-qom.h
+++ b/target-sh4/cpu-qom.h
@@ -87,5 +87,7 @@
void superh_cpu_dump_state(CPUState *cpu, FILE *f,
fprintf_function cpu_fprintf, int flags);
hwaddr superh_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int superh_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int superh_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#endif
diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c
index 51a7757..34b2b57 100644
--- a/target-sh4/cpu.c
+++ b/target-sh4/cpu.c
@@ -240,10 +240,11 @@
static void superh_cpu_realizefn(DeviceState *dev, Error **errp)
{
- SuperHCPU *cpu = SUPERH_CPU(dev);
+ CPUState *cs = CPU(dev);
SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(dev);
- cpu_reset(CPU(cpu));
+ cpu_reset(cs);
+ qemu_init_vcpu(cs);
scc->parent_realize(dev, errp);
}
@@ -286,10 +287,13 @@
cc->dump_state = superh_cpu_dump_state;
cc->set_pc = superh_cpu_set_pc;
cc->synchronize_from_tb = superh_cpu_synchronize_from_tb;
+ cc->gdb_read_register = superh_cpu_gdb_read_register;
+ cc->gdb_write_register = superh_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = superh_cpu_get_phys_page_debug;
#endif
dc->vmsd = &vmstate_sh_cpu;
+ cc->gdb_num_core_regs = 59;
}
static const TypeInfo superh_cpu_type_info = {
diff --git a/target-sh4/gdbstub.c b/target-sh4/gdbstub.c
new file mode 100644
index 0000000..df4fa2a
--- /dev/null
+++ b/target-sh4/gdbstub.c
@@ -0,0 +1,146 @@
+/*
+ * SuperH gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+/* Hint: Use "set architecture sh4" in GDB to see fpu registers */
+/* FIXME: We should use XML for this. */
+
+int superh_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ SuperHCPU *cpu = SUPERH_CPU(cs);
+ CPUSH4State *env = &cpu->env;
+
+ switch (n) {
+ case 0 ... 7:
+ if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
+ return gdb_get_regl(mem_buf, env->gregs[n + 16]);
+ } else {
+ return gdb_get_regl(mem_buf, env->gregs[n]);
+ }
+ case 8 ... 15:
+ return gdb_get_regl(mem_buf, env->gregs[n]);
+ case 16:
+ return gdb_get_regl(mem_buf, env->pc);
+ case 17:
+ return gdb_get_regl(mem_buf, env->pr);
+ case 18:
+ return gdb_get_regl(mem_buf, env->gbr);
+ case 19:
+ return gdb_get_regl(mem_buf, env->vbr);
+ case 20:
+ return gdb_get_regl(mem_buf, env->mach);
+ case 21:
+ return gdb_get_regl(mem_buf, env->macl);
+ case 22:
+ return gdb_get_regl(mem_buf, env->sr);
+ case 23:
+ return gdb_get_regl(mem_buf, env->fpul);
+ case 24:
+ return gdb_get_regl(mem_buf, env->fpscr);
+ case 25 ... 40:
+ if (env->fpscr & FPSCR_FR) {
+ stfl_p(mem_buf, env->fregs[n - 9]);
+ } else {
+ stfl_p(mem_buf, env->fregs[n - 25]);
+ }
+ return 4;
+ case 41:
+ return gdb_get_regl(mem_buf, env->ssr);
+ case 42:
+ return gdb_get_regl(mem_buf, env->spc);
+ case 43 ... 50:
+ return gdb_get_regl(mem_buf, env->gregs[n - 43]);
+ case 51 ... 58:
+ return gdb_get_regl(mem_buf, env->gregs[n - (51 - 16)]);
+ }
+
+ return 0;
+}
+
+int superh_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ SuperHCPU *cpu = SUPERH_CPU(cs);
+ CPUSH4State *env = &cpu->env;
+
+ switch (n) {
+ case 0 ... 7:
+ if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
+ env->gregs[n + 16] = ldl_p(mem_buf);
+ } else {
+ env->gregs[n] = ldl_p(mem_buf);
+ }
+ break;
+ case 8 ... 15:
+ env->gregs[n] = ldl_p(mem_buf);
+ break;
+ case 16:
+ env->pc = ldl_p(mem_buf);
+ break;
+ case 17:
+ env->pr = ldl_p(mem_buf);
+ break;
+ case 18:
+ env->gbr = ldl_p(mem_buf);
+ break;
+ case 19:
+ env->vbr = ldl_p(mem_buf);
+ break;
+ case 20:
+ env->mach = ldl_p(mem_buf);
+ break;
+ case 21:
+ env->macl = ldl_p(mem_buf);
+ break;
+ case 22:
+ env->sr = ldl_p(mem_buf);
+ break;
+ case 23:
+ env->fpul = ldl_p(mem_buf);
+ break;
+ case 24:
+ env->fpscr = ldl_p(mem_buf);
+ break;
+ case 25 ... 40:
+ if (env->fpscr & FPSCR_FR) {
+ env->fregs[n - 9] = ldfl_p(mem_buf);
+ } else {
+ env->fregs[n - 25] = ldfl_p(mem_buf);
+ }
+ break;
+ case 41:
+ env->ssr = ldl_p(mem_buf);
+ break;
+ case 42:
+ env->spc = ldl_p(mem_buf);
+ break;
+ case 43 ... 50:
+ env->gregs[n - 43] = ldl_p(mem_buf);
+ break;
+ case 51 ... 58:
+ env->gregs[n - (51 - 16)] = ldl_p(mem_buf);
+ break;
+ default:
+ return 0;
+ }
+
+ return 4;
+}
diff --git a/target-sparc/Makefile.objs b/target-sparc/Makefile.objs
index 9fc42ea..1cd81cc 100644
--- a/target-sparc/Makefile.objs
+++ b/target-sparc/Makefile.objs
@@ -4,3 +4,4 @@
obj-$(TARGET_SPARC) += int32_helper.o
obj-$(TARGET_SPARC64) += int64_helper.o
obj-$(TARGET_SPARC64) += vis_helper.o
+obj-y += gdbstub.o
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
index 39d975b..8e3e0de 100644
--- a/target-sparc/cpu-qom.h
+++ b/target-sparc/cpu-qom.h
@@ -79,5 +79,7 @@
void sparc_cpu_dump_state(CPUState *cpu, FILE *f,
fprintf_function cpu_fprintf, int flags);
hwaddr sparc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int sparc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int sparc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#endif
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index d1d0339..47ce60d 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -743,6 +743,8 @@
{
SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
+ qemu_init_vcpu(CPU(dev));
+
scc->parent_realize(dev, errp);
}
@@ -787,10 +789,18 @@
#endif
cc->set_pc = sparc_cpu_set_pc;
cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
+ cc->gdb_read_register = sparc_cpu_gdb_read_register;
+ cc->gdb_write_register = sparc_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->do_unassigned_access = sparc_cpu_unassigned_access;
cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
#endif
+
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
+ cc->gdb_num_core_regs = 86;
+#else
+ cc->gdb_num_core_regs = 72;
+#endif
}
static const TypeInfo sparc_cpu_type_info = {
diff --git a/target-sparc/gdbstub.c b/target-sparc/gdbstub.c
new file mode 100644
index 0000000..3de3242
--- /dev/null
+++ b/target-sparc/gdbstub.c
@@ -0,0 +1,208 @@
+/*
+ * SPARC gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+#ifdef TARGET_ABI32
+#define gdb_get_rega(buf, val) gdb_get_reg32(buf, val)
+#else
+#define gdb_get_rega(buf, val) gdb_get_regl(buf, val)
+#endif
+
+int sparc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ SPARCCPU *cpu = SPARC_CPU(cs);
+ CPUSPARCState *env = &cpu->env;
+
+ if (n < 8) {
+ /* g0..g7 */
+ return gdb_get_rega(mem_buf, env->gregs[n]);
+ }
+ if (n < 32) {
+ /* register window */
+ return gdb_get_rega(mem_buf, env->regwptr[n - 8]);
+ }
+#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
+ if (n < 64) {
+ /* fprs */
+ if (n & 1) {
+ return gdb_get_reg32(mem_buf, env->fpr[(n - 32) / 2].l.lower);
+ } else {
+ return gdb_get_reg32(mem_buf, env->fpr[(n - 32) / 2].l.upper);
+ }
+ }
+ /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
+ switch (n) {
+ case 64:
+ return gdb_get_rega(mem_buf, env->y);
+ case 65:
+ return gdb_get_rega(mem_buf, cpu_get_psr(env));
+ case 66:
+ return gdb_get_rega(mem_buf, env->wim);
+ case 67:
+ return gdb_get_rega(mem_buf, env->tbr);
+ case 68:
+ return gdb_get_rega(mem_buf, env->pc);
+ case 69:
+ return gdb_get_rega(mem_buf, env->npc);
+ case 70:
+ return gdb_get_rega(mem_buf, env->fsr);
+ case 71:
+ return gdb_get_rega(mem_buf, 0); /* csr */
+ default:
+ return gdb_get_rega(mem_buf, 0);
+ }
+#else
+ if (n < 64) {
+ /* f0-f31 */
+ if (n & 1) {
+ return gdb_get_reg32(mem_buf, env->fpr[(n - 32) / 2].l.lower);
+ } else {
+ return gdb_get_reg32(mem_buf, env->fpr[(n - 32) / 2].l.upper);
+ }
+ }
+ if (n < 80) {
+ /* f32-f62 (double width, even numbers only) */
+ return gdb_get_reg64(mem_buf, env->fpr[(n - 32) / 2].ll);
+ }
+ switch (n) {
+ case 80:
+ return gdb_get_regl(mem_buf, env->pc);
+ case 81:
+ return gdb_get_regl(mem_buf, env->npc);
+ case 82:
+ return gdb_get_regl(mem_buf, (cpu_get_ccr(env) << 32) |
+ ((env->asi & 0xff) << 24) |
+ ((env->pstate & 0xfff) << 8) |
+ cpu_get_cwp64(env));
+ case 83:
+ return gdb_get_regl(mem_buf, env->fsr);
+ case 84:
+ return gdb_get_regl(mem_buf, env->fprs);
+ case 85:
+ return gdb_get_regl(mem_buf, env->y);
+ }
+#endif
+ return 0;
+}
+
+int sparc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ SPARCCPU *cpu = SPARC_CPU(cs);
+ CPUSPARCState *env = &cpu->env;
+#if defined(TARGET_ABI32)
+ abi_ulong tmp;
+
+ tmp = ldl_p(mem_buf);
+#else
+ target_ulong tmp;
+
+ tmp = ldtul_p(mem_buf);
+#endif
+
+ if (n < 8) {
+ /* g0..g7 */
+ env->gregs[n] = tmp;
+ } else if (n < 32) {
+ /* register window */
+ env->regwptr[n - 8] = tmp;
+ }
+#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
+ else if (n < 64) {
+ /* fprs */
+ /* f0-f31 */
+ if (n & 1) {
+ env->fpr[(n - 32) / 2].l.lower = tmp;
+ } else {
+ env->fpr[(n - 32) / 2].l.upper = tmp;
+ }
+ } else {
+ /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
+ switch (n) {
+ case 64:
+ env->y = tmp;
+ break;
+ case 65:
+ cpu_put_psr(env, tmp);
+ break;
+ case 66:
+ env->wim = tmp;
+ break;
+ case 67:
+ env->tbr = tmp;
+ break;
+ case 68:
+ env->pc = tmp;
+ break;
+ case 69:
+ env->npc = tmp;
+ break;
+ case 70:
+ env->fsr = tmp;
+ break;
+ default:
+ return 0;
+ }
+ }
+ return 4;
+#else
+ else if (n < 64) {
+ /* f0-f31 */
+ tmp = ldl_p(mem_buf);
+ if (n & 1) {
+ env->fpr[(n - 32) / 2].l.lower = tmp;
+ } else {
+ env->fpr[(n - 32) / 2].l.upper = tmp;
+ }
+ return 4;
+ } else if (n < 80) {
+ /* f32-f62 (double width, even numbers only) */
+ env->fpr[(n - 32) / 2].ll = tmp;
+ } else {
+ switch (n) {
+ case 80:
+ env->pc = tmp;
+ break;
+ case 81:
+ env->npc = tmp;
+ break;
+ case 82:
+ cpu_put_ccr(env, tmp >> 32);
+ env->asi = (tmp >> 24) & 0xff;
+ env->pstate = (tmp >> 8) & 0xfff;
+ cpu_put_cwp64(env, tmp & 0xff);
+ break;
+ case 83:
+ env->fsr = tmp;
+ break;
+ case 84:
+ env->fprs = tmp;
+ break;
+ case 85:
+ env->y = tmp;
+ break;
+ default:
+ return 0;
+ }
+ }
+ return 8;
+#endif
+}
diff --git a/target-unicore32/cpu.c b/target-unicore32/cpu.c
index 46813e5..3f78208 100644
--- a/target-unicore32/cpu.c
+++ b/target-unicore32/cpu.c
@@ -92,6 +92,8 @@
{
UniCore32CPUClass *ucc = UNICORE32_CPU_GET_CLASS(dev);
+ qemu_init_vcpu(CPU(dev));
+
ucc->parent_realize(dev, errp);
}
diff --git a/target-xtensa/Makefile.objs b/target-xtensa/Makefile.objs
index 644b7f9..5c150a8 100644
--- a/target-xtensa/Makefile.objs
+++ b/target-xtensa/Makefile.objs
@@ -3,3 +3,4 @@
obj-y += core-dc233c.o
obj-y += core-fsf.o
obj-y += translate.o op_helper.o helper.o cpu.o
+obj-y += gdbstub.o
diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h
index b9896f2..c6cc2d9 100644
--- a/target-xtensa/cpu-qom.h
+++ b/target-xtensa/cpu-qom.h
@@ -45,6 +45,7 @@
* XtensaCPUClass:
* @parent_realize: The parent class' realize handler.
* @parent_reset: The parent class' reset handler.
+ * @config: The CPU core configuration.
*
* An Xtensa CPU model.
*/
@@ -55,6 +56,8 @@
DeviceRealize parent_realize;
void (*parent_reset)(CPUState *cpu);
+
+ const XtensaConfig *config;
} XtensaCPUClass;
/**
@@ -84,5 +87,7 @@
void xtensa_cpu_dump_state(CPUState *cpu, FILE *f,
fprintf_function cpu_fprintf, int flags);
hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+int xtensa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#endif
diff --git a/target-xtensa/cpu.c b/target-xtensa/cpu.c
index d2bcfc6..c19d17a 100644
--- a/target-xtensa/cpu.c
+++ b/target-xtensa/cpu.c
@@ -64,10 +64,34 @@
reset_mmu(env);
}
+static ObjectClass *xtensa_cpu_class_by_name(const char *cpu_model)
+{
+ ObjectClass *oc;
+ char *typename;
+
+ if (cpu_model == NULL) {
+ return NULL;
+ }
+
+ typename = g_strdup_printf("%s-" TYPE_XTENSA_CPU, cpu_model);
+ oc = object_class_by_name(typename);
+ g_free(typename);
+ if (oc == NULL || !object_class_dynamic_cast(oc, TYPE_XTENSA_CPU) ||
+ object_class_is_abstract(oc)) {
+ return NULL;
+ }
+ return oc;
+}
+
static void xtensa_cpu_realizefn(DeviceState *dev, Error **errp)
{
+ CPUState *cs = CPU(dev);
XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(dev);
+ cs->gdb_num_regs = xcc->config->gdb_regmap.num_regs;
+
+ qemu_init_vcpu(cs);
+
xcc->parent_realize(dev, errp);
}
@@ -75,10 +99,12 @@
{
CPUState *cs = CPU(obj);
XtensaCPU *cpu = XTENSA_CPU(obj);
+ XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(obj);
CPUXtensaState *env = &cpu->env;
static bool tcg_inited;
cs->env_ptr = env;
+ env->config = xcc->config;
cpu_exec_init(env);
if (tcg_enabled() && !tcg_inited) {
@@ -105,9 +131,12 @@
xcc->parent_reset = cc->reset;
cc->reset = xtensa_cpu_reset;
+ cc->class_by_name = xtensa_cpu_class_by_name;
cc->do_interrupt = xtensa_cpu_do_interrupt;
cc->dump_state = xtensa_cpu_dump_state;
cc->set_pc = xtensa_cpu_set_pc;
+ cc->gdb_read_register = xtensa_cpu_gdb_read_register;
+ cc->gdb_write_register = xtensa_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug;
#endif
@@ -119,7 +148,7 @@
.parent = TYPE_CPU,
.instance_size = sizeof(XtensaCPU),
.instance_init = xtensa_cpu_initfn,
- .abstract = false,
+ .abstract = true,
.class_size = sizeof(XtensaCPUClass),
.class_init = xtensa_cpu_class_init,
};
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index a8f02f6..95103e9 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -484,6 +484,7 @@
#define XTENSA_TBFLAG_ICOUNT 0x20
#define XTENSA_TBFLAG_CPENABLE_MASK 0x3fc0
#define XTENSA_TBFLAG_CPENABLE_SHIFT 6
+#define XTENSA_TBFLAG_EXCEPTION 0x4000
static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
@@ -510,6 +511,9 @@
if (xtensa_option_enabled(env->config, XTENSA_OPTION_COPROCESSOR)) {
*flags |= env->sregs[CPENABLE] << XTENSA_TBFLAG_CPENABLE_SHIFT;
}
+ if (ENV_GET_CPU(env)->singlestep_enabled && env->exception_taken) {
+ *flags |= XTENSA_TBFLAG_EXCEPTION;
+ }
}
#include "exec/cpu-all.h"
diff --git a/target-xtensa/gdbstub.c b/target-xtensa/gdbstub.c
new file mode 100644
index 0000000..9e13b20
--- /dev/null
+++ b/target-xtensa/gdbstub.c
@@ -0,0 +1,109 @@
+/*
+ * Xtensa gdb server stub
+ *
+ * Copyright (c) 2003-2005 Fabrice Bellard
+ * Copyright (c) 2013 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 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/>.
+ */
+#include "config.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+int xtensa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ XtensaCPU *cpu = XTENSA_CPU(cs);
+ CPUXtensaState *env = &cpu->env;
+ const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
+
+ if (n < 0 || n >= env->config->gdb_regmap.num_regs) {
+ return 0;
+ }
+
+ switch (reg->type) {
+ case 9: /*pc*/
+ return gdb_get_reg32(mem_buf, env->pc);
+
+ case 1: /*ar*/
+ xtensa_sync_phys_from_window(env);
+ return gdb_get_reg32(mem_buf, env->phys_regs[(reg->targno & 0xff)
+ % env->config->nareg]);
+
+ case 2: /*SR*/
+ return gdb_get_reg32(mem_buf, env->sregs[reg->targno & 0xff]);
+
+ case 3: /*UR*/
+ return gdb_get_reg32(mem_buf, env->uregs[reg->targno & 0xff]);
+
+ case 4: /*f*/
+ return gdb_get_reg32(mem_buf, float32_val(env->fregs[reg->targno
+ & 0x0f]));
+
+ case 8: /*a*/
+ return gdb_get_reg32(mem_buf, env->regs[reg->targno & 0x0f]);
+
+ default:
+ qemu_log("%s from reg %d of unsupported type %d\n",
+ __func__, n, reg->type);
+ return 0;
+ }
+}
+
+int xtensa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ XtensaCPU *cpu = XTENSA_CPU(cs);
+ CPUXtensaState *env = &cpu->env;
+ uint32_t tmp;
+ const XtensaGdbReg *reg = env->config->gdb_regmap.reg + n;
+
+ if (n < 0 || n >= env->config->gdb_regmap.num_regs) {
+ return 0;
+ }
+
+ tmp = ldl_p(mem_buf);
+
+ switch (reg->type) {
+ case 9: /*pc*/
+ env->pc = tmp;
+ break;
+
+ case 1: /*ar*/
+ env->phys_regs[(reg->targno & 0xff) % env->config->nareg] = tmp;
+ xtensa_sync_window_from_phys(env);
+ break;
+
+ case 2: /*SR*/
+ env->sregs[reg->targno & 0xff] = tmp;
+ break;
+
+ case 3: /*UR*/
+ env->uregs[reg->targno & 0xff] = tmp;
+ break;
+
+ case 4: /*f*/
+ env->fregs[reg->targno & 0x0f] = make_float32(tmp);
+ break;
+
+ case 8: /*a*/
+ env->regs[reg->targno & 0x0f] = tmp;
+ break;
+
+ default:
+ qemu_log("%s to reg %d of unsupported type %d\n",
+ __func__, n, reg->type);
+ return 0;
+ }
+
+ return 4;
+}
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index de6cc3b..a0f9993 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -35,10 +35,35 @@
static struct XtensaConfigList *xtensa_cores;
+static void xtensa_core_class_init(ObjectClass *oc, void *data)
+{
+ CPUClass *cc = CPU_CLASS(oc);
+ XtensaCPUClass *xcc = XTENSA_CPU_CLASS(oc);
+ const XtensaConfig *config = data;
+
+ xcc->config = config;
+
+ /* Use num_core_regs to see only non-privileged registers in an unmodified
+ * gdb. Use num_regs to see all registers. gdb modification is required
+ * for that: reset bit 0 in the 'flags' field of the registers definitions
+ * in the gdb/xtensa-config.c inside gdb source tree or inside gdb overlay.
+ */
+ cc->gdb_num_core_regs = config->gdb_regmap.num_regs;
+}
+
void xtensa_register_core(XtensaConfigList *node)
{
+ TypeInfo type = {
+ .parent = TYPE_XTENSA_CPU,
+ .class_init = xtensa_core_class_init,
+ .class_data = (void *)node->config,
+ };
+
node->next = xtensa_cores;
xtensa_cores = node;
+ type.name = g_strdup_printf("%s-" TYPE_XTENSA_CPU, node->config->name);
+ type_register(&type);
+ g_free((gpointer)type.name);
}
static uint32_t check_hw_breakpoints(CPUXtensaState *env)
@@ -72,24 +97,17 @@
XtensaCPU *cpu_xtensa_init(const char *cpu_model)
{
+ ObjectClass *oc;
XtensaCPU *cpu;
CPUXtensaState *env;
- const XtensaConfig *config = NULL;
- XtensaConfigList *core = xtensa_cores;
- for (; core; core = core->next)
- if (strcmp(core->config->name, cpu_model) == 0) {
- config = core->config;
- break;
- }
-
- if (config == NULL) {
+ oc = cpu_class_by_name(TYPE_XTENSA_CPU, cpu_model);
+ if (oc == NULL) {
return NULL;
}
- cpu = XTENSA_CPU(object_new(TYPE_XTENSA_CPU));
+ cpu = XTENSA_CPU(object_new(object_class_get_name(oc)));
env = &cpu->env;
- env->config = config;
xtensa_irq_init(env);
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 4c41de0..01123af 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -96,6 +96,9 @@
void HELPER(exception)(CPUXtensaState *env, uint32_t excp)
{
env->exception_index = excp;
+ if (excp == EXCP_DEBUG) {
+ env->exception_taken = 0;
+ }
cpu_loop_exit(env);
}
@@ -387,7 +390,7 @@
}
cpu = CPU(xtensa_env_get_cpu(env));
- env->halt_clock = qemu_get_clock_ns(vm_clock);
+ env->halt_clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
cpu->halted = 1;
if (xtensa_option_enabled(env->config, XTENSA_OPTION_TIMER_INTERRUPT)) {
xtensa_rearm_ccompare_timer(env);
@@ -448,8 +451,10 @@
switch (access & PAGE_CACHE_MASK) {
case PAGE_CACHE_WB:
atomctl >>= 2;
+ /* fall through */
case PAGE_CACHE_WT:
atomctl >>= 2;
+ /* fall through */
case PAGE_CACHE_BYPASS:
if ((atomctl & 0x3) == 0) {
HELPER(exception_cause_vaddr)(env, pc,
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index e692329..504cc53 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -305,16 +305,21 @@
tcg_temp_free(tmp);
}
-static void gen_advance_ccount(DisasContext *dc)
+static void gen_advance_ccount_cond(DisasContext *dc)
{
if (dc->ccount_delta > 0) {
TCGv_i32 tmp = tcg_const_i32(dc->ccount_delta);
- dc->ccount_delta = 0;
gen_helper_advance_ccount(cpu_env, tmp);
tcg_temp_free(tmp);
}
}
+static void gen_advance_ccount(DisasContext *dc)
+{
+ gen_advance_ccount_cond(dc);
+ dc->ccount_delta = 0;
+}
+
static void reset_used_window(DisasContext *dc)
{
dc->used_window = 0;
@@ -491,7 +496,7 @@
tcg_temp_free(tmp);
}
-static void gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access)
+static bool gen_check_sr(DisasContext *dc, uint32_t sr, unsigned access)
{
if (!xtensa_option_bits_enabled(dc->config, sregnames[sr].opt_bits)) {
if (sregnames[sr].name) {
@@ -500,6 +505,7 @@
qemu_log("SR %d is not implemented\n", sr);
}
gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
+ return false;
} else if (!(sregnames[sr].access & access)) {
static const char * const access_text[] = {
[SR_R] = "rsr",
@@ -510,7 +516,9 @@
qemu_log("SR %s is not available for %s\n", sregnames[sr].name,
access_text[access]);
gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
+ return false;
}
+ return true;
}
static void gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr)
@@ -826,15 +834,27 @@
}
if (option_enabled(dc, XTENSA_OPTION_WINDOWED_REGISTER) &&
r1 / 4 > dc->used_window) {
- TCGv_i32 pc = tcg_const_i32(dc->pc);
- TCGv_i32 w = tcg_const_i32(r1 / 4);
+ int label = gen_new_label();
+ TCGv_i32 ws = tcg_temp_new_i32();
dc->used_window = r1 / 4;
- gen_advance_ccount(dc);
- gen_helper_window_check(cpu_env, pc, w);
+ tcg_gen_deposit_i32(ws, cpu_SR[WINDOW_START], cpu_SR[WINDOW_START],
+ dc->config->nareg / 4, dc->config->nareg / 4);
+ tcg_gen_shr_i32(ws, ws, cpu_SR[WINDOW_BASE]);
+ tcg_gen_andi_i32(ws, ws, (2 << (r1 / 4)) - 2);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, ws, 0, label);
+ {
+ TCGv_i32 pc = tcg_const_i32(dc->pc);
+ TCGv_i32 w = tcg_const_i32(r1 / 4);
- tcg_temp_free(w);
- tcg_temp_free(pc);
+ gen_advance_ccount_cond(dc);
+ gen_helper_window_check(cpu_env, pc, w);
+
+ tcg_temp_free(w);
+ tcg_temp_free(pc);
+ }
+ gen_set_label(label);
+ tcg_temp_free(ws);
}
}
@@ -1482,9 +1502,9 @@
break;
case 6: /*XSR*/
- {
+ if (gen_check_sr(dc, RSR_SR, SR_X)) {
TCGv_i32 tmp = tcg_temp_new_i32();
- gen_check_sr(dc, RSR_SR, SR_X);
+
if (RSR_SR >= 64) {
gen_check_privilege(dc);
}
@@ -1707,21 +1727,23 @@
case 3: /*RST3*/
switch (OP2) {
case 0: /*RSR*/
- gen_check_sr(dc, RSR_SR, SR_R);
- if (RSR_SR >= 64) {
- gen_check_privilege(dc);
+ if (gen_check_sr(dc, RSR_SR, SR_R)) {
+ if (RSR_SR >= 64) {
+ gen_check_privilege(dc);
+ }
+ gen_window_check1(dc, RRR_T);
+ gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
}
- gen_window_check1(dc, RRR_T);
- gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
break;
case 1: /*WSR*/
- gen_check_sr(dc, RSR_SR, SR_W);
- if (RSR_SR >= 64) {
- gen_check_privilege(dc);
+ if (gen_check_sr(dc, RSR_SR, SR_W)) {
+ if (RSR_SR >= 64) {
+ gen_check_privilege(dc);
+ }
+ gen_window_check1(dc, RRR_T);
+ gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
}
- gen_window_check1(dc, RRR_T);
- gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
break;
case 2: /*SEXTu*/
@@ -2918,8 +2940,7 @@
gen_tb_start();
- if (cs->singlestep_enabled && env->exception_taken) {
- env->exception_taken = 0;
+ if (tb->flags & XTENSA_TBFLAG_EXCEPTION) {
tcg_gen_movi_i32(cpu_pc, dc.pc);
gen_exception(&dc, EXCP_DEBUG);
}
diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c
index 562a549..41a17f8 100644
--- a/tcg/aarch64/tcg-target.c
+++ b/tcg/aarch64/tcg-target.c
@@ -315,6 +315,17 @@
tcg_out32(s, op_data << 24 | mod << 20 | off << 12 | rn << 5 | rd);
}
+/* tcg_out_ldst_12 expects a scaled unsigned immediate offset */
+static inline void tcg_out_ldst_12(TCGContext *s,
+ enum aarch64_ldst_op_data op_data,
+ enum aarch64_ldst_op_type op_type,
+ TCGReg rd, TCGReg rn,
+ tcg_target_ulong scaled_uimm)
+{
+ tcg_out32(s, (op_data | 1) << 24
+ | op_type << 20 | scaled_uimm << 10 | rn << 5 | rd);
+}
+
static inline void tcg_out_movr(TCGContext *s, int ext, TCGReg rd, TCGReg src)
{
/* register to register move using MOV (shifted register with no shift) */
@@ -374,10 +385,25 @@
{
if (offset >= -256 && offset < 256) {
tcg_out_ldst_9(s, data, type, rd, rn, offset);
- } else {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset);
- tcg_out_ldst_r(s, data, type, rd, rn, TCG_REG_TMP);
+ return;
}
+
+ if (offset >= 256) {
+ /* if the offset is naturally aligned and in range,
+ then we can use the scaled uimm12 encoding */
+ unsigned int s_bits = data >> 6;
+ if (!(offset & ((1 << s_bits) - 1))) {
+ tcg_target_ulong scaled_uimm = offset >> s_bits;
+ if (scaled_uimm <= 0xfff) {
+ tcg_out_ldst_12(s, data, type, rd, rn, scaled_uimm);
+ return;
+ }
+ }
+ }
+
+ /* worst-case scenario, move offset to temp register, use reg offset */
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset);
+ tcg_out_ldst_r(s, data, type, rd, rn, TCG_REG_TMP);
}
/* mov alias implemented with add immediate, useful to move to/from SP */
@@ -706,6 +732,51 @@
tcg_out_ubfm(s, 0, rd, rn, 0, bits);
}
+static inline void tcg_out_addi(TCGContext *s, int ext,
+ TCGReg rd, TCGReg rn, unsigned int aimm)
+{
+ /* add immediate aimm unsigned 12bit value (with LSL 0 or 12) */
+ /* using ADD 0x11000000 | (ext) | (aimm << 10) | (rn << 5) | rd */
+ unsigned int base = ext ? 0x91000000 : 0x11000000;
+
+ if (aimm <= 0xfff) {
+ aimm <<= 10;
+ } else {
+ /* we can only shift left by 12, on assert we cannot represent */
+ assert(!(aimm & 0xfff));
+ assert(aimm <= 0xfff000);
+ base |= 1 << 22; /* apply LSL 12 */
+ aimm >>= 2;
+ }
+
+ tcg_out32(s, base | aimm | (rn << 5) | rd);
+}
+
+static inline void tcg_out_subi(TCGContext *s, int ext,
+ TCGReg rd, TCGReg rn, unsigned int aimm)
+{
+ /* sub immediate aimm unsigned 12bit value (with LSL 0 or 12) */
+ /* using SUB 0x51000000 | (ext) | (aimm << 10) | (rn << 5) | rd */
+ unsigned int base = ext ? 0xd1000000 : 0x51000000;
+
+ if (aimm <= 0xfff) {
+ aimm <<= 10;
+ } else {
+ /* we can only shift left by 12, on assert we cannot represent */
+ assert(!(aimm & 0xfff));
+ assert(aimm <= 0xfff000);
+ base |= 1 << 22; /* apply LSL 12 */
+ aimm >>= 2;
+ }
+
+ tcg_out32(s, base | aimm | (rn << 5) | rd);
+}
+
+static inline void tcg_out_nop(TCGContext *s)
+{
+ tcg_out32(s, 0xd503201f);
+}
+
#ifdef CONFIG_SOFTMMU
#include "exec/softmmu_defs.h"
@@ -727,7 +798,125 @@
helper_stq_mmu,
};
-#else /* !CONFIG_SOFTMMU */
+static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+{
+ reloc_pc19(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
+ tcg_out_movr(s, 1, TCG_REG_X0, TCG_AREG0);
+ tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, lb->addrlo_reg);
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, lb->mem_index);
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP,
+ (tcg_target_long)qemu_ld_helpers[lb->opc & 3]);
+ tcg_out_callr(s, TCG_REG_TMP);
+ if (lb->opc & 0x04) {
+ tcg_out_sxt(s, 1, lb->opc & 3, lb->datalo_reg, TCG_REG_X0);
+ } else {
+ tcg_out_movr(s, 1, lb->datalo_reg, TCG_REG_X0);
+ }
+
+ tcg_out_goto(s, (tcg_target_long)lb->raddr);
+}
+
+static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+{
+ reloc_pc19(lb->label_ptr[0], (tcg_target_long)s->code_ptr);
+
+ tcg_out_movr(s, 1, TCG_REG_X0, TCG_AREG0);
+ tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, lb->addrlo_reg);
+ tcg_out_movr(s, 1, TCG_REG_X2, lb->datalo_reg);
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, lb->mem_index);
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP,
+ (tcg_target_long)qemu_st_helpers[lb->opc & 3]);
+ tcg_out_callr(s, TCG_REG_TMP);
+
+ tcg_out_nop(s);
+ tcg_out_goto(s, (tcg_target_long)lb->raddr);
+}
+
+void tcg_out_tb_finalize(TCGContext *s)
+{
+ int i;
+ for (i = 0; i < s->nb_qemu_ldst_labels; i++) {
+ TCGLabelQemuLdst *label = &s->qemu_ldst_labels[i];
+ if (label->is_ld) {
+ tcg_out_qemu_ld_slow_path(s, label);
+ } else {
+ tcg_out_qemu_st_slow_path(s, label);
+ }
+ }
+}
+
+static void add_qemu_ldst_label(TCGContext *s, int is_ld, int opc,
+ TCGReg data_reg, TCGReg addr_reg,
+ int mem_index,
+ uint8_t *raddr, uint8_t *label_ptr)
+{
+ int idx;
+ TCGLabelQemuLdst *label;
+
+ if (s->nb_qemu_ldst_labels >= TCG_MAX_QEMU_LDST) {
+ tcg_abort();
+ }
+
+ idx = s->nb_qemu_ldst_labels++;
+ label = &s->qemu_ldst_labels[idx];
+ label->is_ld = is_ld;
+ label->opc = opc;
+ label->datalo_reg = data_reg;
+ label->addrlo_reg = addr_reg;
+ label->mem_index = mem_index;
+ label->raddr = raddr;
+ label->label_ptr[0] = label_ptr;
+}
+
+/* Load and compare a TLB entry, emitting the conditional jump to the
+ slow path for the failure case, which will be patched later when finalizing
+ the slow path. Generated code returns the host addend in X1,
+ clobbers X0,X2,X3,TMP. */
+static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg,
+ int s_bits, uint8_t **label_ptr, int mem_index, int is_read)
+{
+ TCGReg base = TCG_AREG0;
+ int tlb_offset = is_read ?
+ offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
+ : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
+ /* Extract the TLB index from the address into X0.
+ X0<CPU_TLB_BITS:0> =
+ addr_reg<TARGET_PAGE_BITS+CPU_TLB_BITS:TARGET_PAGE_BITS> */
+ tcg_out_ubfm(s, (TARGET_LONG_BITS == 64), TCG_REG_X0, addr_reg,
+ TARGET_PAGE_BITS, TARGET_PAGE_BITS + CPU_TLB_BITS);
+ /* Store the page mask part of the address and the low s_bits into X3.
+ Later this allows checking for equality and alignment at the same time.
+ X3 = addr_reg & (PAGE_MASK | ((1 << s_bits) - 1)) */
+ tcg_out_andi(s, (TARGET_LONG_BITS == 64), TCG_REG_X3, addr_reg,
+ (TARGET_LONG_BITS - TARGET_PAGE_BITS) + s_bits,
+ (TARGET_LONG_BITS - TARGET_PAGE_BITS));
+ /* Add any "high bits" from the tlb offset to the env address into X2,
+ to take advantage of the LSL12 form of the addi instruction.
+ X2 = env + (tlb_offset & 0xfff000) */
+ tcg_out_addi(s, 1, TCG_REG_X2, base, tlb_offset & 0xfff000);
+ /* Merge the tlb index contribution into X2.
+ X2 = X2 + (X0 << CPU_TLB_ENTRY_BITS) */
+ tcg_out_arith(s, ARITH_ADD, 1, TCG_REG_X2, TCG_REG_X2,
+ TCG_REG_X0, -CPU_TLB_ENTRY_BITS);
+ /* Merge "low bits" from tlb offset, load the tlb comparator into X0.
+ X0 = load [X2 + (tlb_offset & 0x000fff)] */
+ tcg_out_ldst(s, TARGET_LONG_BITS == 64 ? LDST_64 : LDST_32,
+ LDST_LD, TCG_REG_X0, TCG_REG_X2,
+ (tlb_offset & 0xfff));
+ /* Load the tlb addend. Do that early to avoid stalling.
+ X1 = load [X2 + (tlb_offset & 0xfff) + offsetof(addend)] */
+ tcg_out_ldst(s, LDST_64, LDST_LD, TCG_REG_X1, TCG_REG_X2,
+ (tlb_offset & 0xfff) + (offsetof(CPUTLBEntry, addend)) -
+ (is_read ? offsetof(CPUTLBEntry, addr_read)
+ : offsetof(CPUTLBEntry, addr_write)));
+ /* Perform the address comparison. */
+ tcg_out_cmp(s, (TARGET_LONG_BITS == 64), TCG_REG_X0, TCG_REG_X3, 0);
+ *label_ptr = s->code_ptr;
+ /* If not equal, we jump to the slow path. */
+ tcg_out_goto_cond_noaddr(s, TCG_COND_NE);
+}
+
+#endif /* CONFIG_SOFTMMU */
static void tcg_out_qemu_ld_direct(TCGContext *s, int opc, TCGReg data_r,
TCGReg addr_r, TCGReg off_r)
@@ -815,13 +1004,13 @@
tcg_abort();
}
}
-#endif /* CONFIG_SOFTMMU */
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
{
TCGReg addr_reg, data_reg;
#ifdef CONFIG_SOFTMMU
int mem_index, s_bits;
+ uint8_t *label_ptr;
#endif
data_reg = args[0];
addr_reg = args[1];
@@ -829,23 +1018,10 @@
#ifdef CONFIG_SOFTMMU
mem_index = args[2];
s_bits = opc & 3;
-
- /* TODO: insert TLB lookup here */
-
- /* all arguments passed via registers */
- tcg_out_movr(s, 1, TCG_REG_X0, TCG_AREG0);
- tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, addr_reg);
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, mem_index);
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP,
- (tcg_target_long)qemu_ld_helpers[s_bits]);
- tcg_out_callr(s, TCG_REG_TMP);
-
- if (opc & 0x04) { /* sign extend */
- tcg_out_sxt(s, 1, s_bits, data_reg, TCG_REG_X0);
- } else {
- tcg_out_movr(s, 1, data_reg, TCG_REG_X0);
- }
-
+ tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 1);
+ tcg_out_qemu_ld_direct(s, opc, data_reg, addr_reg, TCG_REG_X1);
+ add_qemu_ldst_label(s, 1, opc, data_reg, addr_reg,
+ mem_index, s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
tcg_out_qemu_ld_direct(s, opc, data_reg, addr_reg,
GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR);
@@ -857,6 +1033,7 @@
TCGReg addr_reg, data_reg;
#ifdef CONFIG_SOFTMMU
int mem_index, s_bits;
+ uint8_t *label_ptr;
#endif
data_reg = args[0];
addr_reg = args[1];
@@ -865,17 +1042,10 @@
mem_index = args[2];
s_bits = opc & 3;
- /* TODO: insert TLB lookup here */
-
- /* all arguments passed via registers */
- tcg_out_movr(s, 1, TCG_REG_X0, TCG_AREG0);
- tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, addr_reg);
- tcg_out_movr(s, 1, TCG_REG_X2, data_reg);
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, mem_index);
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP,
- (tcg_target_long)qemu_st_helpers[s_bits]);
- tcg_out_callr(s, TCG_REG_TMP);
-
+ tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 0);
+ tcg_out_qemu_st_direct(s, opc, data_reg, addr_reg, TCG_REG_X1);
+ add_qemu_ldst_label(s, 0, opc, data_reg, addr_reg,
+ mem_index, s->code_ptr, label_ptr);
#else /* !CONFIG_SOFTMMU */
tcg_out_qemu_st_direct(s, opc, data_reg, addr_reg,
GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR);
@@ -1318,26 +1488,6 @@
tcg_add_target_add_op_defs(aarch64_op_defs);
}
-static inline void tcg_out_addi(TCGContext *s, int ext,
- TCGReg rd, TCGReg rn, unsigned int aimm)
-{
- /* add immediate aimm unsigned 12bit value (we use LSL 0 - no shift) */
- /* using ADD 0x11000000 | (ext) | (aimm << 10) | (rn << 5) | rd */
- unsigned int base = ext ? 0x91000000 : 0x11000000;
- assert(aimm <= 0xfff);
- tcg_out32(s, base | (aimm << 10) | (rn << 5) | rd);
-}
-
-static inline void tcg_out_subi(TCGContext *s, int ext,
- TCGReg rd, TCGReg rn, unsigned int aimm)
-{
- /* sub immediate aimm unsigned 12bit value (we use LSL 0 - no shift) */
- /* using SUB 0x51000000 | (ext) | (aimm << 10) | (rn << 5) | rd */
- unsigned int base = ext ? 0xd1000000 : 0x51000000;
- assert(aimm <= 0xfff);
- tcg_out32(s, base | (aimm << 10) | (rn << 5) | rd);
-}
-
static void tcg_target_qemu_prologue(TCGContext *s)
{
/* NB: frame sizes are in 16 byte stack units! */
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 87eeab3..12a7ca3 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -190,11 +190,11 @@
/* qemu_ld/st address constraint */
case 'L':
ct->ct |= TCG_CT_REG;
-#if TCG_TARGET_REG_BITS == 64
+ if (TCG_TARGET_REG_BITS == 64) {
tcg_regset_set32(ct->u.regs, 0, 0xffff);
-#else
+ } else {
tcg_regset_set32(ct->u.regs, 0, 0xff);
-#endif
+ }
tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0);
tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1);
break;
@@ -541,20 +541,34 @@
static void tcg_out_movi(TCGContext *s, TCGType type,
TCGReg ret, tcg_target_long arg)
{
+ tcg_target_long diff;
+
if (arg == 0) {
tgen_arithr(s, ARITH_XOR, ret, ret);
return;
- } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
+ }
+ if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
tcg_out_opc(s, OPC_MOVL_Iv + LOWREGMASK(ret), 0, ret, 0);
tcg_out32(s, arg);
- } else if (arg == (int32_t)arg) {
+ return;
+ }
+ if (arg == (int32_t)arg) {
tcg_out_modrm(s, OPC_MOVL_EvIz + P_REXW, 0, ret);
tcg_out32(s, arg);
- } else {
- tcg_out_opc(s, OPC_MOVL_Iv + P_REXW + LOWREGMASK(ret), 0, ret, 0);
- tcg_out32(s, arg);
- tcg_out32(s, arg >> 31 >> 1);
+ return;
}
+
+ /* Try a 7 byte pc-relative lea before the 10 byte movq. */
+ diff = arg - ((tcg_target_long)s->code_ptr + 7);
+ if (diff == (int32_t)diff) {
+ tcg_out_opc(s, OPC_LEA | P_REXW, ret, 0, 0);
+ tcg_out8(s, (LOWREGMASK(ret) << 3) | 5);
+ tcg_out32(s, diff);
+ return;
+ }
+
+ tcg_out_opc(s, OPC_MOVL_Iv + P_REXW + LOWREGMASK(ret), 0, ret, 0);
+ tcg_out64(s, arg);
}
static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
@@ -594,6 +608,14 @@
tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
}
+static inline void tcg_out_sti(TCGContext *s, TCGType type, TCGReg base,
+ tcg_target_long ofs, tcg_target_long val)
+{
+ int opc = OPC_MOVL_EvIz + (type == TCG_TYPE_I64 ? P_REXW : 0);
+ tcg_out_modrm_offset(s, opc, 0, base, ofs);
+ tcg_out32(s, val);
+}
+
static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
{
/* Propagate an opcode prefix, such as P_DATA16. */
@@ -1003,22 +1025,24 @@
#include "exec/softmmu_defs.h"
-/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
- int mmu_idx) */
-static const void *qemu_ld_helpers[4] = {
- helper_ldb_mmu,
- helper_ldw_mmu,
- helper_ldl_mmu,
- helper_ldq_mmu,
+/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
+ * int mmu_idx, uintptr_t ra)
+ */
+static const void * const qemu_ld_helpers[4] = {
+ helper_ret_ldb_mmu,
+ helper_ret_ldw_mmu,
+ helper_ret_ldl_mmu,
+ helper_ret_ldq_mmu,
};
-/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
- uintxx_t val, int mmu_idx) */
-static const void *qemu_st_helpers[4] = {
- helper_stb_mmu,
- helper_stw_mmu,
- helper_stl_mmu,
- helper_stq_mmu,
+/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
+ * uintxx_t val, int mmu_idx, uintptr_t ra)
+ */
+static const void * const qemu_st_helpers[4] = {
+ helper_ret_stb_mmu,
+ helper_ret_stw_mmu,
+ helper_ret_stl_mmu,
+ helper_ret_stq_mmu,
};
static void add_qemu_ldst_label(TCGContext *s,
@@ -1446,25 +1470,21 @@
}
}
+/* See the GETPC definition in include/exec/exec-all.h. */
+static inline uintptr_t do_getpc(uint8_t *raddr)
+{
+ return (uintptr_t)raddr - 1;
+}
+
/*
* Generate code for the slow path for a load at the end of block
*/
-static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *label)
+static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
{
- int s_bits;
- int opc = label->opc;
- int mem_index = label->mem_index;
-#if TCG_TARGET_REG_BITS == 32
- int stack_adjust;
- int addrlo_reg = label->addrlo_reg;
- int addrhi_reg = label->addrhi_reg;
-#endif
- int data_reg = label->datalo_reg;
- int data_reg2 = label->datahi_reg;
- uint8_t *raddr = label->raddr;
- uint8_t **label_ptr = &label->label_ptr[0];
-
- s_bits = opc & 3;
+ int opc = l->opc;
+ int s_bits = opc & 3;
+ TCGReg data_reg;
+ uint8_t **label_ptr = &l->label_ptr[0];
/* resolve label address */
*(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
@@ -1472,52 +1492,36 @@
*(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
}
-#if TCG_TARGET_REG_BITS == 32
- tcg_out_pushi(s, mem_index);
- stack_adjust = 4;
- if (TARGET_LONG_BITS == 64) {
- tcg_out_push(s, addrhi_reg);
- stack_adjust += 4;
+ if (TCG_TARGET_REG_BITS == 32) {
+ int ofs = 0;
+
+ tcg_out_st(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, ofs);
+ ofs += 4;
+
+ tcg_out_st(s, TCG_TYPE_I32, l->addrlo_reg, TCG_REG_ESP, ofs);
+ ofs += 4;
+
+ if (TARGET_LONG_BITS == 64) {
+ tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs);
+ ofs += 4;
+ }
+
+ tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, l->mem_index);
+ ofs += 4;
+
+ tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, do_getpc(l->raddr));
+ } else {
+ tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
+ /* The second argument is already loaded with addrlo. */
+ tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2],
+ l->mem_index);
+ tcg_out_movi(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[3],
+ do_getpc(l->raddr));
}
- tcg_out_push(s, addrlo_reg);
- stack_adjust += 4;
- tcg_out_push(s, TCG_AREG0);
- stack_adjust += 4;
-#else
- tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0);
- /* The second argument is already loaded with addrlo. */
- tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], mem_index);
-#endif
-
- /* Code generation of qemu_ld/st's slow path calling MMU helper
-
- PRE_PROC ...
- call MMU helper
- jmp POST_PROC (2b) : short forward jump <- GETRA()
- jmp next_code (5b) : dummy long backward jump which is never executed
- POST_PROC ... : do post-processing <- GETRA() + 7
- jmp next_code : jump to the code corresponding to next IR of qemu_ld/st
- */
tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
- /* Jump to post-processing code */
- tcg_out8(s, OPC_JMP_short);
- tcg_out8(s, 5);
- /* Dummy backward jump having information of fast path'pc for MMU helpers */
- tcg_out8(s, OPC_JMP_long);
- *(int32_t *)s->code_ptr = (int32_t)(raddr - s->code_ptr - 4);
- s->code_ptr += 4;
-
-#if TCG_TARGET_REG_BITS == 32
- if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
- /* Pop and discard. This is 2 bytes smaller than the add. */
- tcg_out_pop(s, TCG_REG_ECX);
- } else if (stack_adjust != 0) {
- tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust);
- }
-#endif
-
+ data_reg = l->datalo_reg;
switch(opc) {
case 0 | 4:
tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
@@ -1545,10 +1549,10 @@
} else if (data_reg == TCG_REG_EDX) {
/* xchg %edx, %eax */
tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
- tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX);
+ tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EAX);
} else {
tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
- tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX);
+ tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_EDX);
}
break;
default:
@@ -1556,28 +1560,17 @@
}
/* Jump to the code corresponding to next IR of qemu_st */
- tcg_out_jmp(s, (tcg_target_long)raddr);
+ tcg_out_jmp(s, (tcg_target_long)l->raddr);
}
/*
* Generate code for the slow path for a store at the end of block
*/
-static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *label)
+static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
{
- int s_bits;
- int stack_adjust;
- int opc = label->opc;
- int mem_index = label->mem_index;
- int data_reg = label->datalo_reg;
-#if TCG_TARGET_REG_BITS == 32
- int data_reg2 = label->datahi_reg;
- int addrlo_reg = label->addrlo_reg;
- int addrhi_reg = label->addrhi_reg;
-#endif
- uint8_t *raddr = label->raddr;
- uint8_t **label_ptr = &label->label_ptr[0];
-
- s_bits = opc & 3;
+ int opc = l->opc;
+ int s_bits = opc & 3;
+ uint8_t **label_ptr = &l->label_ptr[0];
/* resolve label address */
*(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4);
@@ -1585,61 +1578,56 @@
*(uint32_t *)label_ptr[1] = (uint32_t)(s->code_ptr - label_ptr[1] - 4);
}
-#if TCG_TARGET_REG_BITS == 32
- tcg_out_pushi(s, mem_index);
- stack_adjust = 4;
- if (opc == 3) {
- tcg_out_push(s, data_reg2);
- stack_adjust += 4;
- }
- tcg_out_push(s, data_reg);
- stack_adjust += 4;
- if (TARGET_LONG_BITS == 64) {
- tcg_out_push(s, addrhi_reg);
- stack_adjust += 4;
- }
- tcg_out_push(s, addrlo_reg);
- stack_adjust += 4;
- tcg_out_push(s, TCG_AREG0);
- stack_adjust += 4;
-#else
- tcg_out_mov(s, TCG_TYPE_I64, tcg_target_call_iarg_regs[0], TCG_AREG0);
- /* The second argument is already loaded with addrlo. */
- tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
- tcg_target_call_iarg_regs[2], data_reg);
- tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3], mem_index);
- stack_adjust = 0;
-#endif
+ if (TCG_TARGET_REG_BITS == 32) {
+ int ofs = 0;
- /* Code generation of qemu_ld/st's slow path calling MMU helper
+ tcg_out_st(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, ofs);
+ ofs += 4;
- PRE_PROC ...
- call MMU helper
- jmp POST_PROC (2b) : short forward jump <- GETRA()
- jmp next_code (5b) : dummy long backward jump which is never executed
- POST_PROC ... : do post-processing <- GETRA() + 7
- jmp next_code : jump to the code corresponding to next IR of qemu_ld/st
- */
+ tcg_out_st(s, TCG_TYPE_I32, l->addrlo_reg, TCG_REG_ESP, ofs);
+ ofs += 4;
+
+ if (TARGET_LONG_BITS == 64) {
+ tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs);
+ ofs += 4;
+ }
+
+ tcg_out_st(s, TCG_TYPE_I32, l->datalo_reg, TCG_REG_ESP, ofs);
+ ofs += 4;
+
+ if (opc == 3) {
+ tcg_out_st(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_ESP, ofs);
+ ofs += 4;
+ }
+
+ tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, l->mem_index);
+ ofs += 4;
+
+ tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, do_getpc(l->raddr));
+ } else {
+ uintptr_t pc;
+
+ tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
+ /* The second argument is already loaded with addrlo. */
+ tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
+ tcg_target_call_iarg_regs[2], l->datalo_reg);
+ tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[3],
+ l->mem_index);
+
+ pc = do_getpc(l->raddr);
+ if (ARRAY_SIZE(tcg_target_call_iarg_regs) > 4) {
+ tcg_out_movi(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[4], pc);
+ } else if (pc == (int32_t)pc) {
+ tcg_out_sti(s, TCG_TYPE_PTR, TCG_REG_ESP, 0, pc);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RAX, pc);
+ tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_RAX, TCG_REG_ESP, 0);
+ }
+ }
tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
- /* Jump to post-processing code */
- tcg_out8(s, OPC_JMP_short);
- tcg_out8(s, 5);
- /* Dummy backward jump having information of fast path'pc for MMU helpers */
- tcg_out8(s, OPC_JMP_long);
- *(int32_t *)s->code_ptr = (int32_t)(raddr - s->code_ptr - 4);
- s->code_ptr += 4;
-
- if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
- /* Pop and discard. This is 2 bytes smaller than the add. */
- tcg_out_pop(s, TCG_REG_ECX);
- } else if (stack_adjust != 0) {
- tcg_out_addi(s, TCG_REG_CALL_STACK, stack_adjust);
- }
-
- /* Jump to the code corresponding to next IR of qemu_st */
- tcg_out_jmp(s, (tcg_target_long)raddr);
+ tcg_out_jmp(s, (tcg_target_long)l->raddr);
}
/*
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 373c364..793532e 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1617,19 +1617,29 @@
{ INDEX_op_shl_i32, { "r", "rZ", "ri" } },
{ INDEX_op_shr_i32, { "r", "rZ", "ri" } },
{ INDEX_op_sar_i32, { "r", "rZ", "ri" } },
+#if TCG_TARGET_HAS_rot_i32
{ INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
{ INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
+#endif
+#if TCG_TARGET_HAS_bswap16_i32
{ INDEX_op_bswap16_i32, { "r", "r" } },
+#endif
+#if TCG_TARGET_HAS_bswap32_i32
{ INDEX_op_bswap32_i32, { "r", "r" } },
+#endif
{ INDEX_op_ext8s_i32, { "r", "rZ" } },
{ INDEX_op_ext16s_i32, { "r", "rZ" } },
+#if TCG_TARGET_HAS_deposit_i32
{ INDEX_op_deposit_i32, { "r", "0", "rZ" } },
+#endif
{ INDEX_op_brcond_i32, { "rZ", "rZ" } },
+#if TCG_TARGET_HAS_movcond_i32
{ INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
+#endif
{ INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
diff --git a/tcg/tcg.c b/tcg/tcg.c
index dac8224..19bd5a3 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -121,14 +121,23 @@
static inline void tcg_out16(TCGContext *s, uint16_t v)
{
- *(uint16_t *)s->code_ptr = v;
- s->code_ptr += 2;
+ uint8_t *p = s->code_ptr;
+ *(uint16_t *)p = v;
+ s->code_ptr = p + 2;
}
static inline void tcg_out32(TCGContext *s, uint32_t v)
{
- *(uint32_t *)s->code_ptr = v;
- s->code_ptr += 4;
+ uint8_t *p = s->code_ptr;
+ *(uint32_t *)p = v;
+ s->code_ptr = p + 4;
+}
+
+static inline void tcg_out64(TCGContext *s, uint64_t v)
+{
+ uint8_t *p = s->code_ptr;
+ *(uint64_t *)p = v;
+ s->code_ptr = p + 8;
}
/* label relocation processing */
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index d1241b5..e118bc7 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -34,9 +34,6 @@
tcg_abort(); \
} while (0)
-/* Single bit n. */
-#define BIT(n) (1 << (n))
-
/* Bitfield n...m (in 32 bit value). */
#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
diff --git a/tests/.gitignore b/tests/.gitignore
index fb05c2a..d11cc22 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -11,6 +11,7 @@
test-mul64
test-qapi-types.[ch]
test-qapi-visit.[ch]
+test-qdev-global-props
test-qmp-commands.h
test-qmp-commands
test-qmp-input-strict
diff --git a/tests/Makefile b/tests/Makefile
index 6c34eec..baba9e9 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -23,6 +23,8 @@
gcov-files-test-string-input-visitor-y = qapi/string-input-visitor.c
check-unit-y += tests/test-string-output-visitor$(EXESUF)
gcov-files-test-string-output-visitor-y = qapi/string-output-visitor.c
+check-unit-y += tests/test-opts-visitor$(EXESUF)
+gcov-files-test-opts-visitor-y = qapi/opts-visitor.c
check-unit-y += tests/test-coroutine$(EXESUF)
gcov-files-test-coroutine-y = coroutine-$(CONFIG_COROUTINE_BACKEND).c
check-unit-y += tests/test-visitor-serialization$(EXESUF)
@@ -48,12 +50,14 @@
# all code tested by test-int128 is inside int128.h
gcov-files-test-int128-y =
check-unit-y += tests/test-bitops$(EXESUF)
+check-unit-y += tests/test-qdev-global-props$(EXESUF)
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
# All QTests for now are POSIX-only, but the dependencies are
# really in libqtest, not in the testcases themselves.
-check-qtest-i386-y = tests/fdc-test$(EXESUF)
+check-qtest-i386-y = tests/endianness-test$(EXESUF)
+check-qtest-i386-y += tests/fdc-test$(EXESUF)
gcov-files-i386-y = hw/fdc.c
check-qtest-i386-y += tests/ide-test$(EXESUF)
check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
@@ -65,8 +69,16 @@
check-qtest-x86_64-y = $(check-qtest-i386-y)
gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c
gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
+check-qtest-mips-y = tests/endianness-test$(EXESUF)
+check-qtest-mips64-y = tests/endianness-test$(EXESUF)
+check-qtest-mips64el-y = tests/endianness-test$(EXESUF)
+check-qtest-ppc-y = tests/endianness-test$(EXESUF)
+check-qtest-ppc64-y = tests/endianness-test$(EXESUF)
+check-qtest-sh4-y = tests/endianness-test$(EXESUF)
+check-qtest-sh4eb-y = tests/endianness-test$(EXESUF)
+check-qtest-sparc64-y = tests/endianness-test$(EXESUF)
#check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
-#check-qtest-sparc64-y = tests/m48t59-test$(EXESUF)
+#check-qtest-sparc64-y += tests/m48t59-test$(EXESUF)
gcov-files-sparc-y += hw/m48t59.c
gcov-files-sparc64-y += hw/m48t59.c
check-qtest-arm-y = tests/tmp105-test$(EXESUF)
@@ -74,6 +86,14 @@
check-qtest-ppc-y += tests/boot-order-test$(EXESUF)
check-qtest-ppc64-y += tests/boot-order-test$(EXESUF)
+check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
+ comments.json empty.json funny-char.json indented-expr.json \
+ missing-colon.json missing-comma-list.json \
+ missing-comma-object.json non-objects.json \
+ qapi-schema-test.json quoted-structural-chars.json \
+ trailing-comma-list.json trailing-comma-object.json \
+ unclosed-list.json unclosed-object.json unclosed-string.json)
+
GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
@@ -82,7 +102,8 @@
tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
tests/test-qmp-commands.o tests/test-visitor-serialization.o \
- tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o
+ tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
+ tests/test-opts-visitor.o
test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o
@@ -106,15 +127,21 @@
tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o xbzrle.o page_cache.o libqemuutil.a
tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
tests/test-int128$(EXESUF): tests/test-int128.o
+tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
+ hw/core/qdev.o hw/core/qdev-properties.o \
+ hw/core/irq.o \
+ qom/object.o qom/container.o qom/qom-qobject.o \
+ $(test-qapi-obj-y) \
+ libqemuutil.a libqemustub.a
tests/test-qapi-types.c tests/test-qapi-types.h :\
-$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
+$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
tests/test-qapi-visit.c tests/test-qapi-visit.h :\
-$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
+$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
-$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
+$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
@@ -124,6 +151,7 @@
tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y) qapi-types.o qapi-visit.o libqemuutil.a libqemustub.a
tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
+tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
tests/test-mul64$(EXESUF): tests/test-mul64.o libqemuutil.a
tests/test-bitops$(EXESUF): tests/test-bitops.o libqemuutil.a
@@ -136,6 +164,7 @@
tests/rtc-test$(EXESUF): tests/rtc-test.o
tests/m48t59-test$(EXESUF): tests/m48t59-test.o
+tests/endianness-test$(EXESUF): tests/endianness-test.o
tests/fdc-test$(EXESUF): tests/fdc-test.o
tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y)
tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
@@ -161,6 +190,7 @@
@echo " make check-qtest-TARGET Run qtest tests for given target"
@echo " make check-qtest Run qtest tests"
@echo " make check-unit Run qobject tests"
+ @echo " make check-qapi-schema Run QAPI schema tests"
@echo " make check-block Run block tests"
@echo " make check-report.html Generates an HTML test report"
@echo
@@ -223,13 +253,24 @@
check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) qemu-io$(EXESUF)
$<
+.PHONY: check-tests/test-qapi.py
+check-tests/test-qapi.py: tests/test-qapi.py
+
+.PHONY: $(patsubst %, check-%, $(check-qapi-schema-y))
+$(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
+ $(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py <$^ >$*.out 2>$*.err; echo $$? >$*.exit, " TEST $*.out")
+ @diff -q $(SRC_PATH)/$*.out $*.out
+ @diff -q $(SRC_PATH)/$*.err $*.err
+ @diff -q $(SRC_PATH)/$*.exit $*.exit
+
# Consolidated targets
-.PHONY: check-qtest check-unit check
+.PHONY: check-qapi-schema check-qtest check-unit check
+check-qapi-schema: $(patsubst %,check-%, $(check-qapi-schema-y))
check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS))
check-unit: $(patsubst %,check-%, $(check-unit-y))
check-block: $(patsubst %,check-%, $(check-block-y))
-check: check-unit check-qtest
+check: check-qapi-schema check-unit check-qtest
-include $(wildcard tests/*.d)
-include $(wildcard tests/libqos/*.d)
diff --git a/tests/endianness-test.c b/tests/endianness-test.c
new file mode 100644
index 0000000..feb32a8
--- /dev/null
+++ b/tests/endianness-test.c
@@ -0,0 +1,316 @@
+/*
+ * QTest testcase for ISA endianness
+ *
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Authors:
+ * Paolo Bonzini <pbonzini@redhat.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 "libqtest.h"
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "qemu/bswap.h"
+
+typedef struct TestCase TestCase;
+struct TestCase {
+ const char *arch;
+ const char *machine;
+ uint64_t isa_base;
+ bool bswap;
+ const char *superio;
+};
+
+static const TestCase test_cases[] = {
+ { "i386", "pc", -1 },
+ { "mips", "magnum", 0x90000000, .bswap = true },
+ { "mips", "pica61", 0x90000000, .bswap = true },
+ { "mips", "mips", 0x14000000, .bswap = true },
+ { "mips", "malta", 0x10000000, .bswap = true },
+ { "mips64", "magnum", 0x90000000, .bswap = true },
+ { "mips64", "pica61", 0x90000000, .bswap = true },
+ { "mips64", "mips", 0x14000000, .bswap = true },
+ { "mips64", "malta", 0x10000000, .bswap = true },
+ { "mips64el", "fulong2e", 0x1fd00000 },
+ { "ppc", "g3beige", 0xfe000000, .bswap = true, .superio = "i82378" },
+ { "ppc", "prep", 0x80000000, .bswap = true },
+ { "ppc", "bamboo", 0xe8000000, .bswap = true, .superio = "i82378" },
+ { "ppc64", "mac99", 0xf2000000, .bswap = true, .superio = "i82378" },
+ { "ppc64", "pseries", 0x10080000000, .bswap = true, .superio = "i82378" },
+ { "sh4", "r2d", 0xfe240000, .superio = "i82378" },
+ { "sh4eb", "r2d", 0xfe240000, .bswap = true, .superio = "i82378" },
+ { "sparc64", "sun4u", 0x1fe02000000LL, .bswap = true },
+ { "x86_64", "pc", -1 },
+ {}
+};
+
+static uint8_t isa_inb(const TestCase *test, uint16_t addr)
+{
+ uint8_t value;
+ if (test->isa_base == -1) {
+ value = inb(addr);
+ } else {
+ value = readb(test->isa_base + addr);
+ }
+ return value;
+}
+
+static uint16_t isa_inw(const TestCase *test, uint16_t addr)
+{
+ uint16_t value;
+ if (test->isa_base == -1) {
+ value = inw(addr);
+ } else {
+ value = readw(test->isa_base + addr);
+ }
+ return test->bswap ? bswap16(value) : value;
+}
+
+static uint32_t isa_inl(const TestCase *test, uint16_t addr)
+{
+ uint32_t value;
+ if (test->isa_base == -1) {
+ value = inl(addr);
+ } else {
+ value = readl(test->isa_base + addr);
+ }
+ return test->bswap ? bswap32(value) : value;
+}
+
+static void isa_outb(const TestCase *test, uint16_t addr, uint8_t value)
+{
+ if (test->isa_base == -1) {
+ outb(addr, value);
+ } else {
+ writeb(test->isa_base + addr, value);
+ }
+}
+
+static void isa_outw(const TestCase *test, uint16_t addr, uint16_t value)
+{
+ value = test->bswap ? bswap16(value) : value;
+ if (test->isa_base == -1) {
+ outw(addr, value);
+ } else {
+ writew(test->isa_base + addr, value);
+ }
+}
+
+static void isa_outl(const TestCase *test, uint16_t addr, uint32_t value)
+{
+ value = test->bswap ? bswap32(value) : value;
+ if (test->isa_base == -1) {
+ outl(addr, value);
+ } else {
+ writel(test->isa_base + addr, value);
+ }
+}
+
+
+static void test_endianness(gconstpointer data)
+{
+ const TestCase *test = data;
+ char *args;
+
+ args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev",
+ test->machine,
+ test->superio ? " -device " : "",
+ test->superio ?: "");
+ qtest_start(args);
+ isa_outl(test, 0xe0, 0x87654321);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+ g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
+ g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
+ g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
+ g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21);
+
+ isa_outw(test, 0xe2, 0x8866);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664321);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+ g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x88);
+ g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66);
+ g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
+ g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21);
+
+ isa_outw(test, 0xe0, 0x4422);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664422);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
+ g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x88);
+ g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66);
+ g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44);
+ g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
+
+ isa_outb(test, 0xe3, 0x87);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87664422);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8766);
+ g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
+ g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x66);
+ g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44);
+ g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
+
+ isa_outb(test, 0xe2, 0x65);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654422);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
+ g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
+ g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
+ g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x44);
+ g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
+
+ isa_outb(test, 0xe1, 0x43);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654322);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4322);
+ g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
+ g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
+ g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
+ g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x22);
+
+ isa_outb(test, 0xe0, 0x21);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+ g_assert_cmphex(isa_inb(test, 0xe3), ==, 0x87);
+ g_assert_cmphex(isa_inb(test, 0xe2), ==, 0x65);
+ g_assert_cmphex(isa_inb(test, 0xe1), ==, 0x43);
+ g_assert_cmphex(isa_inb(test, 0xe0), ==, 0x21);
+ qtest_quit(global_qtest);
+ g_free(args);
+}
+
+static void test_endianness_split(gconstpointer data)
+{
+ const TestCase *test = data;
+ char *args;
+
+ args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev",
+ test->machine,
+ test->superio ? " -device " : "",
+ test->superio ?: "");
+ qtest_start(args);
+ isa_outl(test, 0xe8, 0x87654321);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+
+ isa_outw(test, 0xea, 0x8866);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664321);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+
+ isa_outw(test, 0xe8, 0x4422);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x88664422);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8866);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
+
+ isa_outb(test, 0xeb, 0x87);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87664422);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8766);
+
+ isa_outb(test, 0xea, 0x65);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654422);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4422);
+
+ isa_outb(test, 0xe9, 0x43);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654322);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4322);
+
+ isa_outb(test, 0xe8, 0x21);
+ g_assert_cmphex(isa_inl(test, 0xe0), ==, 0x87654321);
+ g_assert_cmphex(isa_inw(test, 0xe2), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe0), ==, 0x4321);
+ qtest_quit(global_qtest);
+ g_free(args);
+}
+
+static void test_endianness_combine(gconstpointer data)
+{
+ const TestCase *test = data;
+ char *args;
+
+ args = g_strdup_printf("-display none -M %s%s%s -device pc-testdev",
+ test->machine,
+ test->superio ? " -device " : "",
+ test->superio ?: "");
+ qtest_start(args);
+ isa_outl(test, 0xe0, 0x87654321);
+ g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654321);
+ g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321);
+
+ isa_outw(test, 0xe2, 0x8866);
+ g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x88664321);
+ g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8866);
+ g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321);
+
+ isa_outw(test, 0xe0, 0x4422);
+ g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x88664422);
+ g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8866);
+ g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4422);
+
+ isa_outb(test, 0xe3, 0x87);
+ g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87664422);
+ g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8766);
+
+ isa_outb(test, 0xe2, 0x65);
+ g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654422);
+ g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4422);
+
+ isa_outb(test, 0xe1, 0x43);
+ g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654322);
+ g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4322);
+
+ isa_outb(test, 0xe0, 0x21);
+ g_assert_cmphex(isa_inl(test, 0xe8), ==, 0x87654321);
+ g_assert_cmphex(isa_inw(test, 0xea), ==, 0x8765);
+ g_assert_cmphex(isa_inw(test, 0xe8), ==, 0x4321);
+ qtest_quit(global_qtest);
+ g_free(args);
+}
+
+int main(int argc, char **argv)
+{
+ const char *arch = qtest_get_arch();
+ int ret;
+ int i;
+
+ g_test_init(&argc, &argv, NULL);
+
+ for (i = 0; test_cases[i].arch; i++) {
+ gchar *path;
+ if (strcmp(test_cases[i].arch, arch) != 0) {
+ continue;
+ }
+ path = g_strdup_printf("/%s/endianness/%s",
+ arch, test_cases[i].machine);
+ g_test_add_data_func(path, &test_cases[i], test_endianness);
+
+ path = g_strdup_printf("/%s/endianness/split/%s",
+ arch, test_cases[i].machine);
+ g_test_add_data_func(path, &test_cases[i], test_endianness_split);
+
+ path = g_strdup_printf("/%s/endianness/combine/%s",
+ arch, test_cases[i].machine);
+ g_test_add_data_func(path, &test_cases[i], test_endianness_combine);
+ }
+
+ ret = g_test_run();
+
+ return ret;
+}
diff --git a/tests/libqtest.h b/tests/libqtest.h
index 0f6aade..a6e99bd 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -258,9 +258,9 @@
* qtest_clock_step_next:
* @s: #QTestState instance to operate on.
*
- * Advance the vm_clock to the next deadline.
+ * Advance the QEMU_CLOCK_VIRTUAL to the next deadline.
*
- * Returns: The current value of the vm_clock in nanoseconds.
+ * Returns: The current value of the QEMU_CLOCK_VIRTUAL in nanoseconds.
*/
int64_t qtest_clock_step_next(QTestState *s);
@@ -269,9 +269,9 @@
* @s: QTestState instance to operate on.
* @step: Number of nanoseconds to advance the clock by.
*
- * Advance the vm_clock by @step nanoseconds.
+ * Advance the QEMU_CLOCK_VIRTUAL by @step nanoseconds.
*
- * Returns: The current value of the vm_clock in nanoseconds.
+ * Returns: The current value of the QEMU_CLOCK_VIRTUAL in nanoseconds.
*/
int64_t qtest_clock_step(QTestState *s, int64_t step);
@@ -280,9 +280,9 @@
* @s: QTestState instance to operate on.
* @val: Nanoseconds value to advance the clock to.
*
- * Advance the vm_clock to @val nanoseconds since the VM was launched.
+ * Advance the QEMU_CLOCK_VIRTUAL to @val nanoseconds since the VM was launched.
*
- * Returns: The current value of the vm_clock in nanoseconds.
+ * Returns: The current value of the QEMU_CLOCK_VIRTUAL in nanoseconds.
*/
int64_t qtest_clock_set(QTestState *s, int64_t val);
@@ -584,9 +584,9 @@
/**
* clock_step_next:
*
- * Advance the vm_clock to the next deadline.
+ * Advance the QEMU_CLOCK_VIRTUAL to the next deadline.
*
- * Returns: The current value of the vm_clock in nanoseconds.
+ * Returns: The current value of the QEMU_CLOCK_VIRTUAL in nanoseconds.
*/
static inline int64_t clock_step_next(void)
{
@@ -597,9 +597,9 @@
* clock_step:
* @step: Number of nanoseconds to advance the clock by.
*
- * Advance the vm_clock by @step nanoseconds.
+ * Advance the QEMU_CLOCK_VIRTUAL by @step nanoseconds.
*
- * Returns: The current value of the vm_clock in nanoseconds.
+ * Returns: The current value of the QEMU_CLOCK_VIRTUAL in nanoseconds.
*/
static inline int64_t clock_step(int64_t step)
{
@@ -610,9 +610,9 @@
* clock_set:
* @val: Nanoseconds value to advance the clock to.
*
- * Advance the vm_clock to @val nanoseconds since the VM was launched.
+ * Advance the QEMU_CLOCK_VIRTUAL to @val nanoseconds since the VM was launched.
*
- * Returns: The current value of the vm_clock in nanoseconds.
+ * Returns: The current value of the QEMU_CLOCK_VIRTUAL in nanoseconds.
*/
static inline int64_t clock_set(int64_t val)
{
diff --git a/tests/qapi-schema/comments.err b/tests/qapi-schema/comments.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/comments.err
diff --git a/tests/qapi-schema/comments.exit b/tests/qapi-schema/comments.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/comments.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/comments.json b/tests/qapi-schema/comments.json
new file mode 100644
index 0000000..e643f3a
--- /dev/null
+++ b/tests/qapi-schema/comments.json
@@ -0,0 +1,4 @@
+# Unindented comment
+{ 'enum': 'Status', # Comment to the right of code
+ # Indented comment
+ 'data': [ 'good', 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out
new file mode 100644
index 0000000..e3bd904
--- /dev/null
+++ b/tests/qapi-schema/comments.out
@@ -0,0 +1,3 @@
+[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
+['Status']
+[]
diff --git a/tests/qapi-schema/empty.err b/tests/qapi-schema/empty.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/empty.err
diff --git a/tests/qapi-schema/empty.exit b/tests/qapi-schema/empty.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/empty.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/empty.json b/tests/qapi-schema/empty.json
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/empty.json
diff --git a/tests/qapi-schema/empty.out b/tests/qapi-schema/empty.out
new file mode 100644
index 0000000..b7f89a4
--- /dev/null
+++ b/tests/qapi-schema/empty.out
@@ -0,0 +1,3 @@
+[]
+[]
+[]
diff --git a/tests/qapi-schema/funny-char.err b/tests/qapi-schema/funny-char.err
new file mode 100644
index 0000000..d3dd293
--- /dev/null
+++ b/tests/qapi-schema/funny-char.err
@@ -0,0 +1 @@
+<stdin>:2:36: Stray ";"
diff --git a/tests/qapi-schema/funny-char.exit b/tests/qapi-schema/funny-char.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/funny-char.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/funny-char.json b/tests/qapi-schema/funny-char.json
new file mode 100644
index 0000000..d4973a2
--- /dev/null
+++ b/tests/qapi-schema/funny-char.json
@@ -0,0 +1,2 @@
+{ 'enum': 'Status',
+ 'data': [ 'good', 'bad', 'ugly' ]; }
diff --git a/tests/qapi-schema/funny-char.out b/tests/qapi-schema/funny-char.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/funny-char.out
diff --git a/tests/qapi-schema/indented-expr.err b/tests/qapi-schema/indented-expr.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/indented-expr.err
diff --git a/tests/qapi-schema/indented-expr.exit b/tests/qapi-schema/indented-expr.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/indented-expr.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/indented-expr.json b/tests/qapi-schema/indented-expr.json
new file mode 100644
index 0000000..d80af60
--- /dev/null
+++ b/tests/qapi-schema/indented-expr.json
@@ -0,0 +1,2 @@
+{ 'id' : 'eins' }
+ { 'id' : 'zwei' }
diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
new file mode 100644
index 0000000..98af89a
--- /dev/null
+++ b/tests/qapi-schema/indented-expr.out
@@ -0,0 +1,3 @@
+[OrderedDict([('id', 'eins')]), OrderedDict([('id', 'zwei')])]
+[]
+[]
diff --git a/tests/qapi-schema/missing-colon.err b/tests/qapi-schema/missing-colon.err
new file mode 100644
index 0000000..9f2a355
--- /dev/null
+++ b/tests/qapi-schema/missing-colon.err
@@ -0,0 +1 @@
+<stdin>:1:10: Expected ":"
diff --git a/tests/qapi-schema/missing-colon.exit b/tests/qapi-schema/missing-colon.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/missing-colon.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/missing-colon.json b/tests/qapi-schema/missing-colon.json
new file mode 100644
index 0000000..6fc27ce
--- /dev/null
+++ b/tests/qapi-schema/missing-colon.json
@@ -0,0 +1,2 @@
+{ 'enum' 'Status',
+ 'data': [ 'good', 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/missing-colon.out b/tests/qapi-schema/missing-colon.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/missing-colon.out
diff --git a/tests/qapi-schema/missing-comma-list.err b/tests/qapi-schema/missing-comma-list.err
new file mode 100644
index 0000000..4fe0700
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-list.err
@@ -0,0 +1 @@
+<stdin>:2:20: Expected "," or "]"
diff --git a/tests/qapi-schema/missing-comma-list.exit b/tests/qapi-schema/missing-comma-list.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-list.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/missing-comma-list.json b/tests/qapi-schema/missing-comma-list.json
new file mode 100644
index 0000000..1af39b2
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-list.json
@@ -0,0 +1,2 @@
+{ 'enum': 'Status',
+ 'data': [ 'good' 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/missing-comma-list.out b/tests/qapi-schema/missing-comma-list.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-list.out
diff --git a/tests/qapi-schema/missing-comma-object.err b/tests/qapi-schema/missing-comma-object.err
new file mode 100644
index 0000000..b0121b5
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-object.err
@@ -0,0 +1 @@
+<stdin>:2:3: Expected "," or "}"
diff --git a/tests/qapi-schema/missing-comma-object.exit b/tests/qapi-schema/missing-comma-object.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-object.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/missing-comma-object.json b/tests/qapi-schema/missing-comma-object.json
new file mode 100644
index 0000000..50f5178
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-object.json
@@ -0,0 +1,2 @@
+{ 'enum': 'Status'
+ 'data': [ 'good', 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/missing-comma-object.out b/tests/qapi-schema/missing-comma-object.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-object.out
diff --git a/tests/qapi-schema/non-objects.err b/tests/qapi-schema/non-objects.err
new file mode 100644
index 0000000..a6c2dc2
--- /dev/null
+++ b/tests/qapi-schema/non-objects.err
@@ -0,0 +1 @@
+<stdin>:1:1: Expected "{"
diff --git a/tests/qapi-schema/non-objects.exit b/tests/qapi-schema/non-objects.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/non-objects.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/non-objects.json b/tests/qapi-schema/non-objects.json
new file mode 100644
index 0000000..f3fa851
--- /dev/null
+++ b/tests/qapi-schema/non-objects.json
@@ -0,0 +1,2 @@
+'string'
+[ ]
diff --git a/tests/qapi-schema/non-objects.out b/tests/qapi-schema/non-objects.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/non-objects.out
diff --git a/tests/qapi-schema/qapi-schema-test.err b/tests/qapi-schema/qapi-schema-test.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/qapi-schema-test.err
diff --git a/tests/qapi-schema/qapi-schema-test.exit b/tests/qapi-schema/qapi-schema-test.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/qapi-schema-test.exit
@@ -0,0 +1 @@
+0
diff --git a/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
similarity index 79%
rename from qapi-schema-test.json
rename to tests/qapi-schema/qapi-schema-test.json
index 4434fa3..fe5af75 100644
--- a/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -51,3 +51,18 @@
{ 'command': 'user_def_cmd', 'data': {} }
{ 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
{ 'command': 'user_def_cmd2', 'data': {'ud1a': 'UserDefOne', 'ud1b': 'UserDefOne'}, 'returns': 'UserDefTwo' }
+
+# For testing integer range flattening in opts-visitor. The following schema
+# corresponds to the option format:
+#
+# -userdef i64=3-6,i64=-5--1,u64=2,u16=1,u16=7-12
+#
+# For simplicity, this example doesn't use [type=]discriminator nor optargs
+# specific to discriminator values.
+{ 'type': 'UserDefOptions',
+ 'data': {
+ '*i64' : [ 'int' ],
+ '*u64' : [ 'uint64' ],
+ '*u16' : [ 'uint16' ],
+ '*i64x': 'int' ,
+ '*u64x': 'uint64' } }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
new file mode 100644
index 0000000..3851880
--- /dev/null
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -0,0 +1,21 @@
+[OrderedDict([('enum', 'EnumOne'), ('data', ['value1', 'value2', 'value3'])]),
+ OrderedDict([('type', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]),
+ OrderedDict([('type', 'UserDefOne'), ('data', OrderedDict([('integer', 'int'), ('string', 'str'), ('*enum1', 'EnumOne')]))]),
+ OrderedDict([('type', 'UserDefTwo'), ('data', OrderedDict([('string', 'str'), ('dict', OrderedDict([('string', 'str'), ('dict', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')])), ('*dict2', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]))]))]),
+ OrderedDict([('type', 'UserDefNested'), ('data', OrderedDict([('string0', 'str'), ('dict1', OrderedDict([('string1', 'str'), ('dict2', OrderedDict([('userdef1', 'UserDefOne'), ('string2', 'str')])), ('*dict3', OrderedDict([('userdef2', 'UserDefOne'), ('string3', 'str')]))]))]))]),
+ OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
+ OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
+ OrderedDict([('union', 'UserDefUnion'), ('data', OrderedDict([('a', 'UserDefA'), ('b', 'UserDefB')]))]),
+ OrderedDict([('union', 'UserDefNativeListUnion'), ('data', OrderedDict([('integer', ['int']), ('s8', ['int8']), ('s16', ['int16']), ('s32', ['int32']), ('s64', ['int64']), ('u8', ['uint8']), ('u16', ['uint16']), ('u32', ['uint32']), ('u64', ['uint64']), ('number', ['number']), ('boolean', ['bool']), ('string', ['str'])]))]),
+ OrderedDict([('command', 'user_def_cmd'), ('data', OrderedDict())]),
+ OrderedDict([('command', 'user_def_cmd1'), ('data', OrderedDict([('ud1a', 'UserDefOne')]))]),
+ OrderedDict([('command', 'user_def_cmd2'), ('data', OrderedDict([('ud1a', 'UserDefOne'), ('ud1b', 'UserDefOne')])), ('returns', 'UserDefTwo')]),
+ OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])]
+['EnumOne', 'UserDefUnionKind', 'UserDefNativeListUnionKind']
+[OrderedDict([('type', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]),
+ OrderedDict([('type', 'UserDefOne'), ('data', OrderedDict([('integer', 'int'), ('string', 'str'), ('*enum1', 'EnumOne')]))]),
+ OrderedDict([('type', 'UserDefTwo'), ('data', OrderedDict([('string', 'str'), ('dict', OrderedDict([('string', 'str'), ('dict', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')])), ('*dict2', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]))]))]),
+ OrderedDict([('type', 'UserDefNested'), ('data', OrderedDict([('string0', 'str'), ('dict1', OrderedDict([('string1', 'str'), ('dict2', OrderedDict([('userdef1', 'UserDefOne'), ('string2', 'str')])), ('*dict3', OrderedDict([('userdef2', 'UserDefOne'), ('string3', 'str')]))]))]))]),
+ OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
+ OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
+ OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])]
diff --git a/tests/qapi-schema/quoted-structural-chars.err b/tests/qapi-schema/quoted-structural-chars.err
new file mode 100644
index 0000000..a6c2dc2
--- /dev/null
+++ b/tests/qapi-schema/quoted-structural-chars.err
@@ -0,0 +1 @@
+<stdin>:1:1: Expected "{"
diff --git a/tests/qapi-schema/quoted-structural-chars.exit b/tests/qapi-schema/quoted-structural-chars.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/quoted-structural-chars.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/quoted-structural-chars.json b/tests/qapi-schema/quoted-structural-chars.json
new file mode 100644
index 0000000..9fe657a
--- /dev/null
+++ b/tests/qapi-schema/quoted-structural-chars.json
@@ -0,0 +1 @@
+'{' 'key1' ':' 'value1' ',' 'key2' ':' '[' ']' '}'
diff --git a/tests/qapi-schema/quoted-structural-chars.out b/tests/qapi-schema/quoted-structural-chars.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/quoted-structural-chars.out
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
new file mode 100644
index 0000000..b3d1e1d
--- /dev/null
+++ b/tests/qapi-schema/test-qapi.py
@@ -0,0 +1,27 @@
+#
+# QAPI parser test harness
+#
+# Copyright (c) 2013 Red Hat Inc.
+#
+# Authors:
+# Markus Armbruster <armbru@redhat.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.
+#
+
+from qapi import *
+from pprint import pprint
+import sys
+
+try:
+ exprs = parse_schema(sys.stdin)
+except SystemExit:
+ raise
+except:
+ print >>sys.stderr, "Crashed:", sys.exc_info()[0]
+ exit(1)
+
+pprint(exprs)
+pprint(enum_types)
+pprint(struct_types)
diff --git a/tests/qapi-schema/trailing-comma-list.err b/tests/qapi-schema/trailing-comma-list.err
new file mode 100644
index 0000000..ff839a3
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-list.err
@@ -0,0 +1 @@
+<stdin>:2:36: Expected "{", "[" or string
diff --git a/tests/qapi-schema/trailing-comma-list.exit b/tests/qapi-schema/trailing-comma-list.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-list.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/trailing-comma-list.json b/tests/qapi-schema/trailing-comma-list.json
new file mode 100644
index 0000000..9b0c8bd
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-list.json
@@ -0,0 +1,2 @@
+{ 'enum': 'Status',
+ 'data': [ 'good', 'bad', 'ugly', ] }
diff --git a/tests/qapi-schema/trailing-comma-list.out b/tests/qapi-schema/trailing-comma-list.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-list.out
diff --git a/tests/qapi-schema/trailing-comma-object.err b/tests/qapi-schema/trailing-comma-object.err
new file mode 100644
index 0000000..f540962
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-object.err
@@ -0,0 +1 @@
+<stdin>:2:38: Expected string
diff --git a/tests/qapi-schema/trailing-comma-object.exit b/tests/qapi-schema/trailing-comma-object.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-object.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/trailing-comma-object.json b/tests/qapi-schema/trailing-comma-object.json
new file mode 100644
index 0000000..bbaea55
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-object.json
@@ -0,0 +1,2 @@
+{ 'enum': 'Status',
+ 'data': [ 'good', 'bad', 'ugly' ], }
diff --git a/tests/qapi-schema/trailing-comma-object.out b/tests/qapi-schema/trailing-comma-object.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-object.out
diff --git a/tests/qapi-schema/unclosed-list.err b/tests/qapi-schema/unclosed-list.err
new file mode 100644
index 0000000..0e837a7
--- /dev/null
+++ b/tests/qapi-schema/unclosed-list.err
@@ -0,0 +1 @@
+<stdin>:1:20: Expected "," or "]"
diff --git a/tests/qapi-schema/unclosed-list.exit b/tests/qapi-schema/unclosed-list.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/unclosed-list.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/unclosed-list.json b/tests/qapi-schema/unclosed-list.json
new file mode 100644
index 0000000..e3e9566
--- /dev/null
+++ b/tests/qapi-schema/unclosed-list.json
@@ -0,0 +1 @@
+{ 'key': [ 'value' }
diff --git a/tests/qapi-schema/unclosed-list.out b/tests/qapi-schema/unclosed-list.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/unclosed-list.out
diff --git a/tests/qapi-schema/unclosed-object.err b/tests/qapi-schema/unclosed-object.err
new file mode 100644
index 0000000..e6dc950
--- /dev/null
+++ b/tests/qapi-schema/unclosed-object.err
@@ -0,0 +1 @@
+<stdin>:1:21: Expected "," or "}"
diff --git a/tests/qapi-schema/unclosed-object.exit b/tests/qapi-schema/unclosed-object.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/unclosed-object.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/unclosed-object.json b/tests/qapi-schema/unclosed-object.json
new file mode 100644
index 0000000..8ac069d
--- /dev/null
+++ b/tests/qapi-schema/unclosed-object.json
@@ -0,0 +1 @@
+{ 'key': [ 'value' ]
diff --git a/tests/qapi-schema/unclosed-object.out b/tests/qapi-schema/unclosed-object.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/unclosed-object.out
diff --git a/tests/qapi-schema/unclosed-string.err b/tests/qapi-schema/unclosed-string.err
new file mode 100644
index 0000000..948d883
--- /dev/null
+++ b/tests/qapi-schema/unclosed-string.err
@@ -0,0 +1 @@
+<stdin>:1:11: Missing terminating "'"
diff --git a/tests/qapi-schema/unclosed-string.exit b/tests/qapi-schema/unclosed-string.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/unclosed-string.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/unclosed-string.json b/tests/qapi-schema/unclosed-string.json
new file mode 100644
index 0000000..8c16b6b
--- /dev/null
+++ b/tests/qapi-schema/unclosed-string.json
@@ -0,0 +1,2 @@
+{ 'text': 'lorem ips
+}
diff --git a/tests/qapi-schema/unclosed-string.out b/tests/qapi-schema/unclosed-string.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/qapi-schema/unclosed-string.out
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
index 1cf8bf7..1f39c6a 100755
--- a/tests/qemu-iotests/051
+++ b/tests/qemu-iotests/051
@@ -72,11 +72,11 @@
echo === Enable and disable lazy refcounting on the command line, plus some invalid values ===
echo
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=on
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=off
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=42
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=foo
+run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=on
+run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=off
+run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=
+run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=42
+run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=foo
echo
@@ -85,8 +85,8 @@
_make_test_img -ocompat=0.10 $size
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=on
-run_qemu -drive file=$TEST_IMG,format=qcow2,lazy_refcounts=off
+run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=on
+run_qemu -drive file=$TEST_IMG,format=qcow2,lazy-refcounts=off
echo
echo === No medium ===
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 95ff245..5582ed3 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -22,101 +22,101 @@
=== Enable and disable lazy refcounting on the command line, plus some invalid values ===
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on
-QEMU 1.5.50 monitor - type 'help' for more information
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off
-QEMU 1.5.50 monitor - type 'help' for more information
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=: Parameter 'lazy_refcounts' expects 'on' or 'off'
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=: could not open disk image TEST_DIR/t.qcow2: Invalid argument
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: Parameter 'lazy-refcounts' expects 'on' or 'off'
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: could not open disk image TEST_DIR/t.qcow2: Invalid argument
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=42
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=42: Parameter 'lazy_refcounts' expects 'on' or 'off'
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=42: could not open disk image TEST_DIR/t.qcow2: Invalid argument
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42: Parameter 'lazy-refcounts' expects 'on' or 'off'
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42: could not open disk image TEST_DIR/t.qcow2: Invalid argument
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=foo
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=foo: Parameter 'lazy_refcounts' expects 'on' or 'off'
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=foo: could not open disk image TEST_DIR/t.qcow2: Invalid argument
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo: Parameter 'lazy-refcounts' expects 'on' or 'off'
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo: could not open disk image TEST_DIR/t.qcow2: Invalid argument
=== With version 2 images enabling lazy refcounts must fail ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: Lazy refcounts require a qcow2 image with at least qemu 1.1 compatibility level
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: Lazy refcounts require a qcow2 image with at least qemu 1.1 compatibility level
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off
-QEMU 1.5.50 monitor - type 'help' for more information
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
=== No medium ===
Testing: -drive if=floppy
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive if=ide,media=cdrom
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive if=scsi,media=cdrom
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive if=ide
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: Device needs media, but drive is empty
QEMU_PROG: Device initialization failed.
QEMU_PROG: Initialization of device ide-hd failed
Testing: -drive if=virtio
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
QEMU_PROG: -drive if=virtio: Device initialization failed.
QEMU_PROG: -drive if=virtio: Device initialization failed.
QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized
Testing: -drive if=scsi
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty
QEMU_PROG: -drive if=scsi: Device initialization failed.
QEMU_PROG: Device initialization failed.
QEMU_PROG: Initialization of device lsi53c895a failed
Testing: -drive if=none,id=disk -device ide-cd,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive if=none,id=disk -device ide-drive,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized
Testing: -drive if=none,id=disk -device ide-hd,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device scsi-disk,drive=disk: Device initialization failed.
QEMU_PROG: -device scsi-disk,drive=disk: Device 'scsi-disk' could not be initialized
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty
QEMU_PROG: -device scsi-hd,drive=disk: Device initialization failed.
QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized
@@ -125,77 +125,77 @@
=== Read-only ===
Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: readonly not supported by this bus type
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: read-only not supported by this bus type
Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive
QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive
QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
=== Cache modes ===
Testing: -drive media=cdrom,cache=none
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive media=cdrom,cache=directsync
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive media=cdrom,cache=writeback
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive media=cdrom,cache=writethrough
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive media=cdrom,cache=unsafe
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive media=cdrom,cache=invalid_value
@@ -205,7 +205,7 @@
=== Specifying the protocol layer ===
Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file
-QEMU 1.5.50 monitor - type 'help' for more information
+QEMU X.Y.Z monitor - type 'help' for more information
(qemu) q[K[Dqu[K[D[Dqui[K[D[D[Dquit[K
Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2
diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055
index c66f8db..44bb025 100755
--- a/tests/qemu-iotests/055
+++ b/tests/qemu-iotests/055
@@ -97,6 +97,12 @@
target=target_img, sync='full', mode='existing')
self.assert_qmp(result, 'error/class', 'GenericError')
+ def test_invalid_format(self):
+ result = self.vm.qmp('drive-backup', device='drive0',
+ target=target_img, sync='full',
+ format='spaghetti-noodles')
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
def test_device_not_found(self):
result = self.vm.qmp('drive-backup', device='nonexistent',
target=target_img, sync='full')
diff --git a/tests/qemu-iotests/055.out b/tests/qemu-iotests/055.out
index fa16b5c..6323079 100644
--- a/tests/qemu-iotests/055.out
+++ b/tests/qemu-iotests/055.out
@@ -1,5 +1,5 @@
-.............
+..............
----------------------------------------------------------------------
-Ran 13 tests
+Ran 14 tests
OK
diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056
new file mode 100755
index 0000000..6389342
--- /dev/null
+++ b/tests/qemu-iotests/056
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+#
+# Tests for drive-backup
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# Based on 041.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import time
+import os
+import iotests
+from iotests import qemu_img, qemu_io, create_image
+
+backing_img = os.path.join(iotests.test_dir, 'backing.img')
+test_img = os.path.join(iotests.test_dir, 'test.img')
+target_img = os.path.join(iotests.test_dir, 'target.img')
+
+class TestSyncModesNoneAndTop(iotests.QMPTestCase):
+ image_len = 64 * 1024 * 1024 # MB
+
+ def setUp(self):
+ create_image(backing_img, TestSyncModesNoneAndTop.image_len)
+ qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
+ qemu_io('-c', 'write -P0x41 0 512', test_img)
+ qemu_io('-c', 'write -P0xd5 1M 32k', test_img)
+ qemu_io('-c', 'write -P0xdc 32M 124k', test_img)
+ qemu_io('-c', 'write -P0xdc 67043328 64k', test_img)
+ self.vm = iotests.VM().add_drive(test_img)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(test_img)
+ os.remove(backing_img)
+ try:
+ os.remove(target_img)
+ except OSError:
+ pass
+
+ def test_complete_top(self):
+ self.assert_no_active_block_jobs()
+ result = self.vm.qmp('drive-backup', device='drive0', sync='top',
+ format=iotests.imgfmt, target=target_img)
+ self.assert_qmp(result, 'return', {})
+
+ # Custom completed check as we are not copying all data.
+ completed = False
+ while not completed:
+ for event in self.vm.get_qmp_events(wait=True):
+ if event['event'] == 'BLOCK_JOB_COMPLETED':
+ self.assert_qmp(event, 'data/device', 'drive0')
+ self.assert_qmp_absent(event, 'data/error')
+ completed = True
+
+ self.assert_no_active_block_jobs()
+ self.vm.shutdown()
+ self.assertTrue(iotests.compare_images(test_img, target_img),
+ 'target image does not match source after backup')
+
+ def test_cancel_sync_none(self):
+ self.assert_no_active_block_jobs()
+
+ result = self.vm.qmp('drive-backup', device='drive0',
+ sync='none', target=target_img)
+ self.assert_qmp(result, 'return', {})
+ time.sleep(1)
+ self.vm.hmp_qemu_io('drive0', 'write -P0x5e 0 512')
+ self.vm.hmp_qemu_io('drive0', 'aio_flush')
+ # Verify that the original contents exist in the target image.
+
+ event = self.cancel_and_wait()
+ self.assert_qmp(event, 'data/type', 'backup')
+
+ self.vm.shutdown()
+ time.sleep(1)
+ self.assertEqual(-1, qemu_io('-c', 'read -P0x41 0 512', target_img).find("verification failed"))
+
+
+if __name__ == '__main__':
+ iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/tests/qemu-iotests/056.out b/tests/qemu-iotests/056.out
new file mode 100644
index 0000000..fbc63e6
--- /dev/null
+++ b/tests/qemu-iotests/056.out
@@ -0,0 +1,5 @@
+..
+----------------------------------------------------------------------
+Ran 2 tests
+
+OK
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
new file mode 100755
index 0000000..b03429d
--- /dev/null
+++ b/tests/qemu-iotests/059
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# Test case for vmdk
+#
+# Copyright (C) 2013 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=famz@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# This tests vmdk-specific low-level functionality
+_supported_fmt vmdk
+_supported_proto generic
+_supported_os Linux
+
+capacity_offset=16
+granularity_offset=20
+grain_table_size_offset=44
+
+echo "=== Testing invalid granularity ==="
+echo
+_make_test_img 64M
+poke_file "$TEST_IMG" "$granularity_offset" "\xff\xff\xff\xff\xff\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo "=== Testing too big L2 table size ==="
+echo
+_make_test_img 64M
+poke_file "$TEST_IMG" "$grain_table_size_offset" "\xff\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo "=== Testing too big L1 table size ==="
+echo
+_make_test_img 64M
+poke_file "$TEST_IMG" "$capacity_offset" "\xff\xff\xff\xff"
+poke_file "$TEST_IMG" "$grain_table_size_offset" "\x01\x00\x00\x00"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
new file mode 100644
index 0000000..9e715e5
--- /dev/null
+++ b/tests/qemu-iotests/059.out
@@ -0,0 +1,20 @@
+QA output created by 059
+=== Testing invalid granularity ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+invalid granularity, image may be corrupt
+qemu-io: can't open device TEST_DIR/t.vmdk
+no file open, try 'help open'
+=== Testing too big L2 table size ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+L2 table size too big
+qemu-io: can't open device TEST_DIR/t.vmdk
+no file open, try 'help open'
+=== Testing too big L1 table size ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+L1 size too big
+qemu-io: can't open device TEST_DIR/t.vmdk
+no file open, try 'help open'
+*** done
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 9dbcae8..97a31ff 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -155,7 +155,8 @@
# replace occurrences of QEMU_PROG with "qemu"
_filter_qemu()
{
- sed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#"
+ sed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#" \
+ -e 's#^QEMU [0-9]\+\.[0-9]\+\.[0-9]\+ monitor#QEMU X.Y.Z monitor#'
}
# make sure this script returns success
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index e9ba358..5e077c3 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -34,6 +34,12 @@
fi
}
+# poke_file 'test.img' 512 '\xff\xfe'
+poke_file()
+{
+ printf "$3" | dd "of=$1" bs=1 "seek=$2" conv=notrunc &>/dev/null
+}
+
# we need common.config
if [ "$iam" != "check" ]
then
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index fdc6ed1..43c05d6 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -57,8 +57,10 @@
048 img auto quick
049 rw auto
050 rw auto backing quick
-051 rw auto
+#051 rw auto
052 rw auto backing
053 rw auto
054 rw auto
055 rw auto
+056 rw auto backing
+059 rw auto
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index b028a89..33ad0ec 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -95,6 +95,11 @@
self._num_drives += 1
return self
+ def hmp_qemu_io(self, drive, cmd):
+ '''Write to a given drive using an HMP command'''
+ return self.qmp('human-monitor-command',
+ command_line='qemu-io %s "%s"' % (drive, cmd))
+
def add_fd(self, fd, fdset, opaque, opts=''):
'''Pass a file descriptor to the VM'''
options = ['fd=%d' % fd,
diff --git a/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c b/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
index ce86484..cbf9007 100644
--- a/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
+++ b/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
@@ -14,7 +14,7 @@
resultdsp = 0x01;
__asm
("mthi %0, $ac1\n\t"
- "mtlo %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
"dpaq_sa.l.w $ac1, %3, %4\n\t"
"mfhi %0, $ac1\n\t"
"mflo %1, $ac1\n\t"
@@ -27,8 +27,8 @@
assert(ach == resulth);
assert(acl == resultl);
- ach = 0x12;
- acl = 0x48;
+ ach = 0x00000012;
+ acl = 0x00000048;
rs = 0x80000000;
rt = 0x80000000;
@@ -37,7 +37,7 @@
resultdsp = 0x01;
__asm
("mthi %0, $ac1\n\t"
- "mtlo %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
"dpaq_sa.l.w $ac1, %3, %4\n\t"
"mfhi %0, $ac1\n\t"
"mflo %1, $ac1\n\t"
@@ -51,16 +51,64 @@
assert(acl == resultl);
ach = 0x741532A0;
- acl = 0xfceabb08;
+ acl = 0xFCEABB08;
rs = 0x80000000;
rt = 0x80000000;
- resulth = 0x7fffffff;
- resultl = 0xffffffff;
+ resulth = 0x7FFFFFFF;
+ resultl = 0xFFFFFFFF;
resultdsp = 0x01;
__asm
("mthi %0, $ac1\n\t"
- "mtlo %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpaq_sa.l.w $ac1, %3, %4\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ "rddsp %2\n\t"
+ : "+r"(ach), "+r"(acl), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 17) & 0x01;
+ assert(dsp == resultdsp);
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ ach = 0;
+ acl = 0;
+ rs = 0xC0000000;
+ rt = 0x7FFFFFFF;
+
+ resulth = 0xC0000000;
+ resultl = 0x80000000;
+ resultdsp = 0;
+ __asm
+ ("wrdsp $0\n\t"
+ "mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpaq_sa.l.w $ac1, %3, %4\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ "rddsp %2\n\t"
+ : "+r"(ach), "+r"(acl), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 17) & 0x01;
+ assert(dsp == resultdsp);
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ ach = 0x20000000;
+ acl = 0;
+ rs = 0xE0000000;
+ rt = 0x7FFFFFFF;
+
+ resulth = 0;
+ resultl = 0x40000000;
+ resultdsp = 0;
+ __asm
+ ("wrdsp $0\n\t"
+ "mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
"dpaq_sa.l.w $ac1, %3, %4\n\t"
"mfhi %0, $ac1\n\t"
"mflo %1, $ac1\n\t"
diff --git a/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c b/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
index 22ab4d5..74058fe 100644
--- a/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
+++ b/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
@@ -9,8 +9,8 @@
rs = 0xBC0123AD;
rt = 0x01643721;
- resulth = 0x04;
- resultl = 0xEE9794A3;
+ resulth = 0x00000004;
+ resultl = 0xF15F94A3;
__asm
("mthi %0, $ac1\n\t"
"mtlo %1, $ac1\n\t"
@@ -23,12 +23,12 @@
assert(ach == resulth);
assert(acl == resultl);
- ach = 0x1424Ef1f;
+ ach = 0x1424EF1F;
acl = 0x1035219A;
rs = 0x800083AD;
rt = 0x80003721;
- resulth = 0x1424ef1e;
- resultl = 0x577ed901;
+ resulth = 0x1424EF1E;
+ resultl = 0xC5C0D901;
__asm
("mthi %0, $ac1\n\t"
"mtlo %1, $ac1\n\t"
diff --git a/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c b/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
index b7b73fd..eda3b14 100644
--- a/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
+++ b/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
@@ -9,8 +9,8 @@
rs = 0xBC0123AD;
rt = 0x01643721;
- resulth = 0xfdf4cbe0;
- resultl = 0xd138776b;
+ resulth = 0x00BD3A22;
+ resultl = 0xD138776B;
resultdsp = 0x00;
__asm
("mthi %0, $ac1\n\t"
diff --git a/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c b/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
index 292d685..0f7c070 100644
--- a/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
+++ b/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
@@ -10,12 +10,12 @@
int resulth, resultl;
int resdsp;
- achi = 0x05;
- acli = 0xB4CB;
+ achi = 0x00000005;
+ acli = 0x0000B4CB;
rs = 0xFF060000;
rt = 0xCB000000;
- resulth = 0x04;
- resultl = 0x947438CB;
+ resulth = 0x00000005;
+ resultl = 0x006838CB;
__asm
("mthi %2, $ac1\n\t"
@@ -29,12 +29,12 @@
assert(resulth == acho);
assert(resultl == aclo);
- achi = 0x06;
- acli = 0xB4CB;
+ achi = 0x00000006;
+ acli = 0x0000B4CB;
rs = 0x80000000;
rt = 0x80000000;
- resulth = 0x6;
- resultl = 0x8000b4ca;
+ resulth = 0x00000006;
+ resultl = 0x8000B4CA;
resdsp = 1;
__asm
diff --git a/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c b/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
index 7b2ef2a..942722a 100644
--- a/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
+++ b/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
@@ -10,12 +10,12 @@
int resulth, resultl;
int resdsp;
- achi = 0x05;
- acli = 0xB4CB;
- rs = 0xFF06;
- rt = 0xCB00;
- resulth = 0x04;
- resultl = 0x947438CB;
+ achi = 0x00000005;
+ acli = 0x0000B4CB;
+ rs = 0x0000FF06;
+ rt = 0x0000CB00;
+ resulth = 0x00000005;
+ resultl = 0x006838CB;
__asm
("mthi %2, $ac1\n\t"
@@ -29,12 +29,12 @@
assert(resulth == acho);
assert(resultl == aclo);
- achi = 0x06;
- acli = 0xB4CB;
- rs = 0x8000;
- rt = 0x8000;
- resulth = 0x6;
- resultl = 0x8000b4ca;
+ achi = 0x00000006;
+ acli = 0x0000B4CB;
+ rs = 0x00008000;
+ rt = 0x00008000;
+ resulth = 0x00000006;
+ resultl = 0x8000B4CA;
resdsp = 1;
__asm
diff --git a/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c b/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
index c720603..370c2a8 100644
--- a/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
+++ b/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
@@ -12,7 +12,24 @@
resultdsp = 1;
__asm
- ("mulq_rs.ph %0, %2, %3\n\t"
+ ("wrdsp $0\n\t"
+ "mulq_rs.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ rs = 0x80011234;
+ rt = 0x80024321;
+ result = 0x7FFD098C;
+ resultdsp = 0;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "mulq_rs.ph %0, %2, %3\n\t"
"rddsp %1\n\t"
: "=r"(rd), "=r"(dsp)
: "r"(rs), "r"(rt)
diff --git a/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c b/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
index 3535b37..da6845b 100644
--- a/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
+++ b/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
@@ -12,18 +12,34 @@
result = 0x12348765;
__asm
- ("precrq_rs.ph.w %0, %1, %2\n\t"
+ ("wrdsp $0\n\t"
+ "precrq_rs.ph.w %0, %1, %2\n\t"
: "=r"(rd)
: "r"(rs), "r"(rt)
);
assert(result == rd);
- rs = 0x7fffC678;
+ rs = 0x7FFFC678;
rt = 0x865432A0;
- result = 0x7fff8654;
+ result = 0x7FFF8654;
__asm
- ("precrq_rs.ph.w %0, %2, %3\n\t"
+ ("wrdsp $0\n\t"
+ "precrq_rs.ph.w %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(((dsp >> 22) & 0x01) == 1);
+ assert(result == rd);
+
+ rs = 0xBEEFFEED;
+ rt = 0x7FFF8000;
+ result = 0xBEF07FFF;
+
+ __asm
+ ("wrdsp $0\n\t"
+ "precrq_rs.ph.w %0, %2, %3\n\t"
"rddsp %1\n\t"
: "=r"(rd), "=r"(dsp)
: "r"(rs), "r"(rt)
diff --git a/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
index 798c4da..d551d64 100644
--- a/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
+++ b/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
@@ -4,14 +4,17 @@
int main()
{
int rs, rt, dsp;
- int ach = 5, acl = 5;
+ int ach, acl;
int resulth, resultl, resultdsp;
+ ach = 0x00000005;
+ acl = 0x00000005;
rs = 0x00FF00FF;
rt = 0x00010002;
resulth = 0x00;
resultl = 0x7FFFFFFF;
resultdsp = 0x01;
+ dsp = 0;
__asm
("wrdsp %2\n\t"
"mthi %0, $ac1\n\t"
@@ -27,13 +30,14 @@
assert(ach == resulth);
assert(acl == resultl);
- ach = 9;
- acl = 0xb;
+ ach = 0x00000009;
+ acl = 0x0000000B;
rs = 0x800000FF;
rt = 0x00018000;
resulth = 0x00;
- resultl = 0x7fffffff;
+ resultl = 0x7FFFFFFF;
resultdsp = 0x01;
+ dsp = 0;
__asm
("wrdsp %2\n\t"
"mthi %0, $ac1\n\t"
diff --git a/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
index 14cdd7c..e40543f 100644
--- a/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
+++ b/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
@@ -9,8 +9,8 @@
rs = 0xBC0123AD;
rt = 0x01643721;
- resulth = 0x04;
- resultl = 0xAEA3E09B;
+ resulth = 0x00000005;
+ resultl = 0x1CE5E09B;
resultdsp = 0x00;
__asm
("mthi %0, $ac1\n\t"
@@ -27,12 +27,12 @@
assert(ach == resulth);
assert(acl == resultl);
- ach = 0x99f13005;
+ ach = 0x99F13005;
acl = 0x51730062;
rs = 0x80008000;
rt = 0x80008000;
- resulth = 0x99f13004;
+ resulth = 0x99F13004;
resultl = 0x51730064;
resultdsp = 0x01;
__asm
diff --git a/tests/tcg/xtensa/Makefile b/tests/tcg/xtensa/Makefile
index 002fd87..1b519ca 100644
--- a/tests/tcg/xtensa/Makefile
+++ b/tests/tcg/xtensa/Makefile
@@ -1,9 +1,9 @@
--include ../../config-host.mak
+-include ../../../config-host.mak
CROSS=xtensa-dc232b-elf-
ifndef XT
-SIM = qemu-system-xtensa
+SIM = ../../../xtensa-softmmu/qemu-system-xtensa
SIMFLAGS = -M sim -cpu dc232b -nographic -semihosting $(EXTFLAGS) -kernel
SIMDEBUG = -s -S
else
@@ -13,10 +13,12 @@
endif
CC = $(CROSS)gcc
-AS = $(CROSS)gcc -x assembler
+AS = $(CROSS)gcc -x assembler-with-cpp
LD = $(CROSS)ld
-LDFLAGS = -Tlinker.ld
+XTENSA_SRC_PATH = $(SRC_PATH)/tests/tcg/xtensa
+
+LDFLAGS = -T$(XTENSA_SRC_PATH)/linker.ld
CRT = crt.o vectors.o
@@ -26,6 +28,7 @@
TESTCASES += test_break.tst
TESTCASES += test_bz.tst
TESTCASES += test_clamps.tst
+TESTCASES += test_extui.tst
TESTCASES += test_fail.tst
TESTCASES += test_interrupt.tst
TESTCASES += test_loop.tst
@@ -52,13 +55,13 @@
all: build
-%.o: $(SRC_PATH)/tests/xtensa/%.c
- $(CC) $(CFLAGS) -c $< -o $@
+%.o: $(XTENSA_SRC_PATH)/%.c
+ $(CC) -I$(XTENSA_SRC_PATH) $(CFLAGS) -c $< -o $@
-%.o: $(SRC_PATH)/tests/xtensa/%.S
- $(AS) $(ASFLAGS) -c $< -o $@
+%.o: $(XTENSA_SRC_PATH)/%.S
+ $(AS) -Wa,-I,$(XTENSA_SRC_PATH) $(ASFLAGS) -c $< -o $@
-%.tst: %.o macros.inc $(CRT) Makefile
+%.tst: %.o $(XTENSA_SRC_PATH)/macros.inc $(CRT) Makefile
$(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
build: $(TESTCASES)
diff --git a/tests/tcg/xtensa/test_extui.S b/tests/tcg/xtensa/test_extui.S
new file mode 100644
index 0000000..5d55451
--- /dev/null
+++ b/tests/tcg/xtensa/test_extui.S
@@ -0,0 +1,26 @@
+.include "macros.inc"
+
+test_suite extui
+
+.macro test_extui v, shiftimm, maskimm
+ .if \shiftimm + \maskimm <= 32
+ movi a2, \v
+ extui a3, a2, \shiftimm, \maskimm
+ movi a4, ((\v) >> (\shiftimm)) & ((1 << (\maskimm)) - 1)
+ assert eq, a3, a4
+ .endif
+.endm
+
+test extui
+ .set shiftimm, 0
+ .rept 32
+ .set maskimm, 1
+ .rept 16
+ test_extui 0xc8df1370, shiftimm, maskimm
+ .set maskimm, maskimm + 1
+ .endr
+ .set shiftimm, shiftimm + 1
+ .endr
+test_end
+
+test_suite_end
diff --git a/tests/test-aio.c b/tests/test-aio.c
index c173870..07a1f61 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -12,9 +12,17 @@
#include <glib.h>
#include "block/aio.h"
+#include "qemu/timer.h"
AioContext *ctx;
+typedef struct {
+ EventNotifier e;
+ int n;
+ int active;
+ bool auto_set;
+} EventNotifierTestData;
+
/* Wait until there are no more BHs or AIO requests */
static void wait_for_aio(void)
{
@@ -23,6 +31,14 @@
}
}
+/* Wait until event notifier becomes inactive */
+static void wait_until_inactive(EventNotifierTestData *data)
+{
+ while (data->active > 0) {
+ aio_poll(ctx, true);
+ }
+}
+
/* Simple callbacks for testing. */
typedef struct {
@@ -31,6 +47,15 @@
int max;
} BHTestData;
+typedef struct {
+ QEMUTimer timer;
+ QEMUClockType clock_type;
+ int n;
+ int max;
+ int64_t ns;
+ AioContext *ctx;
+} TimerTestData;
+
static void bh_test_cb(void *opaque)
{
BHTestData *data = opaque;
@@ -39,6 +64,19 @@
}
}
+static void timer_test_cb(void *opaque)
+{
+ TimerTestData *data = opaque;
+ if (++data->n < data->max) {
+ timer_mod(&data->timer,
+ qemu_clock_get_ns(data->clock_type) + data->ns);
+ }
+}
+
+static void dummy_io_handler_read(void *opaque)
+{
+}
+
static void bh_delete_cb(void *opaque)
{
BHTestData *data = opaque;
@@ -50,19 +88,6 @@
}
}
-typedef struct {
- EventNotifier e;
- int n;
- int active;
- bool auto_set;
-} EventNotifierTestData;
-
-static int event_active_cb(EventNotifier *e)
-{
- EventNotifierTestData *data = container_of(e, EventNotifierTestData, e);
- return data->active > 0;
-}
-
static void event_ready_cb(EventNotifier *e)
{
EventNotifierTestData *data = container_of(e, EventNotifierTestData, e);
@@ -231,11 +256,11 @@
{
EventNotifierTestData data = { .n = 0, .active = 0 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
+ aio_set_event_notifier(ctx, &data.e, event_ready_cb);
g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 0);
- aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+ aio_set_event_notifier(ctx, &data.e, NULL);
g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 0);
event_notifier_cleanup(&data.e);
@@ -245,8 +270,8 @@
{
EventNotifierTestData data = { .n = 0, .active = 1 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
- g_assert(aio_poll(ctx, false));
+ aio_set_event_notifier(ctx, &data.e, event_ready_cb);
+ g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 0);
g_assert_cmpint(data.active, ==, 1);
@@ -259,7 +284,7 @@
g_assert_cmpint(data.n, ==, 1);
g_assert_cmpint(data.active, ==, 0);
- aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+ aio_set_event_notifier(ctx, &data.e, NULL);
g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 1);
@@ -270,8 +295,8 @@
{
EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
- g_assert(aio_poll(ctx, false));
+ aio_set_event_notifier(ctx, &data.e, event_ready_cb);
+ g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 0);
g_assert_cmpint(data.active, ==, 10);
@@ -281,12 +306,12 @@
g_assert_cmpint(data.active, ==, 9);
g_assert(aio_poll(ctx, false));
- wait_for_aio();
+ wait_until_inactive(&data);
g_assert_cmpint(data.n, ==, 10);
g_assert_cmpint(data.active, ==, 0);
g_assert(!aio_poll(ctx, false));
- aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+ aio_set_event_notifier(ctx, &data.e, NULL);
g_assert(!aio_poll(ctx, false));
event_notifier_cleanup(&data.e);
}
@@ -297,7 +322,7 @@
EventNotifierTestData dummy = { .n = 0, .active = 1 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb, NULL);
+ aio_set_event_notifier(ctx, &data.e, event_ready_cb);
g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 0);
@@ -305,41 +330,99 @@
/* Until there is an active descriptor, aio_poll may or may not call
* event_ready_cb. Still, it must not block. */
event_notifier_set(&data.e);
- g_assert(!aio_poll(ctx, true));
+ g_assert(aio_poll(ctx, true));
data.n = 0;
/* An active event notifier forces aio_poll to look at EventNotifiers. */
event_notifier_init(&dummy.e, false);
- aio_set_event_notifier(ctx, &dummy.e, event_ready_cb, event_active_cb);
+ aio_set_event_notifier(ctx, &dummy.e, event_ready_cb);
event_notifier_set(&data.e);
g_assert(aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 1);
- g_assert(aio_poll(ctx, false));
+ g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 1);
event_notifier_set(&data.e);
g_assert(aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 2);
- g_assert(aio_poll(ctx, false));
+ g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 2);
event_notifier_set(&dummy.e);
- wait_for_aio();
+ wait_until_inactive(&dummy);
g_assert_cmpint(data.n, ==, 2);
g_assert_cmpint(dummy.n, ==, 1);
g_assert_cmpint(dummy.active, ==, 0);
- aio_set_event_notifier(ctx, &dummy.e, NULL, NULL);
+ aio_set_event_notifier(ctx, &dummy.e, NULL);
event_notifier_cleanup(&dummy.e);
- aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+ aio_set_event_notifier(ctx, &data.e, NULL);
g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 2);
event_notifier_cleanup(&data.e);
}
+static void test_timer_schedule(void)
+{
+ TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
+ .max = 2,
+ .clock_type = QEMU_CLOCK_VIRTUAL };
+ int pipefd[2];
+
+ /* aio_poll will not block to wait for timers to complete unless it has
+ * an fd to wait on. Fixing this breaks other tests. So create a dummy one.
+ */
+ g_assert(!pipe2(pipefd, O_NONBLOCK));
+ aio_set_fd_handler(ctx, pipefd[0],
+ dummy_io_handler_read, NULL, NULL);
+ aio_poll(ctx, false);
+
+ aio_timer_init(ctx, &data.timer, data.clock_type,
+ SCALE_NS, timer_test_cb, &data);
+ timer_mod(&data.timer,
+ qemu_clock_get_ns(data.clock_type) +
+ data.ns);
+
+ g_assert_cmpint(data.n, ==, 0);
+
+ /* timer_mod may well cause an event notifer to have gone off,
+ * so clear that
+ */
+ do {} while (aio_poll(ctx, false));
+
+ g_assert(!aio_poll(ctx, false));
+ g_assert_cmpint(data.n, ==, 0);
+
+ sleep(1);
+ g_assert_cmpint(data.n, ==, 0);
+
+ g_assert(aio_poll(ctx, false));
+ g_assert_cmpint(data.n, ==, 1);
+
+ /* timer_mod called by our callback */
+ do {} while (aio_poll(ctx, false));
+
+ g_assert(!aio_poll(ctx, false));
+ g_assert_cmpint(data.n, ==, 1);
+
+ g_assert(aio_poll(ctx, true));
+ g_assert_cmpint(data.n, ==, 2);
+
+ /* As max is now 2, an event notifier should not have gone off */
+
+ g_assert(!aio_poll(ctx, false));
+ g_assert_cmpint(data.n, ==, 2);
+
+ aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL);
+ close(pipefd[0]);
+ close(pipefd[1]);
+
+ timer_del(&data.timer);
+}
+
/* Now the same tests, using the context as a GSource. They are
* very similar to the ones above, with g_main_context_iteration
* replacing aio_poll. However:
@@ -513,11 +596,11 @@
{
EventNotifierTestData data = { .n = 0, .active = 0 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
+ aio_set_event_notifier(ctx, &data.e, event_ready_cb);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 0);
- aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+ aio_set_event_notifier(ctx, &data.e, NULL);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 0);
event_notifier_cleanup(&data.e);
@@ -527,7 +610,7 @@
{
EventNotifierTestData data = { .n = 0, .active = 1 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
+ aio_set_event_notifier(ctx, &data.e, event_ready_cb);
g_assert(g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 0);
g_assert_cmpint(data.active, ==, 1);
@@ -541,7 +624,7 @@
g_assert_cmpint(data.n, ==, 1);
g_assert_cmpint(data.active, ==, 0);
- aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+ aio_set_event_notifier(ctx, &data.e, NULL);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 1);
@@ -552,7 +635,7 @@
{
EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb, event_active_cb);
+ aio_set_event_notifier(ctx, &data.e, event_ready_cb);
g_assert(g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 0);
g_assert_cmpint(data.active, ==, 10);
@@ -568,7 +651,7 @@
g_assert_cmpint(data.active, ==, 0);
g_assert(!g_main_context_iteration(NULL, false));
- aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+ aio_set_event_notifier(ctx, &data.e, NULL);
while (g_main_context_iteration(NULL, false));
event_notifier_cleanup(&data.e);
}
@@ -579,7 +662,7 @@
EventNotifierTestData dummy = { .n = 0, .active = 1 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb, NULL);
+ aio_set_event_notifier(ctx, &data.e, event_ready_cb);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 0);
@@ -592,7 +675,7 @@
/* An active event notifier forces aio_poll to look at EventNotifiers. */
event_notifier_init(&dummy.e, false);
- aio_set_event_notifier(ctx, &dummy.e, event_ready_cb, event_active_cb);
+ aio_set_event_notifier(ctx, &dummy.e, event_ready_cb);
event_notifier_set(&data.e);
g_assert(g_main_context_iteration(NULL, false));
@@ -612,22 +695,71 @@
g_assert_cmpint(dummy.n, ==, 1);
g_assert_cmpint(dummy.active, ==, 0);
- aio_set_event_notifier(ctx, &dummy.e, NULL, NULL);
+ aio_set_event_notifier(ctx, &dummy.e, NULL);
event_notifier_cleanup(&dummy.e);
- aio_set_event_notifier(ctx, &data.e, NULL, NULL);
+ aio_set_event_notifier(ctx, &data.e, NULL);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 2);
event_notifier_cleanup(&data.e);
}
+static void test_source_timer_schedule(void)
+{
+ TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
+ .max = 2,
+ .clock_type = QEMU_CLOCK_VIRTUAL };
+ int pipefd[2];
+ int64_t expiry;
+
+ /* aio_poll will not block to wait for timers to complete unless it has
+ * an fd to wait on. Fixing this breaks other tests. So create a dummy one.
+ */
+ g_assert(!pipe2(pipefd, O_NONBLOCK));
+ aio_set_fd_handler(ctx, pipefd[0],
+ dummy_io_handler_read, NULL, NULL);
+ do {} while (g_main_context_iteration(NULL, false));
+
+ aio_timer_init(ctx, &data.timer, data.clock_type,
+ SCALE_NS, timer_test_cb, &data);
+ expiry = qemu_clock_get_ns(data.clock_type) +
+ data.ns;
+ timer_mod(&data.timer, expiry);
+
+ g_assert_cmpint(data.n, ==, 0);
+
+ sleep(1);
+ g_assert_cmpint(data.n, ==, 0);
+
+ g_assert(g_main_context_iteration(NULL, false));
+ g_assert_cmpint(data.n, ==, 1);
+
+ /* The comment above was not kidding when it said this wakes up itself */
+ do {
+ g_assert(g_main_context_iteration(NULL, true));
+ } while (qemu_clock_get_ns(data.clock_type) <= expiry);
+ sleep(1);
+ g_main_context_iteration(NULL, false);
+
+ g_assert_cmpint(data.n, ==, 2);
+
+ aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL);
+ close(pipefd[0]);
+ close(pipefd[1]);
+
+ timer_del(&data.timer);
+}
+
+
/* End of tests. */
int main(int argc, char **argv)
{
GSource *src;
+ init_clocks();
+
ctx = aio_context_new();
src = aio_get_g_source(ctx);
g_source_attach(src, NULL);
@@ -648,6 +780,7 @@
g_test_add_func("/aio/event/wait", test_wait_event_notifier);
g_test_add_func("/aio/event/wait/no-flush-cb", test_wait_event_notifier_noflush);
g_test_add_func("/aio/event/flush", test_flush_event_notifier);
+ g_test_add_func("/aio/timer/schedule", test_timer_schedule);
g_test_add_func("/aio-gsource/notify", test_source_notify);
g_test_add_func("/aio-gsource/flush", test_source_flush);
@@ -662,5 +795,6 @@
g_test_add_func("/aio-gsource/event/wait", test_source_wait_event_notifier);
g_test_add_func("/aio-gsource/event/wait/no-flush-cb", test_source_wait_event_notifier_noflush);
g_test_add_func("/aio-gsource/event/flush", test_source_flush_event_notifier);
+ g_test_add_func("/aio-gsource/timer/schedule", test_source_timer_schedule);
return g_test_run();
}
diff --git a/tests/test-opts-visitor.c b/tests/test-opts-visitor.c
new file mode 100644
index 0000000..9f902b5
--- /dev/null
+++ b/tests/test-opts-visitor.c
@@ -0,0 +1,275 @@
+/*
+ * Options Visitor unit-tests.
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * Authors:
+ * Laszlo Ersek <lersek@redhat.com> (based on test-string-output-visitor)
+ *
+ * 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 <glib.h>
+
+#include "qemu/config-file.h" /* qemu_add_opts() */
+#include "qemu/option.h" /* qemu_opts_parse() */
+#include "qapi/opts-visitor.h" /* opts_visitor_new() */
+#include "test-qapi-visit.h" /* visit_type_UserDefOptions() */
+#include "qapi/dealloc-visitor.h" /* qapi_dealloc_visitor_new() */
+
+static QemuOptsList userdef_opts = {
+ .name = "userdef",
+ .head = QTAILQ_HEAD_INITIALIZER(userdef_opts.head),
+ .desc = { { 0 } } /* validated with OptsVisitor */
+};
+
+/* fixture (= glib test case context) and test case manipulation */
+
+typedef struct OptsVisitorFixture {
+ UserDefOptions *userdef;
+ Error *err;
+} OptsVisitorFixture;
+
+
+static void
+setup_fixture(OptsVisitorFixture *f, gconstpointer test_data)
+{
+ const char *opts_string = test_data;
+ QemuOpts *opts;
+ OptsVisitor *ov;
+
+ opts = qemu_opts_parse(qemu_find_opts("userdef"), opts_string, 0);
+ g_assert(opts != NULL);
+
+ ov = opts_visitor_new(opts);
+ visit_type_UserDefOptions(opts_get_visitor(ov), &f->userdef, NULL,
+ &f->err);
+ opts_visitor_cleanup(ov);
+ qemu_opts_del(opts);
+}
+
+
+static void
+teardown_fixture(OptsVisitorFixture *f, gconstpointer test_data)
+{
+ if (f->userdef != NULL) {
+ QapiDeallocVisitor *dv;
+
+ dv = qapi_dealloc_visitor_new();
+ visit_type_UserDefOptions(qapi_dealloc_get_visitor(dv), &f->userdef,
+ NULL, NULL);
+ qapi_dealloc_visitor_cleanup(dv);
+ }
+ error_free(f->err);
+}
+
+
+static void
+add_test(const char *testpath,
+ void (*test_func)(OptsVisitorFixture *f, gconstpointer test_data),
+ gconstpointer test_data)
+{
+ g_test_add(testpath, OptsVisitorFixture, test_data, setup_fixture,
+ test_func, teardown_fixture);
+}
+
+/* test output evaluation */
+
+static void
+expect_ok(OptsVisitorFixture *f, gconstpointer test_data)
+{
+ g_assert(f->err == NULL);
+ g_assert(f->userdef != NULL);
+}
+
+
+static void
+expect_fail(OptsVisitorFixture *f, gconstpointer test_data)
+{
+ g_assert(f->err != NULL);
+
+ /* The error message is printed when this test utility is invoked directly
+ * (ie. without gtester) and the --verbose flag is passed:
+ *
+ * tests/test-opts-visitor --verbose
+ */
+ g_test_message("'%s': %s", (const char *)test_data,
+ error_get_pretty(f->err));
+}
+
+
+static void
+test_value(OptsVisitorFixture *f, gconstpointer test_data)
+{
+ uint64_t magic, bitval;
+ intList *i64;
+ uint64List *u64;
+ uint16List *u16;
+
+ expect_ok(f, test_data);
+
+ magic = 0;
+ for (i64 = f->userdef->i64; i64 != NULL; i64 = i64->next) {
+ g_assert(-16 <= i64->value && i64->value < 64-16);
+ bitval = 1ull << (i64->value + 16);
+ g_assert((magic & bitval) == 0);
+ magic |= bitval;
+ }
+ g_assert(magic == 0xDEADBEEF);
+
+ magic = 0;
+ for (u64 = f->userdef->u64; u64 != NULL; u64 = u64->next) {
+ g_assert(u64->value < 64);
+ bitval = 1ull << u64->value;
+ g_assert((magic & bitval) == 0);
+ magic |= bitval;
+ }
+ g_assert(magic == 0xBADC0FFEE0DDF00D);
+
+ magic = 0;
+ for (u16 = f->userdef->u16; u16 != NULL; u16 = u16->next) {
+ g_assert(u16->value < 64);
+ bitval = 1ull << u16->value;
+ g_assert((magic & bitval) == 0);
+ magic |= bitval;
+ }
+ g_assert(magic == 0xD15EA5E);
+}
+
+
+static void
+expect_i64_min(OptsVisitorFixture *f, gconstpointer test_data)
+{
+ expect_ok(f, test_data);
+ g_assert(f->userdef->has_i64);
+ g_assert(f->userdef->i64->next == NULL);
+ g_assert(f->userdef->i64->value == INT64_MIN);
+}
+
+
+static void
+expect_i64_max(OptsVisitorFixture *f, gconstpointer test_data)
+{
+ expect_ok(f, test_data);
+ g_assert(f->userdef->has_i64);
+ g_assert(f->userdef->i64->next == NULL);
+ g_assert(f->userdef->i64->value == INT64_MAX);
+}
+
+
+static void
+expect_zero(OptsVisitorFixture *f, gconstpointer test_data)
+{
+ expect_ok(f, test_data);
+ g_assert(f->userdef->has_u64);
+ g_assert(f->userdef->u64->next == NULL);
+ g_assert(f->userdef->u64->value == 0);
+}
+
+
+static void
+expect_u64_max(OptsVisitorFixture *f, gconstpointer test_data)
+{
+ expect_ok(f, test_data);
+ g_assert(f->userdef->has_u64);
+ g_assert(f->userdef->u64->next == NULL);
+ g_assert(f->userdef->u64->value == UINT64_MAX);
+}
+
+/* test cases */
+
+int
+main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ qemu_add_opts(&userdef_opts);
+
+ /* Three hexadecimal magic numbers, "dead beef", "bad coffee, odd food" and
+ * "disease", from
+ * <http://en.wikipedia.org/wiki/Magic_number_%28programming%29>, were
+ * converted to binary and dissected into bit ranges. Each magic number is
+ * going to be recomposed using the lists called "i64", "u64" and "u16",
+ * respectively.
+ *
+ * (Note that these types pertain to the individual bit shift counts, not
+ * the magic numbers themselves; the intent is to exercise opts_type_int()
+ * and opts_type_uint64().)
+ *
+ * The "i64" shift counts have been decreased by 16 (decimal) in order to
+ * test negative values as well. Finally, the full list of QemuOpt elements
+ * has been permuted with "shuf".
+ *
+ * Both "i64" and "u64" have some (distinct) single-element ranges
+ * represented as both "a" and "a-a". "u16" is a special case of "i64" (see
+ * visit_type_uint16()), so it wouldn't add a separate test in this regard.
+ */
+
+ add_test("/visitor/opts/flatten/value", &test_value,
+ "i64=-1-0,u64=12-16,u64=2-3,i64=-11--9,u64=57,u16=9,i64=5-5,"
+ "u16=1-4,u16=20,u64=63-63,i64=-16--13,u64=50-52,i64=14-15,u16=11,"
+ "i64=7,u16=18,i64=2-3,u16=6,u64=54-55,u64=0,u64=18-20,u64=33-43,"
+ "i64=9-12,u16=26-27,u64=59-61,u16=13-16,u64=29-31,u64=22-23,"
+ "u16=24,i64=-7--3");
+
+ add_test("/visitor/opts/i64/val1/errno", &expect_fail,
+ "i64=0x8000000000000000");
+ add_test("/visitor/opts/i64/val1/empty", &expect_fail, "i64=");
+ add_test("/visitor/opts/i64/val1/trailing", &expect_fail, "i64=5z");
+ add_test("/visitor/opts/i64/nonlist", &expect_fail, "i64x=5-6");
+ add_test("/visitor/opts/i64/val2/errno", &expect_fail,
+ "i64=0x7fffffffffffffff-0x8000000000000000");
+ add_test("/visitor/opts/i64/val2/empty", &expect_fail, "i64=5-");
+ add_test("/visitor/opts/i64/val2/trailing", &expect_fail, "i64=5-6z");
+ add_test("/visitor/opts/i64/range/empty", &expect_fail, "i64=6-5");
+ add_test("/visitor/opts/i64/range/minval", &expect_i64_min,
+ "i64=-0x8000000000000000--0x8000000000000000");
+ add_test("/visitor/opts/i64/range/maxval", &expect_i64_max,
+ "i64=0x7fffffffffffffff-0x7fffffffffffffff");
+
+ add_test("/visitor/opts/u64/val1/errno", &expect_fail, "u64=-1");
+ add_test("/visitor/opts/u64/val1/empty", &expect_fail, "u64=");
+ add_test("/visitor/opts/u64/val1/trailing", &expect_fail, "u64=5z");
+ add_test("/visitor/opts/u64/nonlist", &expect_fail, "u64x=5-6");
+ add_test("/visitor/opts/u64/val2/errno", &expect_fail,
+ "u64=0xffffffffffffffff-0x10000000000000000");
+ add_test("/visitor/opts/u64/val2/empty", &expect_fail, "u64=5-");
+ add_test("/visitor/opts/u64/val2/trailing", &expect_fail, "u64=5-6z");
+ add_test("/visitor/opts/u64/range/empty", &expect_fail, "u64=6-5");
+ add_test("/visitor/opts/u64/range/minval", &expect_zero, "u64=0-0");
+ add_test("/visitor/opts/u64/range/maxval", &expect_u64_max,
+ "u64=0xffffffffffffffff-0xffffffffffffffff");
+
+ /* Test maximum range sizes. The macro value is open-coded here
+ * *intentionally*; the test case must use concrete values by design. If
+ * OPTS_VISITOR_RANGE_MAX is changed, the following values need to be
+ * recalculated as well. The assert and this comment should help with it.
+ */
+ g_assert(OPTS_VISITOR_RANGE_MAX == 65536);
+
+ /* The unsigned case is simple, a u64-u64 difference can always be
+ * represented as a u64.
+ */
+ add_test("/visitor/opts/u64/range/max", &expect_ok, "u64=0-65535");
+ add_test("/visitor/opts/u64/range/2big", &expect_fail, "u64=0-65536");
+
+ /* The same cannot be said about an i64-i64 difference. */
+ add_test("/visitor/opts/i64/range/max/pos/a", &expect_ok,
+ "i64=0x7fffffffffff0000-0x7fffffffffffffff");
+ add_test("/visitor/opts/i64/range/max/pos/b", &expect_ok,
+ "i64=0x7ffffffffffeffff-0x7ffffffffffffffe");
+ add_test("/visitor/opts/i64/range/2big/pos", &expect_fail,
+ "i64=0x7ffffffffffeffff-0x7fffffffffffffff");
+ add_test("/visitor/opts/i64/range/max/neg/a", &expect_ok,
+ "i64=-0x8000000000000000--0x7fffffffffff0001");
+ add_test("/visitor/opts/i64/range/max/neg/b", &expect_ok,
+ "i64=-0x7fffffffffffffff--0x7fffffffffff0000");
+ add_test("/visitor/opts/i64/range/2big/neg", &expect_fail,
+ "i64=-0x8000000000000000--0x7fffffffffff0000");
+ add_test("/visitor/opts/i64/range/2big/full", &expect_fail,
+ "i64=-0x8000000000000000-0x7fffffffffffffff");
+
+ g_test_run();
+ return 0;
+}
diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
new file mode 100644
index 0000000..e4ad173
--- /dev/null
+++ b/tests/test-qdev-global-props.c
@@ -0,0 +1,180 @@
+/*
+ * Test code for qdev global-properties handling
+ *
+ * Copyright (c) 2012 Red Hat 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.
+ */
+
+#include <glib.h>
+#include <stdint.h>
+
+#include "hw/qdev.h"
+#include "qom/object.h"
+#include "qapi/visitor.h"
+
+
+#define TYPE_STATIC_PROPS "static_prop_type"
+#define STATIC_TYPE(obj) \
+ OBJECT_CHECK(MyType, (obj), TYPE_STATIC_PROPS)
+
+#define PROP_DEFAULT 100
+
+typedef struct MyType {
+ DeviceState parent_obj;
+
+ uint32_t prop1;
+ uint32_t prop2;
+} MyType;
+
+static Property static_props[] = {
+ DEFINE_PROP_UINT32("prop1", MyType, prop1, PROP_DEFAULT),
+ DEFINE_PROP_UINT32("prop2", MyType, prop2, PROP_DEFAULT),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void static_prop_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = NULL;
+ dc->props = static_props;
+}
+
+static const TypeInfo static_prop_type = {
+ .name = TYPE_STATIC_PROPS,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(MyType),
+ .class_init = static_prop_class_init,
+};
+
+/* Test simple static property setting to default value */
+static void test_static_prop(void)
+{
+ MyType *mt;
+
+ mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
+ qdev_init_nofail(DEVICE(mt));
+
+ g_assert_cmpuint(mt->prop1, ==, PROP_DEFAULT);
+}
+
+/* Test setting of static property using global properties */
+static void test_static_globalprop(void)
+{
+ MyType *mt;
+ static GlobalProperty props[] = {
+ { TYPE_STATIC_PROPS, "prop1", "200" },
+ {}
+ };
+
+ qdev_prop_register_global_list(props);
+
+ mt = STATIC_TYPE(object_new(TYPE_STATIC_PROPS));
+ qdev_init_nofail(DEVICE(mt));
+
+ g_assert_cmpuint(mt->prop1, ==, 200);
+ g_assert_cmpuint(mt->prop2, ==, PROP_DEFAULT);
+}
+
+#define TYPE_DYNAMIC_PROPS "dynamic-prop-type"
+#define DYNAMIC_TYPE(obj) \
+ OBJECT_CHECK(MyType, (obj), TYPE_DYNAMIC_PROPS)
+
+static void prop1_accessor(Object *obj,
+ Visitor *v,
+ void *opaque,
+ const char *name,
+ Error **errp)
+{
+ MyType *mt = DYNAMIC_TYPE(obj);
+
+ visit_type_uint32(v, &mt->prop1, name, errp);
+}
+
+static void prop2_accessor(Object *obj,
+ Visitor *v,
+ void *opaque,
+ const char *name,
+ Error **errp)
+{
+ MyType *mt = DYNAMIC_TYPE(obj);
+
+ visit_type_uint32(v, &mt->prop2, name, errp);
+}
+
+static void dynamic_instance_init(Object *obj)
+{
+ object_property_add(obj, "prop1", "uint32", prop1_accessor, prop1_accessor,
+ NULL, NULL, NULL);
+ object_property_add(obj, "prop2", "uint32", prop2_accessor, prop2_accessor,
+ NULL, NULL, NULL);
+}
+
+static void dynamic_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = NULL;
+}
+
+
+static const TypeInfo dynamic_prop_type = {
+ .name = TYPE_DYNAMIC_PROPS,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(MyType),
+ .instance_init = dynamic_instance_init,
+ .class_init = dynamic_class_init,
+};
+
+/* Test setting of static property using global properties */
+static void test_dynamic_globalprop(void)
+{
+ MyType *mt;
+ static GlobalProperty props[] = {
+ { TYPE_DYNAMIC_PROPS, "prop1", "101" },
+ { TYPE_DYNAMIC_PROPS, "prop2", "102" },
+ {}
+ };
+
+ qdev_prop_register_global_list(props);
+
+ mt = DYNAMIC_TYPE(object_new(TYPE_DYNAMIC_PROPS));
+ qdev_init_nofail(DEVICE(mt));
+
+ g_assert_cmpuint(mt->prop1, ==, 101);
+ g_assert_cmpuint(mt->prop2, ==, 102);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+ type_register_static(&static_prop_type);
+ type_register_static(&dynamic_prop_type);
+
+ g_test_add_func("/qdev/properties/static/default", test_static_prop);
+ g_test_add_func("/qdev/properties/static/global", test_static_globalprop);
+ g_test_add_func("/qdev/properties/dynamic/global", test_dynamic_globalprop);
+
+ g_test_run();
+
+ return 0;
+}
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index 2741eef..0beb8fb 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -394,7 +394,7 @@
break;
}
default:
- g_assert(false);
+ g_assert_not_reached();
}
g_string_free(gstr_union, true);
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
index b2fa9a7..e073d83 100644
--- a/tests/test-qmp-output-visitor.c
+++ b/tests/test-qmp-output-visitor.c
@@ -559,7 +559,7 @@
break;
}
default:
- g_assert(false);
+ g_assert_not_reached();
}
}
@@ -645,7 +645,7 @@
}
break;
default:
- g_assert(false);
+ g_assert_not_reached();
}
QDECREF(qlist);
}
diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
index b62338f..c1f8e13 100644
--- a/tests/test-thread-pool.c
+++ b/tests/test-thread-pool.c
@@ -3,6 +3,7 @@
#include "block/aio.h"
#include "block/thread-pool.h"
#include "block/block.h"
+#include "qemu/timer.h"
static AioContext *ctx;
static ThreadPool *pool;
@@ -40,19 +41,13 @@
active--;
}
-/* Wait until all aio and bh activity has finished */
-static void qemu_aio_wait_all(void)
-{
- while (aio_poll(ctx, true)) {
- /* Do nothing */
- }
-}
-
static void test_submit(void)
{
WorkerTestData data = { .n = 0 };
thread_pool_submit(pool, worker_cb, &data);
- qemu_aio_wait_all();
+ while (data.n == 0) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(data.n, ==, 1);
}
@@ -65,7 +60,9 @@
/* The callbacks are not called until after the first wait. */
active = 1;
g_assert_cmpint(data.ret, ==, -EINPROGRESS);
- qemu_aio_wait_all();
+ while (data.ret == -EINPROGRESS) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(active, ==, 0);
g_assert_cmpint(data.n, ==, 1);
g_assert_cmpint(data.ret, ==, 0);
@@ -103,7 +100,9 @@
/* qemu_aio_wait_all will execute the rest of the coroutine. */
- qemu_aio_wait_all();
+ while (data.ret == -EINPROGRESS) {
+ aio_poll(ctx, true);
+ }
/* Back here after the coroutine has finished. */
@@ -187,7 +186,9 @@
}
/* Finish execution and execute any remaining callbacks. */
- qemu_aio_wait_all();
+ while (active > 0) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(active, ==, 0);
for (i = 0; i < 100; i++) {
if (data[i].n == 3) {
@@ -205,6 +206,8 @@
{
int ret;
+ init_clocks();
+
ctx = aio_context_new();
pool = aio_get_thread_pool(ctx);
diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index ee7916b..9aaa587 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -136,7 +136,7 @@
visit_type_int64(v, &pt->value.s64, NULL, errp);
break;
case PTYPE_EOL:
- g_assert(false);
+ g_assert_not_reached();
}
}
@@ -181,7 +181,7 @@
visit_type_uint64List(v, &pl->value.u64_integers, NULL, errp);
break;
default:
- g_assert(false);
+ g_assert_not_reached();
}
}
@@ -500,7 +500,7 @@
break;
}
default:
- g_assert(0);
+ g_assert_not_reached();
}
}
@@ -656,7 +656,7 @@
break;
}
default:
- g_assert(0);
+ g_assert_not_reached();
}
i++;
} while (cur_head);
diff --git a/thread-pool.c b/thread-pool.c
index 0ebd4c2..3735fd3 100644
--- a/thread-pool.c
+++ b/thread-pool.c
@@ -23,6 +23,7 @@
#include "block/block_int.h"
#include "qemu/event_notifier.h"
#include "block/thread-pool.h"
+#include "qemu/main-loop.h"
static void do_spawn_thread(ThreadPool *pool);
@@ -197,12 +198,6 @@
}
}
-static int thread_pool_active(EventNotifier *notifier)
-{
- ThreadPool *pool = container_of(notifier, ThreadPool, notifier);
- return !QLIST_EMPTY(&pool->head);
-}
-
static void thread_pool_cancel(BlockDriverAIOCB *acb)
{
ThreadPoolElement *elem = (ThreadPoolElement *)acb;
@@ -309,8 +304,7 @@
QLIST_INIT(&pool->head);
QTAILQ_INIT(&pool->request_list);
- aio_set_event_notifier(ctx, &pool->notifier, event_notifier_ready,
- thread_pool_active);
+ aio_set_event_notifier(ctx, &pool->notifier, event_notifier_ready);
}
ThreadPool *thread_pool_new(AioContext *ctx)
@@ -344,7 +338,7 @@
qemu_mutex_unlock(&pool->lock);
- aio_set_event_notifier(pool->ctx, &pool->notifier, NULL, NULL);
+ aio_set_event_notifier(pool->ctx, &pool->notifier, NULL);
qemu_sem_destroy(&pool->sem);
qemu_cond_destroy(&pool->check_cancel);
qemu_cond_destroy(&pool->worker_stopped);
diff --git a/tpm.c b/tpm.c
index f13c9bc..d68d69f 100644
--- a/tpm.c
+++ b/tpm.c
@@ -32,7 +32,7 @@
};
static enum TpmModel tpm_models[TPM_MAX_MODELS] = {
- -1,
+ TPM_MODEL_MAX,
};
int tpm_register_model(enum TpmModel model)
@@ -40,7 +40,7 @@
int i;
for (i = 0; i < TPM_MAX_MODELS; i++) {
- if (tpm_models[i] == -1) {
+ if (tpm_models[i] == TPM_MODEL_MAX) {
tpm_models[i] = model;
return 0;
}
diff --git a/trace-events b/trace-events
index 002df83..3856b5c 100644
--- a/trace-events
+++ b/trace-events
@@ -1165,6 +1165,14 @@
kvm_vcpu_ioctl(int cpu_index, int type, void *arg) "cpu_index %d, type %d, arg %p"
kvm_run_exit(int cpu_index, uint32_t reason) "cpu_index %d, reason %d"
+# memory.c
+memory_region_ops_read(void *mr, uint64_t addr, uint64_t value, unsigned size) "mr %p addr %#"PRIx64" value %#"PRIx64" size %u"
+memory_region_ops_write(void *mr, uint64_t addr, uint64_t value, unsigned size) "mr %p addr %#"PRIx64" value %#"PRIx64" size %u"
+
# qom/object.c
object_dynamic_cast_assert(const char *type, const char *target, const char *file, int line, const char *func) "%s->%s (%s:%d:%s)"
object_class_dynamic_cast_assert(const char *type, const char *target, const char *file, int line, const char *func) "%s->%s (%s:%d:%s)"
+
+# hw/xen/xen_pvdevice.c
+xen_pv_mmio_read(uint64_t addr) "WARNING: read from Xen PV Device MMIO space (address %"PRIx64")"
+xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space (address %"PRIx64")"
diff --git a/translate-all.c b/translate-all.c
index e8683d2..3b5fc7c 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1148,7 +1148,8 @@
#if !defined(CONFIG_SOFTMMU)
static void tb_invalidate_phys_page(tb_page_addr_t addr,
- uintptr_t pc, void *puc)
+ uintptr_t pc, void *puc,
+ bool locked)
{
TranslationBlock *tb;
PageDesc *p;
@@ -1206,6 +1207,9 @@
itself */
cpu->current_tb = NULL;
tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
+ if (locked) {
+ mmap_unlock();
+ }
cpu_resume_from_signal(env, puc);
}
#endif
@@ -1723,7 +1727,7 @@
if (!(p->flags & PAGE_WRITE) &&
(flags & PAGE_WRITE) &&
p->first_tb) {
- tb_invalidate_phys_page(addr, 0, NULL);
+ tb_invalidate_phys_page(addr, 0, NULL, false);
}
p->flags = flags;
}
@@ -1818,7 +1822,7 @@
/* and since the content will be modified, we must invalidate
the corresponding translated code. */
- tb_invalidate_phys_page(addr, pc, puc);
+ tb_invalidate_phys_page(addr, pc, puc, true);
#ifdef DEBUG_TB_CHECK
tb_invalidate_check(addr);
#endif
diff --git a/ui/console.c b/ui/console.c
index e3e8297..aad4fc9 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -208,8 +208,8 @@
}
trace_console_refresh(interval);
}
- ds->last_update = qemu_get_clock_ms(rt_clock);
- qemu_mod_timer(ds->gui_timer, ds->last_update + interval);
+ ds->last_update = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+ timer_mod(ds->gui_timer, ds->last_update + interval);
}
static void gui_setup_refresh(DisplayState *ds)
@@ -232,12 +232,12 @@
}
if (need_timer && ds->gui_timer == NULL) {
- ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds);
- qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock));
+ ds->gui_timer = timer_new_ms(QEMU_CLOCK_REALTIME, gui_update, ds);
+ timer_mod(ds->gui_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
}
if (!need_timer && ds->gui_timer != NULL) {
- qemu_del_timer(ds->gui_timer);
- qemu_free_timer(ds->gui_timer);
+ timer_del(ds->gui_timer);
+ timer_free(ds->gui_timer);
ds->gui_timer = NULL;
}
@@ -1040,7 +1040,7 @@
DisplayState *ds = s->ds;
if (active_console && active_console->cursor_timer) {
- qemu_del_timer(active_console->cursor_timer);
+ timer_del(active_console->cursor_timer);
}
active_console = s;
if (ds->have_gfx) {
@@ -1059,8 +1059,8 @@
dpy_text_resize(s, s->width, s->height);
}
if (s->cursor_timer) {
- qemu_mod_timer(s->cursor_timer,
- qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
+ timer_mod(s->cursor_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + CONSOLE_CURSOR_PERIOD / 2);
}
}
}
@@ -1105,7 +1105,7 @@
/* characters are pending: we send them a bit later (XXX:
horrible, should change char device API) */
if (s->out_fifo.count > 0) {
- qemu_mod_timer(s->kbd_timer, qemu_get_clock_ms(rt_clock) + 1);
+ timer_mod(s->kbd_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1);
}
}
@@ -1366,7 +1366,7 @@
dcl->update_interval = interval;
if (!ds->refreshing && ds->update_interval > interval) {
- qemu_mod_timer(ds->gui_timer, ds->last_update + interval);
+ timer_mod(ds->gui_timer, ds->last_update + interval);
}
}
@@ -1691,8 +1691,8 @@
s->cursor_visible_phase = !s->cursor_visible_phase;
graphic_hw_invalidate(s);
- qemu_mod_timer(s->cursor_timer,
- qemu_get_clock_ms(rt_clock) + CONSOLE_CURSOR_PERIOD / 2);
+ timer_mod(s->cursor_timer,
+ qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + CONSOLE_CURSOR_PERIOD / 2);
}
static const GraphicHwOps text_console_ops = {
@@ -1712,7 +1712,7 @@
s->out_fifo.buf = s->out_fifo_buf;
s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
- s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s);
+ s->kbd_timer = timer_new_ms(QEMU_CLOCK_REALTIME, kbd_send_chars, s);
s->ds = ds;
s->y_displayed = 0;
@@ -1729,7 +1729,7 @@
}
s->cursor_timer =
- qemu_new_timer_ms(rt_clock, text_console_update_cursor, s);
+ timer_new_ms(QEMU_CLOCK_REALTIME, text_console_update_cursor, s);
s->hw_ops = &text_console_ops;
s->hw = s;
diff --git a/ui/gtk.c b/ui/gtk.c
index c38146f..b5f4f0b 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -51,10 +51,6 @@
#include <glib/gi18n.h>
#include <locale.h>
#include <vte/vte.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/wait.h>
#include <math.h>
#include "ui/console.h"
diff --git a/ui/input.c b/ui/input.c
index 92c44ca..10d8c05 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -277,11 +277,11 @@
KeyValueList *p;
if (!key_timer) {
- key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL);
+ key_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, release_keys, NULL);
}
if (keycodes != NULL) {
- qemu_del_timer(key_timer);
+ timer_del(key_timer);
release_keys(NULL);
}
@@ -308,7 +308,7 @@
}
/* delayed key up events */
- qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) +
+ timer_mod(key_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
muldiv64(get_ticks_per_sec(), hold_time, 1000));
}
diff --git a/ui/spice-core.c b/ui/spice-core.c
index f308fd9..3a2cd7e 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -48,6 +48,7 @@
static time_t auth_expires = TIME_MAX;
static int spice_migration_completed;
int using_spice = 0;
+int spice_displays;
static QemuThread me;
@@ -62,25 +63,25 @@
SpiceTimer *timer;
timer = g_malloc0(sizeof(*timer));
- timer->timer = qemu_new_timer_ms(rt_clock, func, opaque);
+ timer->timer = timer_new_ms(QEMU_CLOCK_REALTIME, func, opaque);
QTAILQ_INSERT_TAIL(&timers, timer, next);
return timer;
}
static void timer_start(SpiceTimer *timer, uint32_t ms)
{
- qemu_mod_timer(timer->timer, qemu_get_clock_ms(rt_clock) + ms);
+ timer_mod(timer->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + ms);
}
static void timer_cancel(SpiceTimer *timer)
{
- qemu_del_timer(timer->timer);
+ timer_del(timer->timer);
}
static void timer_remove(SpiceTimer *timer)
{
- qemu_del_timer(timer->timer);
- qemu_free_timer(timer->timer);
+ timer_del(timer->timer);
+ timer_free(timer->timer);
QTAILQ_REMOVE(&timers, timer, next);
g_free(timer);
}
@@ -563,7 +564,7 @@
{
MigrationState *s = data;
- if (migration_is_active(s)) {
+ if (migration_in_setup(s)) {
spice_server_migrate_start(spice_server);
} else if (migration_has_finished(s)) {
spice_server_migrate_end(spice_server, true);
@@ -836,6 +837,10 @@
qemu_add_vm_change_state_handler(vm_change_state_handler, NULL);
}
+ if (strcmp(sin->sif->type, SPICE_INTERFACE_QXL) == 0) {
+ spice_displays++;
+ }
+
return spice_server_add_interface(spice_server, sin);
}
diff --git a/ui/vnc-auth-sasl.h b/ui/vnc-auth-sasl.h
index 8091d68..3f59da6 100644
--- a/ui/vnc-auth-sasl.h
+++ b/ui/vnc-auth-sasl.h
@@ -33,6 +33,7 @@
typedef struct VncDisplaySASL VncDisplaySASL;
#include "qemu/acl.h"
+#include "qemu/main-loop.h"
struct VncStateSASL {
sasl_conn_t *conn;
diff --git a/ui/vnc-auth-vencrypt.c b/ui/vnc-auth-vencrypt.c
index c59b188..bc7032e 100644
--- a/ui/vnc-auth-vencrypt.c
+++ b/ui/vnc-auth-vencrypt.c
@@ -25,7 +25,7 @@
*/
#include "vnc.h"
-
+#include "qemu/main-loop.h"
static void start_auth_vencrypt_subauth(VncState *vs)
{
diff --git a/ui/vnc-ws.c b/ui/vnc-ws.c
index df89315..e304baf 100644
--- a/ui/vnc-ws.c
+++ b/ui/vnc-ws.c
@@ -19,6 +19,7 @@
*/
#include "vnc.h"
+#include "qemu/main-loop.h"
#ifdef CONFIG_VNC_TLS
#include "qemu/sockets.h"
diff --git a/user-exec.c b/user-exec.c
index d45ca8e..82bfa66 100644
--- a/user-exec.c
+++ b/user-exec.c
@@ -95,6 +95,10 @@
return 1;
}
+ /* Convert forcefully to guest address space, invalid addresses
+ are still valid segv ones */
+ address = h2g_nocheck(address);
+
env = current_cpu->env_ptr;
/* see if it is an MMU fault */
ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX);
diff --git a/util/aes.c b/util/aes.c
index 91e97fa..4b4d88e 100644
--- a/util/aes.c
+++ b/util/aes.c
@@ -30,12 +30,7 @@
#include "qemu-common.h"
#include "qemu/aes.h"
-#ifndef NDEBUG
-#define NDEBUG
-#endif
-
typedef uint32_t u32;
-typedef uint16_t u16;
typedef uint8_t u8;
/* This controls loop-unrolling in aes_core.c */
diff --git a/util/iov.c b/util/iov.c
index cc6e837..f705586 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -202,6 +202,12 @@
return -1;
}
+ if (ret == 0 && !do_send) {
+ /* recv returns 0 when the peer has performed an orderly
+ * shutdown. */
+ break;
+ }
+
/* Prepare for the next iteration */
offset += ret;
total += ret;
diff --git a/util/qemu-option.c b/util/qemu-option.c
index e0ef426..4ebdc4c 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -173,8 +173,8 @@
}
}
-static void parse_option_size(const char *name, const char *value,
- uint64_t *ret, Error **errp)
+void parse_option_size(const char *name, const char *value,
+ uint64_t *ret, Error **errp)
{
char *postfix;
double sizef;
@@ -593,6 +593,20 @@
return NULL;
}
+int qemu_opt_unset(QemuOpts *opts, const char *name)
+{
+ QemuOpt *opt = qemu_opt_find(opts, name);
+
+ assert(opts_accepts_any(opts));
+
+ if (opt == NULL) {
+ return -1;
+ } else {
+ qemu_opt_del(opt);
+ return 0;
+ }
+}
+
static void opt_set(QemuOpts *opts, const char *name, const char *value,
bool prepend, Error **errp)
{
@@ -914,6 +928,15 @@
get_opt_value(value, sizeof(value), p+4);
id = value;
}
+
+ /*
+ * This code doesn't work for defaults && !list->merge_lists: when
+ * params has no id=, and list has an element with !opts->id, it
+ * appends a new element instead of returning the existing opts.
+ * However, we got no use for this case. Guard against possible
+ * (if unlikely) future misuse:
+ */
+ assert(!defaults || list->merge_lists);
opts = qemu_opts_create(list, id, !defaults, &local_err);
if (opts == NULL) {
if (error_is_set(&local_err)) {
diff --git a/util/qemu-thread-posix.c b/util/qemu-thread-posix.c
index 4489abf..4de133e 100644
--- a/util/qemu-thread-posix.c
+++ b/util/qemu-thread-posix.c
@@ -170,12 +170,11 @@
#if defined(__APPLE__) || defined(__NetBSD__)
pthread_mutex_lock(&sem->lock);
- if (sem->count == INT_MAX) {
+ if (sem->count == UINT_MAX) {
rc = EINVAL;
- } else if (sem->count++ < 0) {
- rc = pthread_cond_signal(&sem->cond);
} else {
- rc = 0;
+ sem->count++;
+ rc = pthread_cond_signal(&sem->cond);
}
pthread_mutex_unlock(&sem->lock);
if (rc != 0) {
@@ -207,19 +206,21 @@
struct timespec ts;
#if defined(__APPLE__) || defined(__NetBSD__)
+ rc = 0;
compute_abs_deadline(&ts, ms);
pthread_mutex_lock(&sem->lock);
- --sem->count;
- while (sem->count < 0) {
+ while (sem->count == 0) {
rc = pthread_cond_timedwait(&sem->cond, &sem->lock, &ts);
if (rc == ETIMEDOUT) {
- ++sem->count;
break;
}
if (rc != 0) {
error_exit(rc, __func__);
}
}
+ if (rc != ETIMEDOUT) {
+ --sem->count;
+ }
pthread_mutex_unlock(&sem->lock);
return (rc == ETIMEDOUT ? -1 : 0);
#else
@@ -249,16 +250,19 @@
void qemu_sem_wait(QemuSemaphore *sem)
{
-#if defined(__APPLE__) || defined(__NetBSD__)
- pthread_mutex_lock(&sem->lock);
- --sem->count;
- while (sem->count < 0) {
- pthread_cond_wait(&sem->cond, &sem->lock);
- }
- pthread_mutex_unlock(&sem->lock);
-#else
int rc;
+#if defined(__APPLE__) || defined(__NetBSD__)
+ pthread_mutex_lock(&sem->lock);
+ while (sem->count == 0) {
+ rc = pthread_cond_wait(&sem->cond, &sem->lock);
+ if (rc != 0) {
+ error_exit(rc, __func__);
+ }
+ }
+ --sem->count;
+ pthread_mutex_unlock(&sem->lock);
+#else
do {
rc = sem_wait(&sem->sem);
} while (rc == -1 && errno == EINTR);
diff --git a/version.rc b/version.rc
index 82e10ec..a50d62f 100644
--- a/version.rc
+++ b/version.rc
@@ -26,3 +26,5 @@
VALUE "Translation", 0x0409, 1252
}
}
+
+IDI_ICON1 ICON "pc-bios/qemu-nsis.ico"
diff --git a/vl.c b/vl.c
index 25b8f2f..dfbc071 100644
--- a/vl.c
+++ b/vl.c
@@ -196,7 +196,7 @@
int autostart;
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
-QEMUClock *rtc_clock;
+QEMUClockType rtc_clock;
int vga_interface_type = VGA_NONE;
static int full_screen = 0;
static int no_frame = 0;
@@ -805,11 +805,11 @@
value = qemu_opt_get(opts, "clock");
if (value) {
if (!strcmp(value, "host")) {
- rtc_clock = host_clock;
+ rtc_clock = QEMU_CLOCK_HOST;
} else if (!strcmp(value, "rt")) {
- rtc_clock = rt_clock;
+ rtc_clock = QEMU_CLOCK_REALTIME;
} else if (!strcmp(value, "vm")) {
- rtc_clock = vm_clock;
+ rtc_clock = QEMU_CLOCK_VIRTUAL;
} else {
fprintf(stderr, "qemu: invalid option value '%s'\n", value);
exit(1);
@@ -2393,7 +2393,7 @@
qemu_chr_new_from_opts(opts, NULL, &local_err);
if (error_is_set(&local_err)) {
- fprintf(stderr, "%s\n", error_get_pretty(local_err));
+ error_report("%s", error_get_pretty(local_err));
error_free(local_err);
return -1;
}
@@ -2965,7 +2965,7 @@
runstate_init();
init_clocks();
- rtc_clock = host_clock;
+ rtc_clock = QEMU_CLOCK_HOST;
qemu_cache_utils_init(envp);
@@ -3714,7 +3714,9 @@
old_param = 1;
break;
case QEMU_OPTION_clock:
- configure_alarms(optarg);
+ /* Clock options no longer exist. Keep this option for
+ * backward compatibility.
+ */
break;
case QEMU_OPTION_startdate:
configure_rtc_date_offset(optarg, 1);
@@ -4375,8 +4377,8 @@
vnc_display_init(ds);
vnc_display_open(ds, vnc_display, &local_err);
if (local_err != NULL) {
- fprintf(stderr, "Failed to start VNC server on `%s': %s\n",
- vnc_display, error_get_pretty(local_err));
+ error_report("Failed to start VNC server on `%s': %s",
+ vnc_display, error_get_pretty(local_err));
error_free(local_err);
exit(1);
}
@@ -4387,7 +4389,7 @@
}
#endif
#ifdef CONFIG_SPICE
- if (using_spice && !qxl_enabled) {
+ if (using_spice && !spice_displays) {
qemu_spice_display_init(ds);
}
#endif
@@ -4419,7 +4421,8 @@
Error *local_err = NULL;
qemu_start_incoming_migration(incoming, &local_err);
if (local_err) {
- fprintf(stderr, "-incoming %s: %s\n", incoming, error_get_pretty(local_err));
+ error_report("-incoming %s: %s", incoming,
+ error_get_pretty(local_err));
error_free(local_err);
exit(1);
}
diff --git a/xen-all.c b/xen-all.c
index 21246e0..eb13111 100644
--- a/xen-all.c
+++ b/xen-all.c
@@ -606,8 +606,8 @@
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));
+ timer_mod(state->buffered_io_timer,
+ BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
return NULL;
}
@@ -828,10 +828,10 @@
XenIOState *state = opaque;
if (handle_buffered_iopage(state)) {
- qemu_mod_timer(state->buffered_io_timer,
- BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
+ timer_mod(state->buffered_io_timer,
+ BUFFER_IO_MAX_DELAY + qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
} else {
- qemu_del_timer(state->buffered_io_timer);
+ timer_del(state->buffered_io_timer);
xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
}
}
@@ -962,7 +962,7 @@
evtchn_fd = xc_evtchn_fd(state->xce_handle);
}
- state->buffered_io_timer = qemu_new_timer_ms(rt_clock, handle_buffered_io,
+ state->buffered_io_timer = timer_new_ms(QEMU_CLOCK_REALTIME, handle_buffered_io,
state);
if (evtchn_fd != -1) {