diff options
327 files changed, 5323 insertions, 3016 deletions
diff --git a/.gitignore b/.gitignore index 0fe114d251..d2c5c2f6b8 100644 --- a/.gitignore +++ b/.gitignore @@ -45,7 +45,10 @@ qemu-bridge-helper 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/MAINTAINERS b/MAINTAINERS index 70a3370ac6..d128ed035a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -852,8 +852,9 @@ S: Orphan 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 @@ -168,7 +168,9 @@ recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES) bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS) $(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) diff --git a/aio-posix.c b/aio-posix.c index 2440eb9c27..bd06f33c78 100644 --- a/aio-posix.c +++ b/aio-posix.c @@ -165,6 +165,10 @@ static bool aio_dispatch(AioContext *ctx) g_free(tmp); } } + + /* Run our timers */ + progress |= timerlistgroup_run_timers(&ctx->tlg); + return progress; } @@ -219,9 +223,9 @@ bool aio_poll(AioContext *ctx, bool blocking) } /* 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) { @@ -232,9 +236,11 @@ bool aio_poll(AioContext *ctx, bool blocking) node->pfd.revents = pfd->revents; } } - if (aio_dispatch(ctx)) { - progress = 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 78b2801c51..f9cfbb75ac 100644 --- a/aio-win32.c +++ b/aio-win32.c @@ -95,6 +95,7 @@ bool aio_poll(AioContext *ctx, bool blocking) HANDLE events[MAXIMUM_WAIT_OBJECTS + 1]; bool progress; int count; + int timeout; progress = false; @@ -108,6 +109,9 @@ bool aio_poll(AioContext *ctx, bool blocking) progress = true; } + /* Run timers */ + progress |= timerlistgroup_run_timers(&ctx->tlg); + /* * Then dispatch any pending callbacks from the GSource. * @@ -125,7 +129,7 @@ bool aio_poll(AioContext *ctx, bool blocking) node->io_notify(node->e); /* aio_notify() does not count as progress */ - if (node->opaque != &ctx->notifier) { + if (node->e != &ctx->notifier) { progress = true; } } @@ -164,8 +168,11 @@ bool aio_poll(AioContext *ctx, bool blocking) /* 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) { @@ -188,7 +195,7 @@ bool aio_poll(AioContext *ctx, bool blocking) node->io_notify(node->e); /* aio_notify() does not count as progress */ - if (node->opaque != &ctx->notifier) { + if (node->e != &ctx->notifier) { progress = true; } } @@ -208,5 +215,14 @@ bool aio_poll(AioContext *ctx, bool blocking) events[ret - WAIT_OBJECT_0] = events[--count]; } + 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 ac8eb593c9..0471cd5a6b 100644 --- a/arch_init.c +++ b/arch_init.c @@ -393,7 +393,7 @@ static void migration_bitmap_sync(void) } 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(); @@ -411,7 +411,7 @@ static void migration_bitmap_sync(void) 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) { @@ -673,7 +673,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) 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; @@ -692,7 +692,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque) 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); @@ -1126,8 +1126,8 @@ void do_acpitable_option(const QemuOpts *opts) 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); } @@ -1218,11 +1218,11 @@ static void check_guest_throttling(void) } 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. @@ -150,7 +150,10 @@ aio_ctx_prepare(GSource *source, gint *timeout) { 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 @@ aio_ctx_prepare(GSource *source, gint *timeout) } } + 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 @@ aio_ctx_check(GSource *source) return true; } } - return aio_pending(ctx); + return aio_pending(ctx) || (timerlistgroup_deadline_ns(&ctx->tlg) == 0); } static gboolean @@ -205,6 +216,7 @@ aio_ctx_finalize(GSource *source) 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 @@ void aio_notify(AioContext *ctx) event_notifier_set(&ctx->notifier); } +static void aio_timerlist_notify(void *opaque) +{ + aio_notify(opaque); +} + AioContext *aio_context_new(void) { AioContext *ctx; @@ -244,6 +261,7 @@ AioContext *aio_context_new(void) aio_set_event_notifier(ctx, &ctx->notifier, (EventNotifierHandler *) 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 02bb8861f8..af4cdf60e7 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1124,10 +1124,10 @@ static int audio_is_timer_needed (void) 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 @@ static void audio_init (void) 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 9f23aa2cb3..cb386620ae 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -46,7 +46,7 @@ static int no_run_out (HWVoiceOut *hw, int live) 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 @@ static int no_run_in (HWVoiceIn *hw) 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 bc24557de4..5af436c31d 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -81,7 +81,7 @@ static void spice_audio_fini (void *opaque) 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 @@ static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate) 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 950fa8f19c..6846a1a9f7 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -52,7 +52,7 @@ static int wav_run_out (HWVoiceOut *hw, int live) 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 62aa784436..1132899026 100644 --- a/backends/baum.c +++ b/backends/baum.c @@ -314,9 +314,9 @@ static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len) 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 @@ static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len) 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 @@ static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len) c = '?'; text[i] = c; } - qemu_del_timer(baum->cellCount_timer); + timer_del(baum->cellCount_timer); memset(zero, 0, sizeof(zero)); @@ -553,7 +553,7 @@ static void baum_close(struct CharDriverState *chr) { 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 @@ CharDriverState *chr_baum_init(void) 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 @@ CharDriverState *chr_baum_init(void) return chr; fail: - qemu_free_timer(baum->cellCount_timer); + timer_free(baum->cellCount_timer); brlapi__closeConnection(handle); fail_handle: g_free(handle); @@ -130,8 +130,8 @@ void bdrv_io_limits_disable(BlockDriverState *bs) 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; } @@ -148,7 +148,7 @@ static void bdrv_block_timer(void *opaque) void bdrv_io_limits_enable(BlockDriverState *bs) { - 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; } @@ -180,8 +180,8 @@ static void bdrv_io_limits_intercept(BlockDriverState *bs, */ 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); } @@ -706,6 +706,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockDriverState *file, 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); @@ -1402,6 +1403,7 @@ void bdrv_close(BlockDriverState *bs) bs->valid_key = 0; bs->sg = 0; bs->growable = 0; + bs->zero_beyond_eof = false; QDECREF(bs->options); bs->options = NULL; @@ -2569,7 +2571,35 @@ static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs, } } - 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); @@ -3717,7 +3747,7 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors, 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; @@ -3737,7 +3767,7 @@ static bool bdrv_exceed_io_limits(BlockDriverState *bs, int nb_sectors, *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 6ae8a05a3e..e12b3b1461 100644 --- a/block/backup.c +++ b/block/backup.c @@ -272,9 +272,9 @@ static void coroutine_fn backup_run(void *opaque) 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); + block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, delay_ns); } else { - block_job_sleep_ns(&job->common, rt_clock, 0); + block_job_sleep_ns(&job->common, QEMU_CLOCK_REALTIME, 0); } if (block_job_is_cancelled(&job->common)) { diff --git a/block/commit.c b/block/commit.c index 2227fc2e6c..51a1ab3678 100644 --- a/block/commit.c +++ b/block/commit.c @@ -103,7 +103,7 @@ wait: /* 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/iscsi.c b/block/iscsi.c index 47a3adc9b5..2bbee1f6e5 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -960,7 +960,7 @@ static void iscsi_nop_timed_event(void *opaque) 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 @@ -1173,8 +1173,8 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags) #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: @@ -1204,8 +1204,8 @@ static void iscsi_close(BlockDriverState *bs) 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); iscsi_destroy_context(iscsi); @@ -1267,8 +1267,8 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options) 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/mirror.c b/block/mirror.c index bed4a7eadd..86de4582b4 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -356,7 +356,7 @@ static void coroutine_fn mirror_run(void *opaque) } 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 @@ static void coroutine_fn mirror_run(void *opaque) * 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 @@ static void coroutine_fn mirror_run(void *opaque) 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 @@ static void coroutine_fn mirror_run(void *opaque) 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/qcow2.c b/block/qcow2.c index 3376901bd7..78097e5173 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1402,7 +1402,7 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options) 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 @@ static int qcow2_load_vmstate(BlockDriverState *bs, uint8_t *buf, { 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/qed.c b/block/qed.c index f767b0528c..cc904c4834 100644 --- a/block/qed.c +++ b/block/qed.c @@ -353,10 +353,10 @@ static void qed_start_need_check_timer(BDRVQEDState *s) { 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_start_need_check_timer(BDRVQEDState *s) 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 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags) } } - 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 @@ static void bdrv_qed_close(BlockDriverState *bs) 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/stream.c b/block/stream.c index db49b4d85f..99821252b1 100644 --- a/block/stream.c +++ b/block/stream.c @@ -114,7 +114,7 @@ wait: /* 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/vmdk.c b/block/vmdk.c index 346bb5cad9..63b489d29e 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -401,6 +401,14 @@ static int vmdk_add_extent(BlockDriverState *bs, 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)); @@ -473,9 +481,9 @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent) 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; @@ -486,14 +494,14 @@ static int vmdk_open_vmdk3(BlockDriverState *bs, if (ret < 0) { return ret; } - - ret = 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), - &extent); + 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; } @@ -598,14 +606,6 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, } l1_size = (le64_to_cpu(header.capacity) + l1_entry_sectors - 1) / l1_entry_sectors; - 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; - } if (le32_to_cpu(header.flags) & VMDK4_FLAG_RGD) { l1_backup_offset = le64_to_cpu(header.rgd_offset) << 9; } @@ -674,7 +674,7 @@ static int vmdk_open_sparse(BlockDriverState *bs, 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); @@ -718,7 +718,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, } 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; } @@ -731,7 +732,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, } /* save to extents array */ - if (!strcmp(type, "FLAT")) { + if (!strcmp(type, "FLAT") || !strcmp(type, "VMFS")) { /* FLAT extent */ VmdkExtent *extent; @@ -741,8 +742,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, 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); @@ -789,6 +790,8 @@ static int vmdk_open_desc_file(BlockDriverState *bs, int flags, goto exit; } if (strcmp(ct, "monolithicFlat") && + strcmp(ct, "vmfs") && + strcmp(ct, "vmfsSparse") && strcmp(ct, "twoGbMaxExtentSparse") && strcmp(ct, "twoGbMaxExtentFlat")) { fprintf(stderr, @@ -1381,7 +1384,6 @@ static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs, return ret; } - static int vmdk_create_extent(const char *filename, int64_t filesize, bool flat, bool compress, bool zeroed_grain) { diff --git a/block/win32-aio.c b/block/win32-aio.c index fcb7c754da..5d1d199b61 100644 --- a/block/win32-aio.c +++ b/block/win32-aio.c @@ -105,13 +105,6 @@ static void win32_aio_completion_cb(EventNotifier *e) } } -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 @@ QEMUWin32AIOState *win32_aio_init(void) 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 bc7016a8d4..121520ecbc 100644 --- a/blockdev.c +++ b/blockdev.c @@ -487,7 +487,11 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts, 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; } } @@ -1295,7 +1299,7 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd, 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)); } } } diff --git a/blockjob.c b/blockjob.c index ca80df1d0e..7edc945119 100644 --- a/blockjob.c +++ b/blockjob.c @@ -187,7 +187,7 @@ int block_job_cancel_sync(BlockJob *job) 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 @@ void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns) if (block_job_is_paused(job)) { qemu_coroutine_yield(); } else { - co_sleep_ns(clock, ns); + co_sleep_ns(type, ns); } job->busy = true; } @@ -362,7 +362,11 @@ if test ! -z "$cpu" ; then elif check_define __i386__ ; then cpu="i386" elif check_define __x86_64__ ; then - cpu="x86_64" + if check_define __ILP32__ ; then + cpu="x32" + else + cpu="x86_64" + fi elif check_define __sparc__ ; then if check_define __arch64__ ; then cpu="sparc64" @@ -399,7 +403,7 @@ ARCH= # Normalise host CPU name and set ARCH. # Note that this case should only have supported host CPUs, not guests. case "$cpu" in - ia64|ppc|ppc64|s390|s390x|sparc64) + ia64|ppc|ppc64|s390|s390x|sparc64|x32) cpu="$cpu" ;; i386|i486|i586|i686|i86pc|BePC) @@ -550,7 +554,7 @@ Haiku) kvm="yes" vhost_net="yes" vhost_scsi="yes" - if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then + if [ "$cpu" = "i386" -o "$cpu" = "x86_64" -o "$cpu" = "x32" ] ; then audio_possible_drivers="$audio_possible_drivers fmod" fi QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES" @@ -977,6 +981,11 @@ case "$cpu" in LDFLAGS="-m64 $LDFLAGS" cc_i386='$(CC) -m32' ;; + x32) + CPU_CFLAGS="-mx32" + LDFLAGS="-mx32 $LDFLAGS" + cc_i386='$(CC) -m32' + ;; # No special flags required for other host CPUs esac @@ -1251,7 +1260,7 @@ fi if test "$pie" = ""; then case "$cpu-$targetos" in - i386-Linux|x86_64-Linux|i386-OpenBSD|x86_64-OpenBSD) + i386-Linux|x86_64-Linux|x32-Linux|i386-OpenBSD|x86_64-OpenBSD) ;; *) pie="no" @@ -2818,6 +2827,37 @@ if compile_prog "" "" ; then 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 @@ -3475,7 +3515,7 @@ fi if test "$pie" = "no" ; then textseg_addr= case "$cpu" in - arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64) + arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64 | x32) textseg_addr=0x60000000 ;; mips) @@ -3650,7 +3690,7 @@ echo "libs_softmmu=$libs_softmmu" >> $config_host_mak echo "ARCH=$ARCH" >> $config_host_mak case "$cpu" in - arm|i386|x86_64|ppc|aarch64) + arm|i386|x86_64|x32|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 @@ -3814,6 +3854,12 @@ fi 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 @@ -4079,7 +4125,7 @@ elif test "$ARCH" = "sparc64" ; then QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/sparc $QEMU_INCLUDES" elif test "$ARCH" = "s390x" ; then QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/s390 $QEMU_INCLUDES" -elif test "$ARCH" = "x86_64" ; then +elif test "$ARCH" = "x86_64" -o "$ARCH" = "x32" ; then QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/i386 $QEMU_INCLUDES" else QEMU_INCLUDES="-I\$(SRC_PATH)/tcg/\$(ARCH) $QEMU_INCLUDES" @@ -4141,7 +4187,7 @@ fi if test "$linux" = "yes" ; then mkdir -p linux-headers case "$cpu" in - i386|x86_64) + i386|x86_64|x32) linux_arch=x86 ;; ppcemb|ppc|ppc64) @@ -4407,7 +4453,7 @@ for i in $ARCH $TARGET_BASE_ARCH ; do echo "CONFIG_HPPA_DIS=y" >> $config_target_mak echo "CONFIG_HPPA_DIS=y" >> config-all-disas.mak ;; - i386|x86_64) + i386|x86_64|x32) echo "CONFIG_I386_DIS=y" >> $config_target_mak echo "CONFIG_I386_DIS=y" >> config-all-disas.mak ;; diff --git a/cpu-exec.c b/cpu-exec.c index 301be28bf7..5a4399509e 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -53,7 +53,7 @@ void cpu_resume_from_signal(CPUArchState *env, void *puc) static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr) { CPUArchState *env = cpu->env_ptr; - tcg_target_ulong next_tb = tcg_qemu_tb_exec(env, tb_ptr); + uintptr_t next_tb = tcg_qemu_tb_exec(env, tb_ptr); if ((next_tb & TB_EXIT_MASK) > TB_EXIT_IDX1) { /* We didn't start executing this TB (eg because the instruction * counter hit zero); we must restore the guest PC to the address @@ -209,7 +209,7 @@ int cpu_exec(CPUArchState *env) int ret, interrupt_request; TranslationBlock *tb; uint8_t *tc_ptr; - tcg_target_ulong next_tb; + uintptr_t next_tb; if (cpu->halted) { if (!cpu_has_work(cpu)) { @@ -207,7 +207,7 @@ static void icount_adjust(void) 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 @@ -228,15 +228,16 @@ static void icount_adjust(void) 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(); } @@ -252,22 +253,22 @@ static void icount_warp_rt(void *opaque) } 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; @@ -275,19 +276,19 @@ static void icount_warp_rt(void *opaque) 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; @@ -296,20 +297,20 @@ void qemu_clock_warp(QEMUClock *clock) * 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; } @@ -318,28 +319,40 @@ void qemu_clock_warp(QEMUClock *clock) 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); } } @@ -363,7 +376,8 @@ void configure_icount(const char *option) 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; @@ -381,12 +395,15 @@ void configure_icount(const char *option) 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); } /***********************************************************/ @@ -735,7 +752,7 @@ static void qemu_tcg_wait_io_event(void) 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 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) 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 @@ void pause_all_vcpus(void) { 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 @@ void resume_all_vcpus(void) { 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 @@ static int tcg_cpu_exec(CPUArchState *env) #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 @@ static void tcg_exec_all(void) { 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 @@ static void tcg_exec_all(void) 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)) { @@ -1367,6 +1401,20 @@ void qmp_inject_nmi(Error **errp) apic_deliver_nmi(env->apic_state); } } +#elif defined(TARGET_S390X) + CPUState *cs; + S390CPU *cpu; + + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + cpu = S390_CPU(cs); + if (cpu->env.cpu_num == monitor_get_cpu_index()) { + if (s390_cpu_restart(S390_CPU(cs)) == -1) { + error_set(errp, QERR_UNSUPPORTED); + return; + } + break; + } + } #else error_set(errp, QERR_UNSUPPORTED); #endif @@ -158,6 +158,35 @@ print_insn_thumb1(bfd_vma pc, disassemble_info *info) } #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 @@ void target_disas(FILE *out, CPUArchState *env, target_ulong code, 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 @@ void target_disas(FILE *out, CPUArchState *env, target_ulong code, #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 @@ void disas(FILE *out, void *code, unsigned long size) 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 @@ void disas(FILE *out, void *code, unsigned long size) 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/disas/ppc.c b/disas/ppc.c index c149506fd8..99c4cbc3ab 100644 --- a/disas/ppc.c +++ b/disas/ppc.c @@ -5157,7 +5157,8 @@ int print_insn_ppc (bfd_vma memaddr, struct disassemble_info *info) { int dialect = (char *) info->private_data - (char *) 0; - return print_insn_powerpc (memaddr, info, 1, dialect); + return print_insn_powerpc (memaddr, info, info->endian == BFD_ENDIAN_BIG, + dialect); } /* Print a big endian PowerPC instruction. */ diff --git a/dma-helpers.c b/dma-helpers.c index 499550fc23..c9620a5bbd 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/hmp-commands.hx b/hmp-commands.hx index 8c6b91a9c7..65b7f6076c 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -11,7 +11,7 @@ ETEXI { .name = "help|?", - .args_type = "name:s?", + .args_type = "name:S?", .params = "[cmd]", .help = "show the help", .mhandler.cmd = do_help_cmd, @@ -822,7 +822,7 @@ The values that can be specified here depend on the machine type, but are the same that can be specified in the @code{-boot} command line option. ETEXI -#if defined(TARGET_I386) +#if defined(TARGET_I386) || defined(TARGET_S390X) { .name = "nmi", .args_type = "", @@ -834,7 +834,7 @@ ETEXI STEXI @item nmi @var{cpu} @findex nmi -Inject an NMI on the given CPU (x86 only). +Inject an NMI (x86) or RESTART (s390x) on the given CPU. ETEXI @@ -1195,13 +1195,13 @@ static void hmp_migrate_status_cb(void *opaque) 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 @@ void hmp_migrate(Monitor *mon, const QDict *qdict) 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/acpi/core.c b/hw/acpi/core.c index b07fedac59..7467b88e27 100644 --- a/hw/acpi/core.c +++ b/hw/acpi/core.c @@ -433,9 +433,9 @@ void acpi_pm_tmr_update(ACPIREGS *ar, bool enable) 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 @@ void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, 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_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, 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 c88569061c..613d98736a 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -263,7 +263,7 @@ static int acpi_load_old(QEMUFile *f, void *opaque, int version_id) 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 245004530c..aac9a32e0c 100644 --- a/hw/alpha/typhoon.c +++ b/hw/alpha/typhoon.c @@ -833,7 +833,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, 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)); } diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c index b6a0b27b02..47511d2cae 100644 --- a/hw/arm/omap1.c +++ b/hw/arm/omap1.c @@ -99,7 +99,7 @@ struct omap_mpu_timer_s { 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 uint32_t omap_timer_read(struct omap_mpu_timer_s *timer) 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 @@ static inline void omap_timer_update(struct omap_mpu_timer_s *timer) * 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 const MemoryRegionOps omap_mpu_timer_ops = { 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 @@ static struct omap_mpu_timer_s *omap_mpu_timer_init(MemoryRegion *system_memory, 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 const MemoryRegionOps omap_wd_timer_ops = { 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 @@ static struct omap_watchdog_timer_s *omap_wd_timer_init(MemoryRegion *memory, 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 const MemoryRegionOps omap_os_timer_ops = { 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 @@ static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory, 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 @@ static void omap_ulpd_pm_write(void *opaque, hwaddr addr, 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 @@ static void omap_rtc_tick(void *opaque) 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 @@ static void omap_rtc_reset(struct omap_rtc_s *s) 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 @@ static struct omap_rtc_s *omap_rtc_init(MemoryRegion *system_memory, 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 @@ static void omap_mcbsp_source_tick(void *opaque) 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_start(struct omap_mcbsp_s *s) 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 @@ static void omap_mcbsp_sink_tick(void *opaque) 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 @@ static void omap_mcbsp_tx_stop(struct omap_mcbsp_s *s) { 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 @@ static void omap_mcbsp_reset(struct omap_mcbsp_s *s) 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 @@ static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory, 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 @@ static void omap_lpg_tick(void *opaque) 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 @@ static void omap_lpg_update(struct omap_lpg_s *s) 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 @@ static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory, 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); diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 17ddd3fab8..02b7016a04 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -335,7 +335,7 @@ static int pxa2xx_cpccnt_read(CPUARMState *env, const ARMCPRegInfo *ri, { 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; } @@ -842,7 +842,7 @@ static inline void pxa2xx_rtc_int_update(PXA2xxRTCState *s) 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) / @@ -852,7 +852,7 @@ static void pxa2xx_rtc_hzupdate(PXA2xxRTCState *s) 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; @@ -860,7 +860,7 @@ static void pxa2xx_rtc_swupdate(PXA2xxRTCState *s) 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; @@ -870,43 +870,43 @@ static inline void pxa2xx_rtc_alarm_update(PXA2xxRTCState *s, 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) @@ -986,16 +986,19 @@ static uint64_t pxa2xx_rtc_read(void *opaque, hwaddr addr, 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: @@ -1135,14 +1138,14 @@ static int pxa2xx_rtc_init(SysBusDevice *dev) 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->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->last_hz = s->last_sw = s->last_pi = qemu_clock_get_ms(rtc_clock); + + 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); diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index a532cf6038..ba172835eb 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -393,7 +393,7 @@ static void spitz_keyboard_tick(void *opaque) 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); } @@ -485,7 +485,7 @@ static void spitz_keyboard_register(PXA2xxState *cpu) 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); } @@ -505,7 +505,7 @@ static int spitz_keyboard_init(SysBusDevice *sbd) spitz_keyboard_pre_map(s); - s->kbdtimer = qemu_new_timer_ns(vm_clock, spitz_keyboard_tick, s); + 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); diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 49be8fd8b4..3170d69d42 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -78,14 +78,14 @@ static void gptm_update_irq(gptm_state *s) 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]; @@ -103,7 +103,7 @@ static void gptm_reload(gptm_state *s, int n, int reset) 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) @@ -318,8 +318,8 @@ static int stellaris_gptm_init(SysBusDevice *sbd) 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]); + 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; } diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index 7b8ef8cbeb..170d0ce267 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -269,7 +269,7 @@ static inline void strongarm_rtc_int_update(StrongARMRTCState *s) 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; @@ -278,17 +278,17 @@ static void strongarm_rtc_hzupdate(StrongARMRTCState *s) 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); } } @@ -322,7 +322,7 @@ static uint64_t strongarm_rtc_read(void *opaque, hwaddr addr, 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); @@ -388,10 +388,10 @@ static int strongarm_rtc_init(SysBusDevice *dev) 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); @@ -1085,8 +1085,8 @@ static void strongarm_uart_receive(void *opaque, const uint8_t *buf, int size) } /* 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); @@ -1107,7 +1107,7 @@ static void strongarm_uart_event(void *opaque, int event) 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); @@ -1118,7 +1118,7 @@ static void strongarm_uart_tx(void *opaque) 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); @@ -1237,8 +1237,8 @@ static int strongarm_uart_init(SysBusDevice *dev) 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, @@ -1282,8 +1282,8 @@ static int strongarm_uart_post_load(void *opaque, int version_id) /* 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; diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 0421d473ff..0c792475d1 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -173,7 +173,7 @@ static void timer_handler (int c, double interval_Sec) 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 diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index 32e44adb53..a6666c6cdf 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -40,11 +40,11 @@ static const TypeInfo hda_codec_bus_info = { .instance_size = sizeof(HDACodecBus), }; -void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, +void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, size_t bus_size, hda_codec_response_func response, hda_codec_xfer_func xfer) { - qbus_create_inplace(&bus->qbus, TYPE_HDA_BUS, dev, NULL); + qbus_create_inplace(bus, bus_size, TYPE_HDA_BUS, dev, NULL); bus->response = response; bus->xfer = xfer; } @@ -526,7 +526,7 @@ static void intel_hda_get_wall_clk(IntelHDAState *d, const IntelHDAReg *reg) { 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 @@ static void intel_hda_reset(DeviceState *dev) 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) { @@ -1142,7 +1142,7 @@ static int intel_hda_init(PCIDevice *pci) msi_init(&d->pci, 0x50, 1, true, false); } - hda_codec_bus_init(DEVICE(pci), &d->codecs, + hda_codec_bus_init(DEVICE(pci), &d->codecs, sizeof(d->codecs), intel_hda_response, intel_hda_xfer); return 0; diff --git a/hw/audio/intel-hda.h b/hw/audio/intel-hda.h index 2544f0a344..d784bcf5fc 100644 --- a/hw/audio/intel-hda.h +++ b/hw/audio/intel-hda.h @@ -48,7 +48,7 @@ struct HDACodecDevice { uint32_t cad; /* codec address */ }; -void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, +void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, size_t bus_size, hda_codec_response_func response, hda_codec_xfer_func xfer); HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad); diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c index 3e586888eb..db79131cf1 100644 --- a/hw/audio/sb16.c +++ b/hw/audio/sb16.c @@ -768,9 +768,9 @@ static void complete (SB16State *s) } 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 @@ static void sb16_realizefn (DeviceState *dev, Error **errp) 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"); } diff --git a/hw/block/fdc.c b/hw/block/fdc.c index e35ed2eabb..c5a6c21215 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -1647,8 +1647,8 @@ static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction) 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) @@ -2108,7 +2108,7 @@ static void fdctrl_realize_common(FDCtrl *fdctrl, Error **errp) 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 */ diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 0263e5c636..5dee229734 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -187,7 +187,7 @@ static void nvme_enqueue_req_completion(NvmeCQueue *cq, NvmeRequest *req) 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 uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req) 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 @@ static void nvme_init_sq(NvmeSQueue *sq, NvmeCtrl *n, uint64_t dma_addr, 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 uint16_t nvme_create_sq(NvmeCtrl *n, NvmeCmd *cmd) 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 @@ static void nvme_init_cq(NvmeCQueue *cq, NvmeCtrl *n, uint64_t dma_addr, 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 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) 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 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) } 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); } } diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 825011d8cb..018a9677ba 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -613,7 +613,7 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) 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/pflash_cfi02.c b/hw/block/pflash_cfi02.c index 9fc02e3d64..99445b09b9 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -430,8 +430,8 @@ static void pflash_write (pflash_t *pfl, hwaddr offset, } 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 @@ static void pflash_write (pflash_t *pfl, hwaddr offset, } 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 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) 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/bt/hci-csr.c b/hw/bt/hci-csr.c index 16a25cb349..7b9b91608a 100644 --- a/hw/bt/hci-csr.c +++ b/hw/bt/hci-csr.c @@ -87,7 +87,7 @@ static inline void csrhci_fifo_wake(struct csrhci_s *s) } 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 @@ CharDriverState *uart_hci_init(qemu_irq wakeup) 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 b53cd5dea2..d1c0604a9b 100644 --- a/hw/bt/hci.c +++ b/hw/bt/hci.c @@ -576,7 +576,7 @@ static void bt_hci_inquiry_result(struct bt_hci_s *hci, 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 @@ static void bt_hci_lmp_link_establish(struct bt_hci_s *hci, 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 @@ static void bt_hci_lmp_link_teardown(struct bt_hci_s *hci, uint16_t handle) 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 @@ static int bt_hci_mode_change(struct bt_hci_s *hci, uint16_t handle, 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 @@ static int bt_hci_mode_cancel(struct bt_hci_s *hci, uint16_t handle, int mode) 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 @@ static void bt_hci_reset(struct bt_hci_s *hci) 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 @@ static void bt_submit_hci(struct HCIInfo *info, } 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 @@ static void bt_submit_hci(struct HCIInfo *info, 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 HCIInfo *bt_new_hci(struct bt_scatternet_s *net) { 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 @@ static void bt_hci_done(struct HCIInfo *info) * 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 521587a112..2301d6f87f 100644 --- a/hw/bt/l2cap.c +++ b/hw/bt/l2cap.c @@ -166,9 +166,9 @@ static void l2cap_retransmission_timer_update(struct l2cap_chan_s *ch) { #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 @@ static void l2cap_monitor_timer_update(struct l2cap_chan_s *ch) { #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 3c2e96097b..f8ccbdd13a 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -141,9 +141,9 @@ static void fifo_trigger_update(void *opaque) 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; @@ -265,7 +265,7 @@ static void uart_ctrl_update(UartState *s) 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)) { @@ -291,7 +291,7 @@ static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size) 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); @@ -452,10 +452,10 @@ static int cadence_uart_init(SysBusDevice *dev) 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; diff --git a/hw/char/ipack.c b/hw/char/ipack.c index f890471db5..b7e45bedb2 100644 --- a/hw/char/ipack.c +++ b/hw/char/ipack.c @@ -24,11 +24,12 @@ IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot) return NULL; } -void ipack_bus_new_inplace(IPackBus *bus, DeviceState *parent, +void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size, + DeviceState *parent, const char *name, uint8_t n_slots, qemu_irq_handler handler) { - qbus_create_inplace(&bus->qbus, TYPE_IPACK_BUS, parent, name); + qbus_create_inplace(bus, bus_size, TYPE_IPACK_BUS, parent, name); bus->n_slots = n_slots; bus->set_irq = handler; } diff --git a/hw/char/ipack.h b/hw/char/ipack.h index f2b7a12e05..f8dc0f242a 100644 --- a/hw/char/ipack.h +++ b/hw/char/ipack.h @@ -72,7 +72,8 @@ extern const VMStateDescription vmstate_ipack_device; VMSTATE_STRUCT(_field, _state, 1, vmstate_ipack_device, IPackDevice) IPackDevice *ipack_device_find(IPackBus *bus, int32_t slot); -void ipack_bus_new_inplace(IPackBus *bus, DeviceState *parent, +void ipack_bus_new_inplace(IPackBus *bus, size_t bus_size, + DeviceState *parent, const char *name, uint8_t n_slots, qemu_irq_handler handler); diff --git a/hw/char/serial.c b/hw/char/serial.c index 602559254e..27dab7d9d6 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 @@ static void serial_update_msl(SerialState *s) 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 @@ static void serial_update_msl(SerialState *s) 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 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque) 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 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, 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 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, /* 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 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val, 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 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size) 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 @@ static void serial_receive1(void *opaque, const uint8_t *buf, int size) } 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 @@ static void serial_reset(void *opaque) 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 @@ void serial_realize_core(SerialState *s, Error **errp) 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 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase, 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 @@ SerialState *serial_mm_init(MemoryRegion *address_space, 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 a7997213b6..9c2aef82e6 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -47,6 +47,8 @@ static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max) buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE]; } + qemu_chr_accept_input(dev->chardev); + return n; } diff --git a/hw/char/tpci200.c b/hw/char/tpci200.c index d9e17b2956..e04ff26019 100644 --- a/hw/char/tpci200.c +++ b/hw/char/tpci200.c @@ -607,7 +607,7 @@ static int tpci200_initfn(PCIDevice *pci_dev) pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las2); pci_register_bar(&s->dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las3); - ipack_bus_new_inplace(&s->bus, DEVICE(&s->dev), NULL, + ipack_bus_new_inplace(&s->bus, sizeof(s->bus), DEVICE(pci_dev), NULL, N_MODULES, tpci200_set_irq); return 0; diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index da417c7010..703f026370 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -603,7 +603,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque) } } 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 @@ static int fetch_active_ports_list(QEMUFile *f, int version_id, 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 @@ static int fetch_active_ports_list(QEMUFile *f, int version_id, } } } - qemu_mod_timer(s->post_load->timer, 1); + timer_mod(s->post_load->timer, 1); return 0; } @@ -911,8 +911,8 @@ static int virtio_serial_device_init(VirtIODevice *vdev) sizeof(struct virtio_console_config)); /* Spawn a new virtio-serial bus on which the ports will ride as devices */ - qbus_create_inplace(&vser->bus.qbus, TYPE_VIRTIO_SERIAL_BUS, qdev, - vdev->bus_name); + qbus_create_inplace(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS, + qdev, vdev->bus_name); vser->bus.qbus.allow_hotplug = 1; vser->bus.vser = vser; QTAILQ_INIT(&vser->ports); @@ -999,8 +999,8 @@ static int virtio_serial_device_exit(DeviceState *dev) 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); diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c index 4bc96c9fa2..3036bde1f3 100644 --- a/hw/core/ptimer.c +++ b/hw/core/ptimer.c @@ -48,7 +48,7 @@ static void ptimer_reload(ptimer_state *s) 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 ptimer_get_count(ptimer_state *s) 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 @@ void ptimer_set_count(ptimer_state *s, uint64_t count) { 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 @@ void ptimer_run(ptimer_state *s, int oneshot) 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 @@ void ptimer_stop(ptimer_state *s) return; s->delta = ptimer_get_count(s); - qemu_del_timer(s->timer); + timer_del(s->timer); s->enabled = 0; } @@ -160,7 +160,7 @@ void ptimer_set_period(ptimer_state *s, int64_t period) 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 @@ void ptimer_set_freq(ptimer_state *s, uint32_t freq) 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 @@ void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload) 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 @@ ptimer_state *ptimer_init(QEMUBH *bh) 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.c b/hw/core/qdev.c index 758de9fccc..533f6dd122 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -470,10 +470,10 @@ static void bus_unparent(Object *obj) } } -void qbus_create_inplace(void *bus, const char *typename, +void qbus_create_inplace(void *bus, size_t size, const char *typename, DeviceState *parent, const char *name) { - object_initialize(bus, typename); + object_initialize(bus, size, typename); qbus_realize(bus, parent, name); } diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index 9004d8c543..b84cd4a16f 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -276,8 +276,8 @@ static void main_system_bus_create(void) /* assign main_system_bus before qbus_create_inplace() * in order to make "if (bus != sysbus_get_default())" work */ main_system_bus = g_malloc0(system_bus_info.instance_size); - qbus_create_inplace(main_system_bus, TYPE_SYSTEM_BUS, NULL, - "main-system-bus"); + qbus_create_inplace(main_system_bus, system_bus_info.instance_size, + TYPE_SYSTEM_BUS, NULL, "main-system-bus"); OBJECT(main_system_bus)->free = g_free; object_property_add_child(container_get(qdev_get_machine(), "/unattached"), diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c index 8748cc5046..9a4ea7e2df 100644 --- a/hw/cpu/icc_bus.c +++ b/hw/cpu/icc_bus.c @@ -90,7 +90,8 @@ static void icc_bridge_init(Object *obj) ICCBridgeState *s = ICC_BRIGDE(obj); SysBusDevice *sb = SYS_BUS_DEVICE(obj); - qbus_create_inplace(&s->icc_bus, TYPE_ICC_BUS, DEVICE(s), "icc"); + qbus_create_inplace(&s->icc_bus, sizeof(s->icc_bus), TYPE_ICC_BUS, + DEVICE(s), "icc"); /* Do not change order of registering regions, * APIC must be first registered region, board maps it by 0 index diff --git a/hw/display/qxl-logger.c b/hw/display/qxl-logger.c index 3cd85d9b97..c900c2ca4f 100644 --- a/hw/display/qxl-logger.c +++ b/hw/display/qxl-logger.c @@ -242,7 +242,7 @@ int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext) 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 c5370575ea..7649f2b1f4 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1596,7 +1596,7 @@ async_common: 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: diff --git a/hw/display/vga.c b/hw/display/vga.c index 06f44a808c..7b91d9c54e 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -318,7 +318,7 @@ static uint8_t vga_precise_retrace(VGACommonState *s) 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 @@ static void vga_draw_text(VGACommonState *s, int full_update) 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 @@ static void vga_update_display(void *opaque) } 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/dma/pl330.c b/hw/dma/pl330.c index ddcc4135d7..401399d330 100644 --- a/hw/dma/pl330.c +++ b/hw/dma/pl330.c @@ -1256,7 +1256,7 @@ static void pl330_dma_stop_irq(void *opaque, int irq, int level) 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 @@ static void pl330_reset(DeviceState *d) 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 @@ static void pl330_realize(DeviceState *dev, Error **errp) "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/rc4030.c b/hw/dma/rc4030.c index 4ec433f957..af2663256e 100644 --- a/hw/dma/rc4030.c +++ b/hw/dma/rc4030.c @@ -107,7 +107,7 @@ static void set_next_tick(rc4030State *s) 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 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus, *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 5e3491d373..c06aabb406 100644 --- a/hw/dma/soc_dma.c +++ b/hw/dma/soc_dma.c @@ -84,10 +84,10 @@ struct dma_s { 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 @@ void soc_dma_set_request(struct soc_dma_ch_s *ch, int level) 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 @@ struct soc_dma_s *soc_dma_init(int n) 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/xilinx_axidma.c b/hw/dma/xilinx_axidma.c index a48e3baa99..d67c5f19a4 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" @@ -578,8 +579,10 @@ static void xilinx_axidma_init(Object *obj) (Object **) &s->tx_control_dev, &errp); assert_no_error(errp); - object_initialize(&s->rx_data_dev, TYPE_XILINX_AXI_DMA_DATA_STREAM); - object_initialize(&s->rx_control_dev, TYPE_XILINX_AXI_DMA_CONTROL_STREAM); + object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev), + TYPE_XILINX_AXI_DMA_DATA_STREAM); + object_initialize(&s->rx_control_dev, sizeof(s->rx_control_dev), + TYPE_XILINX_AXI_DMA_CONTROL_STREAM); object_property_add_child(OBJECT(s), "axistream-connected-target", (Object *)&s->rx_data_dev, &errp); assert_no_error(errp); diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index 179b806d96..5609063120 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -79,7 +79,7 @@ void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic) 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 c1f40948f9..20b6457fbd 100644 --- a/hw/i386/kvm/i8254.c +++ b/hw/i386/kvm/i8254.c @@ -65,12 +65,12 @@ static void kvm_pit_update_clock_offset(KVMPITState *s) /* * 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 @@ static void kvm_pit_set_gate(PITCommonState *s, PITChannelState *sc, int val) 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/pci-assign.c b/hw/i386/kvm/pci-assign.c index 5618173cc6..011764fbf6 100644 --- a/hw/i386/kvm/pci-assign.c +++ b/hw/i386/kvm/pci-assign.c @@ -568,8 +568,7 @@ static int get_real_device_id(const char *devpath, uint16_t *val) return get_real_id(devpath, "device", val); } -static int get_real_device(AssignedDevice *pci_dev, uint16_t r_seg, - uint8_t r_bus, uint8_t r_dev, uint8_t r_func) +static int get_real_device(AssignedDevice *pci_dev) { char dir[128], name[128]; int fd, r = 0, v; @@ -582,7 +581,8 @@ static int get_real_device(AssignedDevice *pci_dev, uint16_t r_seg, dev->region_number = 0; snprintf(dir, sizeof(dir), "/sys/bus/pci/devices/%04x:%02x:%02x.%x/", - r_seg, r_bus, r_dev, r_func); + pci_dev->host.domain, pci_dev->host.bus, + pci_dev->host.slot, pci_dev->host.function); snprintf(name, sizeof(name), "%sconfig", dir); @@ -1769,8 +1769,7 @@ static int assigned_initfn(struct PCIDevice *pci_dev) memcpy(dev->emulate_config_write, dev->emulate_config_read, sizeof(dev->emulate_config_read)); - if (get_real_device(dev, dev->host.domain, dev->host.bus, - dev->host.slot, dev->host.function)) { + if (get_real_device(dev)) { error_report("pci-assign: Error: Couldn't get real device (%s)!", dev->dev.qdev.id); goto out; diff --git a/hw/i386/pc.c b/hw/i386/pc.c index e8bc8ce172..3a620a1856 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -978,7 +978,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) 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); } @@ -1096,8 +1096,8 @@ void pc_acpi_init(const char *default_dsdt) 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); diff --git a/hw/i386/xen_domainbuild.c b/hw/i386/xen_domainbuild.c index 4e2cf95ae5..c0ab7537df 100644 --- a/hw/i386/xen_domainbuild.c +++ b/hw/i386/xen_domainbuild.c @@ -148,7 +148,7 @@ static void xen_domain_poll(void *opaque) 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 @@ int xen_domain_build_pv(const char *kernel, const char *ramdisk, 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 bba150fd74..a71a4ca47c 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1175,7 +1175,7 @@ void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) for (i = 0; i < s->ports; i++) { AHCIDevice *ad = &s->dev[i]; - ide_bus_new(&ad->port, qdev, i, 1); + ide_bus_new(&ad->port, sizeof(ad->port), qdev, i, 1); ide_init2(&ad->port, irqs[i]); ad->hba = s; diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index d6ef7992d4..0500a7a1b6 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -289,7 +289,7 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev) irq = qemu_allocate_irqs(cmd646_set_irq, d, 2); for (i = 0; i < 2; i++) { - ide_bus_new(&d->bus[i], DEVICE(dev), i, 2); + ide_bus_new(&d->bus[i], sizeof(d->bus[i]), DEVICE(dev), i, 2); ide_init2(&d->bus[i], irq[i]); bmdma_init(&d->bus[i], &d->bmdma[i], d); diff --git a/hw/ide/core.c b/hw/ide/core.c index a73af7252a..399b1bae68 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -768,8 +768,8 @@ static void ide_sector_write_cb(void *opaque, int ret) 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 @@ static void ide_init1(IDEBus *bus, int unit) 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/internal.h b/hw/ide/internal.h index 048a052143..5d1cf87742 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -576,7 +576,8 @@ void ide_atapi_cmd(IDEState *s); void ide_atapi_cmd_reply_end(IDEState *s); /* hw/ide/qdev.c */ -void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id, int max_units); +void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev, + int bus_id, int max_units); IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive); #endif /* HW_IDE_INTERNAL_H */ diff --git a/hw/ide/isa.c b/hw/ide/isa.c index bbc8c6b9c9..afc24d4728 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -70,7 +70,7 @@ static void isa_ide_realizefn(DeviceState *dev, Error **errp) ISADevice *isadev = ISA_DEVICE(dev); ISAIDEState *s = ISA_IDE(dev); - ide_bus_new(&s->bus, dev, 0, 2); + ide_bus_new(&s->bus, sizeof(s->bus), dev, 0, 2); ide_init_ioport(&s->bus, isadev, s->iobase, s->iobase2); isa_init_irq(isadev, &s->irq, s->isairq); ide_init2(&s->bus, s->irq); diff --git a/hw/ide/macio.c b/hw/ide/macio.c index ef4ba2b2c5..da94580aac 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -547,7 +547,7 @@ static void macio_ide_initfn(Object *obj) SysBusDevice *d = SYS_BUS_DEVICE(obj); MACIOIDEState *s = MACIO_IDE(obj); - ide_bus_new(&s->bus, DEVICE(obj), 0, 2); + ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2); memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000); sysbus_init_mmio(d, &s->mem); sysbus_init_irq(d, &s->irq); diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index d251ff983c..9f66a52599 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -137,7 +137,7 @@ static void mmio_ide_initfn(Object *obj) SysBusDevice *d = SYS_BUS_DEVICE(obj); MMIOState *s = MMIO_IDE(obj); - ide_bus_new(&s->bus, DEVICE(obj), 0, 2); + ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2); sysbus_init_irq(d, &s->irq); } diff --git a/hw/ide/piix.c b/hw/ide/piix.c index e6e6c0bb7a..ab36749417 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -136,7 +136,7 @@ static void pci_piix_init_ports(PCIIDEState *d) { int i; for (i = 0; i < 2; i++) { - ide_bus_new(&d->bus[i], DEVICE(d), i, 2); + ide_bus_new(&d->bus[i], sizeof(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)); diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 1d84e15378..18c4b7eca9 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -47,9 +47,10 @@ static const TypeInfo ide_bus_info = { .class_init = ide_bus_class_init, }; -void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id, int max_units) +void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev, + int bus_id, int max_units) { - qbus_create_inplace(&idebus->qbus, TYPE_IDE_BUS, dev, NULL); + qbus_create_inplace(idebus, idebus_size, TYPE_IDE_BUS, dev, NULL); idebus->bus_id = bus_id; idebus->max_units = max_units; } diff --git a/hw/ide/via.c b/hw/ide/via.c index e5fb2970e1..99468c773e 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -159,7 +159,7 @@ static void vt82c686b_init_ports(PCIIDEState *d) { int i; for (i = 0; i < 2; i++) { - ide_bus_new(&d->bus[i], DEVICE(d), i, 2); + ide_bus_new(&d->bus[i], sizeof(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)); diff --git a/hw/input/hid.c b/hw/input/hid.c index 14b3125956..bb0fa6a619 100644 --- a/hw/input/hid.c +++ b/hw/input/hid.c @@ -85,8 +85,8 @@ static void hid_idle_timer(void *opaque) 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 @@ static void hid_del_idle_timer(HIDState *hs) 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 bacbeb2343..f583cf0279 100644 --- a/hw/input/lm832x.c +++ b/hw/input/lm832x.c @@ -365,7 +365,7 @@ static void lm_kbd_write(LM823KbdState *s, int reg, int byte, uint8_t value) 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 @@ static int lm8323_init(I2CSlave *i2c) 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/tsc2005.c b/hw/input/tsc2005.c index a771cd5e52..21d4f4dbbd 100644 --- a/hw/input/tsc2005.c +++ b/hw/input/tsc2005.c @@ -201,7 +201,7 @@ static void tsc2005_write(TSC2005State *s, int reg, uint16_t data) 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 @@ static void tsc2005_pin_update(TSC2005State *s) 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 @@ static uint8_t tsc2005_txrx_word(void *opaque, uint8_t value) 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 @@ static void tsc2005_save(QEMUFile *f, void *opaque) 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 @@ static int tsc2005_load(QEMUFile *f, void *opaque, int version_id) 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 @@ static int tsc2005_load(QEMUFile *f, void *opaque, int version_id) 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 @@ void *tsc2005_init(qemu_irq pintdav) 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 9b854e77dd..485c9e5753 100644 --- a/hw/input/tsc210x.c +++ b/hw/input/tsc210x.c @@ -503,9 +503,9 @@ static uint16_t tsc2102_audio_register_read(TSC210xState *s, int reg) 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 @@ static uint16_t tsc2102_audio_register_read(TSC210xState *s, int reg) 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 @@ static void tsc2102_control_register_write( 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 @@ static void tsc2102_control_register_write( 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 @@ static void tsc2102_audio_register_write( 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 @@ static void tsc2102_audio_register_write( 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 @@ static void tsc210x_pin_update(TSC210xState *s) 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_i2s_set_rate(TSC210xState *s, int in, int out) 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 @@ static void tsc210x_save(QEMUFile *f, void *opaque) 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 void tsc210x_save(QEMUFile *f, void *opaque) 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 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id) 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 @@ static int tsc210x_load(QEMUFile *f, void *opaque, int version_id) 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 @@ uWireSlave *tsc2102_init(qemu_irq pint) 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 @@ uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav) 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 5e3b96e4db..a913186ed0 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -606,7 +606,7 @@ static uint32_t apic_get_current_count(APICCommonState *s) { 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 uint32_t apic_get_current_count(APICCommonState *s) 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 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val) 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 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val) 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_pre_save(APICCommonState *s) 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 @@ static void apic_init(APICCommonState *s) 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 b03e904a7a..a0beb10863 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -198,7 +198,7 @@ void apic_init_reset(DeviceState *d) 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/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 178344b5a3..6066fa6838 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -78,9 +78,9 @@ static inline int64_t systick_scale(nvic_state *s) 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 @@ static void systick_reset(nvic_state *s) s->systick.control = 0; s->systick.reload = 0; s->systick.tick = 0; - qemu_del_timer(s->systick.timer); + timer_del(s->systick.timer); } /* The external routines use the hardware vector numbering, ie. the first @@ -158,7 +158,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset) 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 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value) 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 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp) * 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/i8259.c b/hw/intc/i8259.c index 1415bda93f..c6f248b145 100644 --- a/hw/intc/i8259.c +++ b/hw/intc/i8259.c @@ -150,7 +150,7 @@ static void pic_set_irq(void *opaque, int irq, int level) #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 @@ int pic_read_irq(DeviceState *d) #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/xics.c b/hw/intc/xics.c index 6b3c071588..bb018d1829 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -642,6 +642,17 @@ static void xics_realize(DeviceState *dev, Error **errp) ICSState *ics = icp->ics; int i; + /* Registration of global state belongs into realize */ + 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); + + 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); + ics->nr_irqs = icp->nr_irqs; ics->offset = XICS_IRQ_BASE; ics->icp = icp; @@ -650,7 +661,7 @@ static void xics_realize(DeviceState *dev, Error **errp) 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); + object_initialize(&icp->ss[i], sizeof(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])); @@ -678,16 +689,6 @@ static void xics_class_init(ObjectClass *oc, void *data) 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); - - 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 = { diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c index e0266bf15a..c8b4b000cd 100644 --- a/hw/mips/cputimer.c +++ b/hw/mips/cputimer.c @@ -47,11 +47,11 @@ static void cpu_mips_timer_update(CPUMIPSState *env) 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 @@ uint32_t cpu_mips_get_count (CPUMIPSState *env) } 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 @@ void cpu_mips_store_count (CPUMIPSState *env, uint32_t count) 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_start_count(CPUMIPSState *env) 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 @@ static void mips_timer_cb (void *opaque) 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/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c index 4a911d4f8c..0fc26d29a5 100644 --- a/hw/misc/arm_sysctl.c +++ b/hw/misc/arm_sysctl.c @@ -170,7 +170,7 @@ static uint64_t arm_sysctl_read(void *opaque, hwaddr offset, 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 */ diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index c0fd7da118..bc71aa7ccd 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -128,7 +128,7 @@ static unsigned int get_counter(CUDATimer *s) 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 unsigned int get_counter(CUDATimer *s) 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 @@ static void cuda_timer_update(CUDAState *s, CUDATimer *ti, 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 @@ static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val) 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 @@ static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val) 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 @@ static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val) 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 @@ static void cuda_adb_poll(void *opaque) 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 @@ static void cuda_receive_packet(CUDAState *s, 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 @@ static void cuda_receive_packet(CUDAState *s, 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 @@ static void cuda_realizefn(DeviceState *dev, Error **errp) 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) @@ -711,8 +711,8 @@ static void cuda_initfn(Object *obj) s->timers[i].index = i; } - qbus_create_inplace((BusState *)&s->adb_bus, TYPE_ADB_BUS, DEVICE(obj), - "adb.0"); + qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS, + DEVICE(obj), "adb.0"); } static void cuda_class_init(ObjectClass *oc, void *data) diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index c0d0bf7287..7f99aa0d5c 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -202,11 +202,12 @@ static int macio_oldworld_initfn(PCIDevice *d) return 0; } -static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, int index) +static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size, + int index) { gchar *name; - object_initialize(ide, TYPE_MACIO_IDE); + object_initialize(ide, ide_size, TYPE_MACIO_IDE); qdev_set_parent_bus(DEVICE(ide), sysbus_get_default()); memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000), &ide->mem); @@ -224,13 +225,13 @@ static void macio_oldworld_init(Object *obj) qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs)); - object_initialize(&os->nvram, TYPE_MACIO_NVRAM); + object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM); dev = DEVICE(&os->nvram); qdev_prop_set_uint32(dev, "size", 0x2000); qdev_prop_set_uint32(dev, "it_shift", 4); for (i = 0; i < 2; i++) { - macio_init_ide(s, &os->ide[i], i); + macio_init_ide(s, &os->ide[i], sizeof(os->ide[i]), i); } } @@ -245,10 +246,10 @@ static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size) 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; } @@ -310,7 +311,7 @@ static void macio_newworld_init(Object *obj) qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs)); for (i = 0; i < 2; i++) { - macio_init_ide(s, &ns->ide[i], i); + macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i); } } @@ -321,7 +322,7 @@ static void macio_instance_init(Object *obj) memory_region_init(&s->bar, NULL, "macio", 0x80000); - object_initialize(&s->cuda, TYPE_CUDA); + object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA); qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default()); object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL); diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index 017e69352a..a1c08fb74e 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -276,8 +276,8 @@ static void vfio_intx_mmap_enable(void *opaque) 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 @@ static void vfio_intx_interrupt(void *opaque) 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 @@ static void vfio_disable_intx(VFIODevice *vdev) { 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; @@ -646,7 +646,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr, vector->virq = msg ? kvm_irqchip_add_msi_route(kvm_state, *msg) : -1; if (vector->virq < 0 || kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt, - vector->virq) < 0) { + NULL, vector->virq) < 0) { if (vector->virq >= 0) { kvm_irqchip_release_virq(kvm_state, vector->virq); vector->virq = -1; @@ -814,7 +814,7 @@ retry: vector->virq = kvm_irqchip_add_msi_route(kvm_state, msg); if (vector->virq < 0 || kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interrupt, - vector->virq) < 0) { + NULL, vector->virq) < 0) { qemu_set_fd_handler(event_notifier_get_fd(&vector->interrupt), vfio_msi_interrupt, NULL, vector); } @@ -3176,7 +3176,7 @@ static int vfio_initfn(PCIDevice *pdev) } 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 @@ static void vfio_exitfn(PCIDevice *pdev) 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); diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index 049aa704c1..789d385743 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -274,7 +274,7 @@ static void do_read_rra(dp8393xState *s) 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 @@ static void set_next_tick(dp8393xState *s) 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 @@ static void update_wt_regs(dp8393xState *s) 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 ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) 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 @@ static void nic_cleanup(NetClientState *nc) 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 @@ void dp83932_init(NICInfo *nd, hwaddr base, int it_shift, 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 fdb1f890b4..f5ebed46ab 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -190,7 +190,7 @@ set_phy_ctrl(E1000State *s, int index, uint16_t val) 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 @@ static void e1000_reset(void *opaque) 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 @@ static int e1000_post_load(void *opaque, int version_id) 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 @@ pci_e1000_uninit(PCIDevice *dev) { 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 @@ static int pci_e1000_init(PCIDevice *pci_dev) 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; } diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c index 2c838f67dc..2315f996d4 100644 --- a/hw/net/lan9118.c +++ b/hw/net/lan9118.c @@ -439,7 +439,7 @@ static void lan9118_reset(DeviceState *d) 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); @@ -1236,7 +1236,7 @@ static uint64_t lan9118_readl(void *opaque, hwaddr offset, 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; diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c index 2c2301c360..a8931652b3 100644 --- a/hw/net/pcnet-pci.c +++ b/hw/net/pcnet-pci.c @@ -284,8 +284,8 @@ static void pci_pcnet_uninit(PCIDevice *dev) 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); } diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c index 63aa73a241..7cb47b3f1f 100644 --- a/hw/net/pcnet.c +++ b/hw/net/pcnet.c @@ -1331,7 +1331,7 @@ static void pcnet_poll_timer(void *opaque) { PCNetState *s = opaque; - qemu_del_timer(s->poll_timer); + timer_del(s->poll_timer); if (CSR_TDMD(s)) { pcnet_transmit(s); @@ -1340,7 +1340,7 @@ static void pcnet_poll_timer(void *opaque) 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 { @@ -1351,8 +1351,8 @@ static void pcnet_poll_timer(void *opaque) } 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))); } } @@ -1731,7 +1731,7 @@ int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) 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 ee3b6903a1..c31199f8c8 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -2648,7 +2648,7 @@ static void rtl8139_IntrMask_write(RTL8139State *s, uint32_t val) 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 @@ static void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val) * 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 void rtl8139_IntrStatus_write(RTL8139State *s, uint32_t val) 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 @@ static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time) 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 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val) 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 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val) 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 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr) 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 uint32_t rtl8139_mmio_readl(void *opaque, hwaddr addr) 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 const VMStateDescription vmstate_rtl8139_hotplug_ready ={ 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 @@ static void rtl8139_timer(void *opaque) 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 @@ static void pci_rtl8139_uninit(PCIDevice *dev) 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 @@ static int pci_rtl8139_init(PCIDevice *dev) 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"); diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index aa1880cb87..dd41008fb0 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -162,14 +162,14 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status) 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 @@ static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq) 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 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue) 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 @@ static int virtio_net_device_init(VirtIODevice *vdev) 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 @@ static int virtio_net_device_exit(DeviceState *qdev) 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); } diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c index f173429ecc..3eb7715c22 100644 --- a/hw/net/xilinx_axienet.c +++ b/hw/net/xilinx_axienet.c @@ -990,8 +990,10 @@ static void xilinx_enet_init(Object *obj) (Object **) &s->tx_control_dev, &errp); assert_no_error(errp); - object_initialize(&s->rx_data_dev, TYPE_XILINX_AXI_ENET_DATA_STREAM); - object_initialize(&s->rx_control_dev, TYPE_XILINX_AXI_ENET_CONTROL_STREAM); + object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev), + TYPE_XILINX_AXI_ENET_DATA_STREAM); + object_initialize(&s->rx_control_dev, sizeof(s->rx_control_dev), + TYPE_XILINX_AXI_ENET_CONTROL_STREAM); object_property_add_child(OBJECT(s), "axistream-connected-target", (Object *)&s->rx_data_dev, &errp); assert_no_error(errp); diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c index 4144b34be7..988ca20898 100644 --- a/hw/openrisc/cputimer.c +++ b/hw/openrisc/cputimer.c @@ -33,9 +33,9 @@ void cpu_openrisc_count_update(OpenRISCCPU *cpu) 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 @@ void cpu_openrisc_count_update(OpenRISCCPU *cpu) } 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 @@ static void openrisc_timer_cb(void *opaque) 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 @@ static void openrisc_timer_cb(void *opaque) 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 2a2d077acf..8e1af8bf2e 100644 --- a/hw/openrisc/openrisc_sim.c +++ b/hw/openrisc/openrisc_sim.c @@ -86,9 +86,8 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size, kernel_filename); exit(1); } + cpu->env.pc = entry; } - - cpu->env.pc = entry; } static void openrisc_sim_init(QEMUMachineInitArgs *args) diff --git a/hw/openrisc/pic_cpu.c b/hw/openrisc/pic_cpu.c index ca0b7c11bd..2af1d6013a 100644 --- a/hw/openrisc/pic_cpu.c +++ b/hw/openrisc/pic_cpu.c @@ -26,26 +26,25 @@ static void openrisc_pic_cpu_handler(void *opaque, int irq, int level) { 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-host/prep.c b/hw/pci-host/prep.c index e120058511..0e71fdbfb1 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -155,11 +155,11 @@ static void raven_pcihost_initfn(Object *obj) MemoryRegion *address_space_io = get_system_io(); DeviceState *pci_dev; - pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), NULL, + pci_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), NULL, address_space_mem, address_space_io, 0, TYPE_PCI_BUS); h->bus = &s->pci_bus; - object_initialize(&s->pci_dev, TYPE_RAVEN_PCI_DEVICE); + object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_RAVEN_PCI_DEVICE); pci_dev = DEVICE(&s->pci_dev); qdev_set_parent_bus(pci_dev, BUS(&s->pci_bus)); object_property_set_int(OBJECT(&s->pci_dev), PCI_DEVFN(0, 0), "addr", diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 4febd24f12..54735043b7 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -133,7 +133,7 @@ static void q35_host_initfn(Object *obj) memory_region_init_io(&phb->data_mem, obj, &pci_host_data_le_ops, phb, "pci-conf-data", 4); - object_initialize(&s->mch, TYPE_MCH_PCI_DEVICE); + object_initialize(&s->mch, sizeof(s->mch), TYPE_MCH_PCI_DEVICE); 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); diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c index 9238d39b00..6b28929d26 100644 --- a/hw/pci-host/versatile.c +++ b/hw/pci-host/versatile.c @@ -384,12 +384,12 @@ static void pci_vpb_init(Object *obj) memory_region_init(&s->pci_io_space, OBJECT(s), "pci_io", 1ULL << 32); memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 1ULL << 32); - pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), "pci", + pci_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), "pci", &s->pci_mem_space, &s->pci_io_space, PCI_DEVFN(11, 0), TYPE_PCI_BUS); h->bus = &s->pci_bus; - object_initialize(&s->pci_dev, TYPE_VERSATILE_PCI_HOST); + object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_VERSATILE_PCI_HOST); qdev_set_parent_bus(DEVICE(&s->pci_dev), BUS(&s->pci_bus)); /* Window sizes for VersatilePB; realview_pci's init will override */ diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 8c33352c9a..d00682e134 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -312,13 +312,13 @@ bool pci_bus_is_root(PCIBus *bus) return !bus->parent_dev; } -void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent, +void pci_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, const char *name, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, uint8_t devfn_min, const char *typename) { - qbus_create_inplace(bus, typename, parent, name); + qbus_create_inplace(bus, bus_size, typename, parent, name); pci_bus_init(bus, parent, name, address_space_mem, address_space_io, devfn_min); } diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index a90671d2f2..e6b22b860f 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -367,7 +367,8 @@ int pci_bridge_initfn(PCIDevice *dev, const char *typename) br->bus_name = dev->qdev.id; } - qbus_create_inplace(&sec_bus->qbus, typename, &dev->qdev, br->bus_name); + qbus_create_inplace(sec_bus, sizeof(br->sec_bus), typename, DEVICE(dev), + br->bus_name); sec_bus->parent_dev = dev; sec_bus->map_irq = br->map_irq ? br->map_irq : pci_swizzle_map_irq_fn; sec_bus->address_space_mem = &br->address_space_mem; diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index e79612b0e9..9059ff9bc7 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -123,13 +123,14 @@ static void dt_serial_create(void *fdt, unsigned long long offset, } } -static int ppce500_load_device_tree(CPUPPCState *env, - QEMUMachineInitArgs *args, +static int ppce500_load_device_tree(QEMUMachineInitArgs *args, PPCE500Params *params, hwaddr addr, hwaddr initrd_base, - hwaddr initrd_size) + hwaddr initrd_size, + bool dry_run) { + CPUPPCState *env = first_cpu->env_ptr; int ret = -1; uint64_t mem_reg_property[] = { 0, cpu_to_be64(args->ram_size) }; int fdt_size; @@ -369,12 +370,10 @@ static int ppce500_load_device_tree(CPUPPCState *env, } done: - qemu_devtree_dumpdtb(fdt, fdt_size); - ret = rom_add_blob_fixed(BINARY_DEVICE_TREE_FILE, fdt, fdt_size, addr); - if (ret < 0) { - goto out; + if (!dry_run) { + qemu_devtree_dumpdtb(fdt, fdt_size); + cpu_physical_memory_write(addr, fdt, fdt_size); } - g_free(fdt); ret = fdt_size; out: @@ -383,6 +382,41 @@ out: return ret; } +typedef struct DeviceTreeParams { + QEMUMachineInitArgs args; + PPCE500Params params; + hwaddr addr; + hwaddr initrd_base; + hwaddr initrd_size; +} DeviceTreeParams; + +static void ppce500_reset_device_tree(void *opaque) +{ + DeviceTreeParams *p = opaque; + ppce500_load_device_tree(&p->args, &p->params, p->addr, p->initrd_base, + p->initrd_size, false); +} + +static int ppce500_prep_device_tree(QEMUMachineInitArgs *args, + PPCE500Params *params, + hwaddr addr, + hwaddr initrd_base, + hwaddr initrd_size) +{ + DeviceTreeParams *p = g_new(DeviceTreeParams, 1); + p->args = *args; + p->params = *params; + p->addr = addr; + p->initrd_base = initrd_base; + p->initrd_size = initrd_size; + + qemu_register_reset(ppce500_reset_device_tree, p); + + /* Issue the device tree loader once, so that we get the size of the blob */ + return ppce500_load_device_tree(args, params, addr, initrd_base, + initrd_size, true); +} + /* Create -kernel TLB entries for BookE. */ static inline hwaddr booke206_page_size_to_tlb(uint64_t size) { @@ -746,7 +780,7 @@ void ppce500_init(QEMUMachineInitArgs *args, PPCE500Params *params) struct boot_info *boot_info; int dt_size; - dt_size = ppce500_load_device_tree(env, args, params, dt_base, + dt_size = ppce500_prep_device_tree(args, params, dt_base, initrd_base, initrd_size); if (dt_size < 0) { fprintf(stderr, "couldn't load device tree\n"); diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index e1c095c7e2..59b41cbc6f 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -471,7 +471,7 @@ uint64_t cpu_ppc_load_tbl (CPUPPCState *env) 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 @@ static inline uint32_t _cpu_ppc_load_tbu(CPUPPCState *env) 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 @@ void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value) 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 @@ static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value) 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 @@ uint64_t cpu_ppc_load_atbl (CPUPPCState *env) 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 @@ uint32_t cpu_ppc_load_atbu (CPUPPCState *env) 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 @@ void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value) 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 @@ void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value) 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 @@ static void cpu_ppc_tb_stop (CPUPPCState *env) /* 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 @@ static void cpu_ppc_tb_start (CPUPPCState *env) /* 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 @@ static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next) 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 @@ uint64_t cpu_ppc_load_purr (CPUPPCState *env) 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 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, 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 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, } *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 @@ static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value) 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 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq) 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 @@ static void cpu_4xx_fit_cb (void *opaque) 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 @@ static void cpu_4xx_fit_cb (void *opaque) 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 @@ static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp) (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 @@ static void cpu_4xx_wdt_cb (void *opaque) 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 @@ static void cpu_4xx_wdt_cb (void *opaque) 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 @@ clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq, 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_boards.c b/hw/ppc/ppc405_boards.c index 43a83ca7c5..f1a8f6734a 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -27,9 +27,11 @@ #include "hw/timer/m48t59.h" #include "hw/block/flash.h" #include "sysemu/sysemu.h" +#include "sysemu/qtest.h" #include "block/block.h" #include "hw/boards.h" #include "qemu/log.h" +#include "qemu/error-report.h" #include "hw/loader.h" #include "sysemu/blockdev.h" #include "exec/address-spaces.h" @@ -42,7 +44,7 @@ #define USE_FLASH_BIOS -#define DEBUG_BOARD_INIT +//#define DEBUG_BOARD_INIT /*****************************************************************************/ /* PPC405EP reference board (IBM) */ @@ -252,17 +254,20 @@ static void ref405ep_init(QEMUMachineInitArgs *args) if (filename) { bios_size = load_image(filename, memory_region_get_ram_ptr(bios)); g_free(filename); + if (bios_size < 0 || bios_size > BIOS_SIZE) { + error_report("Could not load PowerPC BIOS '%s'", bios_name); + exit(1); + } + bios_size = (bios_size + 0xfff) & ~0xfff; + memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); + } else if (!qtest_enabled() || kernel_filename != NULL) { + error_report("Could not load PowerPC BIOS '%s'", bios_name); + exit(1); } else { + /* Avoid an uninitialized variable warning */ bios_size = -1; } - if (bios_size < 0 || bios_size > BIOS_SIZE) { - fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n", - bios_name); - exit(1); - } - bios_size = (bios_size + 0xfff) & ~0xfff; memory_region_set_readonly(bios, true); - memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); } /* Register FPGA */ #ifdef DEBUG_BOARD_INIT @@ -353,9 +358,9 @@ static void ref405ep_init(QEMUMachineInitArgs *args) bdloc = 0; } #ifdef DEBUG_BOARD_INIT + printf("bdloc " RAM_ADDR_FMT "\n", bdloc); printf("%s: Done\n", __func__); #endif - printf("bdloc " RAM_ADDR_FMT "\n", bdloc); } static QEMUMachine ref405ep_machine = { @@ -568,17 +573,17 @@ static void taihu_405ep_init(QEMUMachineInitArgs *args) if (filename) { bios_size = load_image(filename, memory_region_get_ram_ptr(bios)); g_free(filename); - } else { - bios_size = -1; - } - if (bios_size < 0 || bios_size > BIOS_SIZE) { - fprintf(stderr, "qemu: could not load PowerPC bios '%s'\n", - bios_name); + if (bios_size < 0 || bios_size > BIOS_SIZE) { + error_report("Could not load PowerPC BIOS '%s'", bios_name); + exit(1); + } + bios_size = (bios_size + 0xfff) & ~0xfff; + memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); + } else if (!qtest_enabled()) { + error_report("Could not load PowerPC BIOS '%s'", bios_name); exit(1); } - bios_size = (bios_size + 0xfff) & ~0xfff; memory_region_set_readonly(bios, true); - memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); } /* Register Linux flash */ dinfo = drive_get(IF_PFLASH, 0, fl_idx); diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 290f71ab69..6d6a7f1203 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -30,15 +30,15 @@ #include "qemu/log.h" #include "exec/address-spaces.h" -#define DEBUG_OPBA -#define DEBUG_SDRAM -#define DEBUG_GPIO -#define DEBUG_SERIAL -#define DEBUG_OCM +//#define DEBUG_OPBA +//#define DEBUG_SDRAM +//#define DEBUG_GPIO +//#define DEBUG_SERIAL +//#define DEBUG_OCM //#define DEBUG_I2C -#define DEBUG_GPT -#define DEBUG_MAL -#define DEBUG_CLOCKS +//#define DEBUG_GPT +//#define DEBUG_MAL +//#define DEBUG_CLOCKS //#define DEBUG_CLOCKS_LL ram_addr_t ppc405_set_bootinfo (CPUPPCState *env, ppc4xx_bd_info_t *bd, @@ -1348,7 +1348,7 @@ static uint32_t ppc4xx_gpt_readl (void *opaque, hwaddr addr) 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 @@ static void ppc4xx_gpt_writel (void *opaque, 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 @@ static void ppc4xx_gpt_reset (void *opaque) 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 @@ static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5]) 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/ppc_booke.c b/hw/ppc/ppc_booke.c index 000c27f2e8..8bbfc728de 100644 --- a/hw/ppc/ppc_booke.c +++ b/hw/ppc/ppc_booke.c @@ -136,7 +136,7 @@ static void booke_update_fixed_timer(CPUPPCState *env, 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 @@ static void booke_update_fixed_timer(CPUPPCState *env, (*next)++; } - qemu_mod_timer(timer, *next); + timer_mod(timer, *next); } static void booke_decr_cb(void *opaque) @@ -303,12 +303,12 @@ void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags) 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/spapr.c b/hw/ppc/spapr.c index 3a2b381288..279b88af97 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -88,6 +88,9 @@ int spapr_allocate_irq(int hint, bool lsi) if (hint) { irq = hint; + if (hint >= spapr->next_irq) { + spapr->next_irq = hint + 1; + } /* FIXME: we should probably check for collisions somehow */ } else { irq = spapr->next_irq++; @@ -103,22 +106,39 @@ int spapr_allocate_irq(int hint, bool lsi) return irq; } -/* Allocate block of consequtive IRQs, returns a number of the first */ -int spapr_allocate_irq_block(int num, bool lsi) +/* + * Allocate block of consequtive IRQs, returns a number of the first. + * If msi==true, aligns the first IRQ number to num. + */ +int spapr_allocate_irq_block(int num, bool lsi, bool msi) { int first = -1; - int i; + int i, hint = 0; + + /* + * MSIMesage::data is used for storing VIRQ so + * it has to be aligned to num to support multiple + * MSI vectors. MSI-X is not affected by this. + * The hint is used for the first IRQ, the rest should + * be allocated continously. + */ + if (msi) { + assert((num == 1) || (num == 2) || (num == 4) || + (num == 8) || (num == 16) || (num == 32)); + hint = (spapr->next_irq + num - 1) & ~(num - 1); + } for (i = 0; i < num; ++i) { int irq; - irq = spapr_allocate_irq(0, lsi); + irq = spapr_allocate_irq(hint, lsi); if (!irq) { return -1; } if (0 == i) { first = irq; + hint = 0; } /* If the above doesn't create a consecutive block then that's @@ -262,7 +282,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model, uint32_t start_prop = cpu_to_be32(initrd_base); uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt" - "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk"; + "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk\0hcall-set-mode"; char qemu_hypertas_prop[] = "hcall-memop1"; uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)}; uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)}; @@ -789,7 +809,7 @@ static void htab_save_first_pass(QEMUFile *f, sPAPREnvironment *spapr, { int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; int index = spapr->htab_save_index; - int64_t starttime = qemu_get_clock_ns(rt_clock); + int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); assert(spapr->htab_first_pass); @@ -820,7 +840,7 @@ static void htab_save_first_pass(QEMUFile *f, sPAPREnvironment *spapr, qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), HASH_PTE_SIZE_64 * n_valid); - if ((qemu_get_clock_ns(rt_clock) - starttime) > max_ns) { + if ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { break; } } @@ -841,7 +861,7 @@ static int htab_save_later_pass(QEMUFile *f, sPAPREnvironment *spapr, int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; int examined = 0, sent = 0; int index = spapr->htab_save_index; - int64_t starttime = qemu_get_clock_ns(rt_clock); + int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); assert(!spapr->htab_first_pass); @@ -886,7 +906,7 @@ static int htab_save_later_pass(QEMUFile *f, sPAPREnvironment *spapr, HASH_PTE_SIZE_64 * n_valid); sent += index - chunkstart; - if (!final && (qemu_get_clock_ns(rt_clock) - starttime) > max_ns) { + if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { break; } } @@ -1214,6 +1234,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) spapr_create_nvram(spapr); /* Set up PCI */ + spapr_pci_msi_init(spapr, SPAPR_PCI_MSI_WINDOW); spapr_pci_rtas_init(); phb = spapr_create_phb(spapr, 0); diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 67d6cd91d1..89e6a00dd9 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -657,6 +657,54 @@ static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr, return H_SUCCESS; } +static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPREnvironment *spapr, + target_ulong opcode, target_ulong *args) +{ + CPUState *cs; + target_ulong mflags = args[0]; + target_ulong resource = args[1]; + target_ulong value1 = args[2]; + target_ulong value2 = args[3]; + target_ulong ret = H_P2; + + if (resource == H_SET_MODE_ENDIAN) { + if (value1) { + ret = H_P3; + goto out; + } + if (value2) { + ret = H_P4; + goto out; + } + + switch (mflags) { + case H_SET_MODE_ENDIAN_BIG: + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + PowerPCCPU *cp = POWERPC_CPU(cs); + CPUPPCState *env = &cp->env; + env->spr[SPR_LPCR] &= ~LPCR_ILE; + } + ret = H_SUCCESS; + break; + + case H_SET_MODE_ENDIAN_LITTLE: + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + PowerPCCPU *cp = POWERPC_CPU(cs); + CPUPPCState *env = &cp->env; + env->spr[SPR_LPCR] |= LPCR_ILE; + } + ret = H_SUCCESS; + break; + + default: + ret = H_UNSUPPORTED_FLAG; + } + } + +out: + return ret; +} + static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1]; static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1]; @@ -734,6 +782,8 @@ static void hypercall_register_types(void) /* qemu/KVM-PPC specific hcalls */ spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas); + + spapr_register_hypercall(H_SET_MODE, h_set_mode); } type_init(hypercall_register_types) diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 3d4a1fcfe1..ef45f4f0cc 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -22,13 +22,12 @@ #include "kvm_ppc.h" #include "sysemu/dma.h" #include "exec/address-spaces.h" +#include "trace.h" #include "hw/ppc/spapr.h" #include <libfdt.h> -/* #define DEBUG_TCE */ - enum sPAPRTCEAccess { SPAPR_TCE_FAULT = 0, SPAPR_TCE_RO = 1, @@ -61,44 +60,28 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr) { sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu); uint64_t tce; - -#ifdef DEBUG_TCE - fprintf(stderr, "spapr_tce_translate liobn=0x%" PRIx32 " addr=0x" - DMA_ADDR_FMT "\n", tcet->liobn, addr); -#endif + IOMMUTLBEntry ret = { + .target_as = &address_space_memory, + .iova = 0, + .translated_addr = 0, + .addr_mask = ~(hwaddr)0, + .perm = IOMMU_NONE, + }; if (tcet->bypass) { - return (IOMMUTLBEntry) { - .target_as = &address_space_memory, - .iova = 0, - .translated_addr = 0, - .addr_mask = ~(hwaddr)0, - .perm = IOMMU_RW, - }; - } - - /* Check if we are in bound */ - if (addr >= tcet->window_size) { -#ifdef DEBUG_TCE - fprintf(stderr, "spapr_tce_translate out of bounds\n"); -#endif - return (IOMMUTLBEntry) { .perm = IOMMU_NONE }; + ret.perm = IOMMU_RW; + } else if (addr < tcet->window_size) { + /* Check if we are in bound */ + tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT]; + ret.iova = addr & ~SPAPR_TCE_PAGE_MASK; + ret.translated_addr = tce & ~SPAPR_TCE_PAGE_MASK; + ret.addr_mask = SPAPR_TCE_PAGE_MASK; + ret.perm = tce; } + trace_spapr_iommu_xlate(tcet->liobn, addr, ret.iova, ret.perm, + ret.addr_mask); - tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT]; - -#ifdef DEBUG_TCE - fprintf(stderr, " -> *paddr=0x%llx, *len=0x%llx\n", - (tce & ~SPAPR_TCE_PAGE_MASK), SPAPR_TCE_PAGE_MASK + 1); -#endif - - return (IOMMUTLBEntry) { - .target_as = &address_space_memory, - .iova = addr & ~SPAPR_TCE_PAGE_MASK, - .translated_addr = tce & ~SPAPR_TCE_PAGE_MASK, - .addr_mask = SPAPR_TCE_PAGE_MASK, - .perm = tce, - }; + return ret; } static int spapr_tce_table_pre_load(void *opaque) @@ -150,10 +133,7 @@ static int spapr_tce_table_realize(DeviceState *dev) } 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 + trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd); memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops, "iommu-spapr", UINT64_MAX); @@ -250,20 +230,17 @@ static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong liobn = args[0]; target_ulong ioba = args[1]; target_ulong tce = args[2]; + target_ulong ret = H_PARAMETER; sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn); ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1); if (tcet) { - return put_tce_emu(tcet, ioba, tce); + ret = put_tce_emu(tcet, ioba, tce); } -#ifdef DEBUG_TCE - fprintf(stderr, "%s on liobn=" TARGET_FMT_lx /*%s*/ - " ioba 0x" TARGET_FMT_lx " TCE 0x" TARGET_FMT_lx "\n", - __func__, liobn, /*dev->qdev.id, */ioba, tce); -#endif + trace_spapr_iommu_put(liobn, ioba, tce, ret); - return H_PARAMETER; + return ret; } int spapr_dma_dt(void *fdt, int node_off, const char *propname, diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 1ca35a0a72..9b6ee32acf 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -65,22 +65,14 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid, { sPAPRPHBState *sphb = find_phb(spapr, buid); PCIHostState *phb = PCI_HOST_BRIDGE(sphb); - BusState *bus = BUS(phb->bus); - BusChild *kid; + int bus_num = (config_addr >> 16) & 0xFF; int devfn = (config_addr >> 8) & 0xFF; if (!phb) { return NULL; } - QTAILQ_FOREACH(kid, &bus->children, sibling) { - PCIDevice *dev = (PCIDevice *)kid->child; - if (dev->devfn == devfn) { - return dev; - } - } - - return NULL; + return pci_find_device(phb->bus, bus_num, devfn); } static uint32_t rtas_pci_cfgaddr(uint32_t arg) @@ -258,11 +250,11 @@ static int spapr_msicfg_find(sPAPRPHBState *phb, uint32_t config_addr, * This is required for msi_notify()/msix_notify() which * will write at the addresses via spapr_msi_write(). */ -static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr, - bool msix, unsigned req_num) +static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr, bool msix, + unsigned first_irq, unsigned req_num) { unsigned i; - MSIMessage msg = { .address = addr, .data = 0 }; + MSIMessage msg = { .address = addr, .data = first_irq }; if (!msix) { msi_set_message(pdev, msg); @@ -270,8 +262,7 @@ static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr, return; } - for (i = 0; i < req_num; ++i) { - msg.address = addr | (i << 2); + for (i = 0; i < req_num; ++i, ++msg.data) { msix_set_message(pdev, i, msg); trace_spapr_pci_msi_setup(pdev->name, i, msg.address); } @@ -351,7 +342,8 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr, /* There is no cached config, allocate MSIs */ if (!phb->msi_table[ndev].nvec) { - irq = spapr_allocate_irq_block(req_num, false); + irq = spapr_allocate_irq_block(req_num, false, + ret_intr_type == RTAS_TYPE_MSI); if (irq < 0) { fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev); rtas_st(rets, 0, -1); /* Hardware error */ @@ -363,8 +355,8 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr, } /* Setup MSI/MSIX vectors in the device (via cfgspace or MSIX BAR) */ - spapr_msi_setmsg(pdev, phb->msi_win_addr | (ndev << 16), - ret_intr_type == RTAS_TYPE_MSIX, req_num); + spapr_msi_setmsg(pdev, spapr->msi_win_addr, ret_intr_type == RTAS_TYPE_MSIX, + phb->msi_table[ndev].irq, req_num); rtas_st(rets, 0, 0); rtas_st(rets, 1, req_num); @@ -450,10 +442,7 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) static void spapr_msi_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { - sPAPRPHBState *phb = opaque; - int ndev = addr >> 16; - int vec = ((addr & 0xFFFF) >> 2) | data; - uint32_t irq = phb->msi_table[ndev].irq + vec; + uint32_t irq = data; trace_spapr_pci_msi_write(addr, data, irq); @@ -467,6 +456,23 @@ static const MemoryRegionOps spapr_msi_ops = { .endianness = DEVICE_LITTLE_ENDIAN }; +void spapr_pci_msi_init(sPAPREnvironment *spapr, hwaddr addr) +{ + /* + * As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors, + * we need to allocate some memory to catch those writes coming + * from msi_notify()/msix_notify(). + * As MSIMessage:addr is going to be the same and MSIMessage:data + * is going to be a VIRQ number, 4 bytes of the MSI MR will only + * be used. + */ + spapr->msi_win_addr = addr; + memory_region_init_io(&spapr->msiwindow, NULL, &spapr_msi_ops, spapr, + "msi", getpagesize()); + memory_region_add_subregion(get_system_memory(), spapr->msi_win_addr, + &spapr->msiwindow); +} + /* * PHB PCI device */ @@ -492,8 +498,7 @@ static int spapr_phb_init(SysBusDevice *s) if ((sphb->buid != -1) || (sphb->dma_liobn != -1) || (sphb->mem_win_addr != -1) - || (sphb->io_win_addr != -1) - || (sphb->msi_win_addr != -1)) { + || (sphb->io_win_addr != -1)) { fprintf(stderr, "Either \"index\" or other parameters must" " be specified for PAPR PHB, not both\n"); return -1; @@ -506,7 +511,6 @@ static int spapr_phb_init(SysBusDevice *s) + sphb->index * SPAPR_PCI_WINDOW_SPACING; sphb->mem_win_addr = windows_base + SPAPR_PCI_MMIO_WIN_OFF; sphb->io_win_addr = windows_base + SPAPR_PCI_IO_WIN_OFF; - sphb->msi_win_addr = windows_base + SPAPR_PCI_MSI_WIN_OFF; } if (sphb->buid == -1) { @@ -529,11 +533,6 @@ static int spapr_phb_init(SysBusDevice *s) return -1; } - if (sphb->msi_win_addr == -1) { - fprintf(stderr, "MSI window address not specified for PHB\n"); - return -1; - } - if (find_phb(spapr, sphb->buid)) { fprintf(stderr, "PCI host bridges must have unique BUIDs\n"); return -1; @@ -573,18 +572,6 @@ static int spapr_phb_init(SysBusDevice *s) get_system_io(), 0, SPAPR_PCI_IO_WIN_SIZE); memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, &sphb->iowindow); - - /* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors, - * we need to allocate some memory to catch those writes coming - * from msi_notify()/msix_notify() */ - if (msi_supported) { - sprintf(namebuf, "%s.msi", sphb->dtbusname); - memory_region_init_io(&sphb->msiwindow, OBJECT(sphb), &spapr_msi_ops, sphb, - namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000); - memory_region_add_subregion(get_system_memory(), sphb->msi_win_addr, - &sphb->msiwindow); - } - /* * Selecting a busname is more complex than you'd think, due to * interacting constraints. If the user has specified an id @@ -659,7 +646,6 @@ static Property spapr_phb_properties[] = { DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, -1), DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, SPAPR_PCI_IO_WIN_SIZE), - DEFINE_PROP_HEX64("msi_win_addr", sPAPRPHBState, msi_win_addr, -1), DEFINE_PROP_END_OF_LIST(), }; @@ -701,7 +687,6 @@ static const VMStateDescription vmstate_spapr_pci = { 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, diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 394ce05ba2..eb542f218a 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -202,6 +202,28 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPREnvironment *spapr, rtas_st(rets, 0, -3); } +static void rtas_stop_self(PowerPCCPU *cpu, sPAPREnvironment *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, + uint32_t nret, target_ulong rets) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + + cs->halted = 1; + cpu_exit(cs); + /* + * While stopping a CPU, the guest calls H_CPPR which + * effectively disables interrupts on XICS level. + * However decrementer interrupts in TCG can still + * wake the CPU up so here we disable interrupts in MSR + * as well. + * As rtas_start_cpu() resets the whole MSR anyway, there is + * no need to bother with specific bits, we just clear it. + */ + env->msr = 0; +} + static struct rtas_call { const char *name; spapr_rtas_fn fn; @@ -322,6 +344,7 @@ static void core_rtas_register_types(void) spapr_rtas_register("query-cpu-stopped-state", rtas_query_cpu_stopped_state); spapr_rtas_register("start-cpu", rtas_start_cpu); + spapr_rtas_register("stop-self", rtas_stop_self); } type_init(core_rtas_register_types) diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index 7250f512ea..fcfa678344 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -141,22 +141,31 @@ static int xilinx_load_device_tree(hwaddr addr, { char *path; int fdt_size; - void *fdt; + void *fdt = NULL; int r; + const char *dtb_filename; - /* Try the local "ppc.dtb" override. */ - fdt = load_device_tree("ppc.dtb", &fdt_size); - if (!fdt) { - path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); - if (path) { - fdt = load_device_tree(path, &fdt_size); - g_free(path); + dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb"); + if (dtb_filename) { + fdt = load_device_tree(dtb_filename, &fdt_size); + if (!fdt) { + error_report("Error while loading device tree file '%s'", + dtb_filename); } + } else { + /* Try the local "ppc.dtb" override. */ + fdt = load_device_tree("ppc.dtb", &fdt_size); if (!fdt) { - return 0; + path = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE); + if (path) { + fdt = load_device_tree(path, &fdt_size); + g_free(path); + } } } - + if (!fdt) { + return 0; + } r = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline); if (r < 0) fprintf(stderr, "couldn't set /chosen/bootargs\n"); diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c index 0faade0766..a3aceef8f5 100644 --- a/hw/s390x/event-facility.c +++ b/hw/s390x/event-facility.c @@ -324,8 +324,8 @@ static int init_event_facility(S390SCLPDevice *sdev) sdev->event_pending = event_pending; /* Spawn a new sclp-events facility */ - qbus_create_inplace(&event_facility->sbus.qbus, - TYPE_SCLP_EVENTS_BUS, (DeviceState *)sdev, NULL); + qbus_create_inplace(&event_facility->sbus, sizeof(event_facility->sbus), + TYPE_SCLP_EVENTS_BUS, DEVICE(sdev), NULL); event_facility->sbus.qbus.allow_hotplug = 0; event_facility->qdev = (DeviceState *) sdev; diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index f0aa9414f2..6a831114da 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -47,7 +47,8 @@ #define VIRTIO_EXT_CODE 0x2603 -static void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev); +static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size, + VirtIOS390Device *dev); static const TypeInfo s390_virtio_bus_info = { .name = TYPE_S390_VIRTIO_BUS, @@ -170,7 +171,7 @@ static int s390_virtio_net_init(VirtIOS390Device *s390_dev) static void s390_virtio_net_instance_init(Object *obj) { VirtIONetS390 *dev = VIRTIO_NET_S390(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_NET); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -189,7 +190,7 @@ static int s390_virtio_blk_init(VirtIOS390Device *s390_dev) static void s390_virtio_blk_instance_init(Object *obj) { VirtIOBlkS390 *dev = VIRTIO_BLK_S390(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BLK); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -230,7 +231,7 @@ static int s390_virtio_serial_init(VirtIOS390Device *s390_dev) static void s390_virtio_serial_instance_init(Object *obj) { VirtIOSerialS390 *dev = VIRTIO_SERIAL_S390(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SERIAL); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -262,7 +263,7 @@ static int s390_virtio_scsi_init(VirtIOS390Device *s390_dev) static void s390_virtio_scsi_instance_init(Object *obj) { VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -283,7 +284,7 @@ static int s390_vhost_scsi_init(VirtIOS390Device *s390_dev) static void s390_vhost_scsi_instance_init(Object *obj) { VHostSCSIS390 *dev = VHOST_SCSI_S390(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VHOST_SCSI); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } #endif @@ -309,7 +310,7 @@ static int s390_virtio_rng_init(VirtIOS390Device *s390_dev) static void s390_virtio_rng_instance_init(Object *obj) { VirtIORNGS390 *dev = VIRTIO_RNG_S390(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_RNG); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, (Object **)&dev->vdev.conf.rng, NULL); @@ -585,7 +586,7 @@ static int s390_virtio_busdev_init(DeviceState *dev) VirtIOS390Device *_dev = (VirtIOS390Device *)dev; VirtIOS390DeviceClass *_info = VIRTIO_S390_DEVICE_GET_CLASS(dev); - virtio_s390_bus_new(&_dev->bus, _dev); + virtio_s390_bus_new(&_dev->bus, sizeof(_dev->bus), _dev); return _info->init(_dev); } @@ -691,14 +692,15 @@ static const TypeInfo s390_virtio_bridge_info = { /* virtio-s390-bus */ -static void virtio_s390_bus_new(VirtioBusState *bus, VirtIOS390Device *dev) +static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size, + VirtIOS390Device *dev) { DeviceState *qdev = DEVICE(dev); BusState *qbus; char virtio_bus_name[] = "virtio-bus"; - qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_S390_BUS, qdev, - virtio_bus_name); + qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_S390_BUS, + qdev, virtio_bus_name); qbus = BUS(bus); qbus->allow_hotplug = 1; } diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index e2681a63e6..733d988871 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -17,6 +17,21 @@ #include "css.h" #include "virtio-ccw.h" +void io_subsystem_reset(void) +{ + DeviceState *css, *sclp; + + css = DEVICE(object_resolve_path_type("", "virtual-css-bridge", NULL)); + if (css) { + qdev_reset_all(css); + } + sclp = DEVICE(object_resolve_path_type("", + "s390-sclp-event-facility", NULL)); + if (sclp) { + qdev_reset_all(sclp); + } +} + static int virtio_ccw_hcall_notify(const uint64_t *args) { uint64_t subch_id = args[0]; diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 8835bd4339..cd67db5e5b 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -27,7 +27,8 @@ #include "virtio-ccw.h" #include "trace.h" -static void virtio_ccw_bus_new(VirtioBusState *bus, VirtioCcwDevice *dev); +static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size, + VirtioCcwDevice *dev); static int virtual_css_bus_reset(BusState *qbus) { @@ -659,7 +660,7 @@ static int virtio_ccw_net_init(VirtioCcwDevice *ccw_dev) static void virtio_ccw_net_instance_init(Object *obj) { VirtIONetCcw *dev = VIRTIO_NET_CCW(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_NET); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -679,7 +680,7 @@ static int virtio_ccw_blk_init(VirtioCcwDevice *ccw_dev) static void virtio_ccw_blk_instance_init(Object *obj) { VirtIOBlkCcw *dev = VIRTIO_BLK_CCW(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BLK); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -712,7 +713,7 @@ static int virtio_ccw_serial_init(VirtioCcwDevice *ccw_dev) static void virtio_ccw_serial_instance_init(Object *obj) { VirtioSerialCcw *dev = VIRTIO_SERIAL_CCW(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SERIAL); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -758,7 +759,7 @@ static void balloon_ccw_stats_set_poll_interval(Object *obj, struct Visitor *v, static void virtio_ccw_balloon_instance_init(Object *obj) { VirtIOBalloonCcw *dev = VIRTIO_BALLOON_CCW(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BALLOON); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); object_property_add(obj, "guest-stats", "guest statistics", @@ -798,7 +799,7 @@ static int virtio_ccw_scsi_init(VirtioCcwDevice *ccw_dev) static void virtio_ccw_scsi_instance_init(Object *obj) { VirtIOSCSICcw *dev = VIRTIO_SCSI_CCW(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -819,7 +820,7 @@ static int vhost_ccw_scsi_init(VirtioCcwDevice *ccw_dev) static void vhost_ccw_scsi_instance_init(Object *obj) { VHostSCSICcw *dev = VHOST_SCSI_CCW(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VHOST_SCSI); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } #endif @@ -1170,7 +1171,7 @@ static const TypeInfo vhost_ccw_scsi = { static void virtio_ccw_rng_instance_init(Object *obj) { VirtIORNGCcw *dev = VIRTIO_RNG_CCW(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_RNG); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, (Object **)&dev->vdev.conf.rng, NULL); @@ -1209,7 +1210,7 @@ static int virtio_ccw_busdev_init(DeviceState *dev) VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev; VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev); - virtio_ccw_bus_new(&_dev->bus, _dev); + virtio_ccw_bus_new(&_dev->bus, sizeof(_dev->bus), _dev); return _info->init(_dev); } @@ -1289,14 +1290,15 @@ static const TypeInfo virtual_css_bridge_info = { /* virtio-ccw-bus */ -static void virtio_ccw_bus_new(VirtioBusState *bus, VirtioCcwDevice *dev) +static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size, + VirtioCcwDevice *dev) { DeviceState *qdev = DEVICE(dev); BusState *qbus; char virtio_bus_name[] = "virtio-bus"; - qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_CCW_BUS, qdev, - virtio_bus_name); + qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_CCW_BUS, + qdev, virtio_bus_name); qbus = BUS(bus); qbus->allow_hotplug = 1; } diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c index d7ec1736c0..99bf8ec446 100644 --- a/hw/scsi/esp-pci.c +++ b/hw/scsi/esp-pci.c @@ -363,7 +363,7 @@ static int esp_pci_scsi_init(PCIDevice *dev) pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io); s->irq = dev->irq[0]; - scsi_bus_new(&s->bus, d, &esp_pci_scsi_info, NULL); + scsi_bus_new(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info, NULL); if (!d->hotplugged) { scsi_bus_legacy_handle_cmdline(&s->bus, &err); if (err != NULL) { diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 101e957d4d..2d150bfe48 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -688,7 +688,7 @@ static void sysbus_esp_realize(DeviceState *dev, Error **errp) qdev_init_gpio_in(dev, sysbus_esp_gpio_demux, 2); - scsi_bus_new(&s->bus, dev, &esp_scsi_info, NULL); + scsi_bus_new(&s->bus, sizeof(s->bus), dev, &esp_scsi_info, NULL); scsi_bus_legacy_handle_cmdline(&s->bus, &err); if (err != NULL) { error_propagate(errp, err); diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 611f2aa1b2..0c36842729 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -2117,7 +2117,7 @@ static int lsi_scsi_init(PCIDevice *dev) pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io); QTAILQ_INIT(&s->queue); - scsi_bus_new(&s->bus, d, &lsi_scsi_info, NULL); + scsi_bus_new(&s->bus, sizeof(s->bus), d, &lsi_scsi_info, NULL); if (!d->hotplugged) { scsi_bus_legacy_handle_cmdline(&s->bus, &err); if (err != NULL) { diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index a6d5285911..09b51b387b 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -2171,7 +2171,8 @@ static int megasas_scsi_init(PCIDevice *dev) s->frames[i].state = s; } - scsi_bus_new(&s->bus, DEVICE(dev), &megasas_scsi_info, NULL); + scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), + &megasas_scsi_info, NULL); if (!d->hotplugged) { scsi_bus_legacy_handle_cmdline(&s->bus, &err); if (err != NULL) { diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index fbf9173fb4..5cd6137046 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -72,10 +72,10 @@ static void scsi_device_unit_attention_reported(SCSIDevice *s) } /* Create a scsi bus, and attach devices to it. */ -void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info, - const char *bus_name) +void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host, + const SCSIBusInfo *info, const char *bus_name) { - qbus_create_inplace(&bus->qbus, TYPE_SCSI_BUS, host, bus_name); + qbus_create_inplace(bus, bus_size, TYPE_SCSI_BUS, host, bus_name); bus->busnr = next_scsi_bus++; bus->info = info; bus->qbus.allow_hotplug = 1; diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c index e9090e5c72..b2fcd4b3e3 100644 --- a/hw/scsi/spapr_vscsi.c +++ b/hw/scsi/spapr_vscsi.c @@ -1020,7 +1020,8 @@ static int spapr_vscsi_init(VIOsPAPRDevice *dev) dev->crq.SendFunc = vscsi_do_crq; - scsi_bus_new(&s->bus, &dev->qdev, &vscsi_scsi_info, NULL); + scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), + &vscsi_scsi_info, NULL); if (!dev->qdev.hotplugged) { scsi_bus_legacy_handle_cmdline(&s->bus, &err); if (err != NULL) { diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 05da56bd24..3bd690d128 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -627,7 +627,8 @@ static int virtio_scsi_device_init(VirtIODevice *vdev) return ret; } - scsi_bus_new(&s->bus, qdev, &virtio_scsi_scsi_info, vdev->bus_name); + scsi_bus_new(&s->bus, sizeof(s->bus), qdev, + &virtio_scsi_scsi_info, vdev->bus_name); if (!qdev->hotplugged) { scsi_bus_legacy_handle_cmdline(&s->bus, &err); diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index d42b35941b..819d671ba2 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -1088,7 +1088,8 @@ pvscsi_init(PCIDevice *pci_dev) return -ENOMEM; } - scsi_bus_new(&s->bus, &pci_dev->qdev, &pvscsi_scsi_info, NULL); + scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(pci_dev), + &pvscsi_scsi_info, NULL); pvscsi_reset_state(s); return 0; diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index d2dbddc11e..1483e196cd 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -134,8 +134,8 @@ static void sdhci_raise_insertion_irq(void *opaque) 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 @@ static void sdhci_insert_eject_cb(void *opaque, int irq, int level) 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_card_readonly_cb(void *opaque, int irq, int level) 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 @@ static void sdhci_do_adma(SDHCIState *s) } /* 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 @@ static void sdhci_initfn(Object *obj) 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/sparc64/sun4u.c b/hw/sparc64/sun4u.c index e7a489387c..6f271d9cfc 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -363,7 +363,7 @@ void cpu_put_timer(QEMUFile *f, CPUTimer *s) 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 @@ void cpu_get_timer(QEMUFile *f, CPUTimer *s) 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 @@ static CPUTimer *cpu_timer_create(const char *name, SPARCCPU *cpu, 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 CPUTimer *cpu_timer_create(const char *name, SPARCCPU *cpu, 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 @@ void cpu_tick_set_count(CPUTimer *timer, uint64_t count) 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 @@ void cpu_tick_set_count(CPUTimer *timer, uint64_t count) 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 @@ uint64_t cpu_tick_get_count(CPUTimer *timer) 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 @@ void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit) 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); } } diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c index 92773155d2..8020c9f4b5 100644 --- a/hw/timer/arm_mptimer.c +++ b/hw/timer/arm_mptimer.c @@ -81,10 +81,10 @@ static void timerblock_reload(TimerBlock *tb, int restart) 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) @@ -113,7 +113,7 @@ static uint64_t timerblock_read(void *opaque, hwaddr addr, 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; @@ -140,7 +140,7 @@ static void timerblock_write(void *opaque, hwaddr addr, 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) { @@ -211,7 +211,7 @@ static void timerblock_reset(TimerBlock *tb) tb->status = 0; tb->tick = 0; if (tb->timer) { - qemu_del_timer(tb->timer); + timer_del(tb->timer); } } @@ -248,7 +248,7 @@ static int arm_mptimer_init(SysBusDevice *dev) 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); diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c index acfea59779..a47afde23a 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. */ diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c index 888f9ce000..a279bced78 100644 --- a/hw/timer/cadence_ttc.c +++ b/hw/timer/cadence_ttc.c @@ -172,7 +172,7 @@ static void cadence_timer_run(CadenceTimerState *s) 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)); } @@ -184,7 +184,7 @@ static void cadence_timer_sync(CadenceTimerState *s) (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) { @@ -401,7 +401,7 @@ static void cadence_timer_init(uint32_t freq, CadenceTimerState *s) 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) diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c index a38d9e4eb6..aee4990eb1 100644 --- a/hw/timer/etraxfs_timer.c +++ b/hw/timer/etraxfs_timer.c @@ -93,7 +93,7 @@ timer_read(void *opaque, hwaddr addr, unsigned int size) 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; diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c index a8009a4316..86f4fcd3e8 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" @@ -905,7 +906,7 @@ static void exynos4210_ltick_event(void *opaque) /* 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]; diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c index a52f0f6c6b..1aa8f4d07a 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" diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c index 7c1055a99c..74c16d6c90 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" diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 648b38362d..fcd22aea59 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -152,7 +152,7 @@ static int deactivating_bit(uint64_t old, uint64_t new, uint64_t mask) 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 @@ static int hpet_post_load(void *opaque, int version_id) 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 @@ static void hpet_timer(void *opaque) } } 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 @@ static void hpet_set_timer(HPETTimer *t) 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 @@ static void hpet_ram_write(void *opaque, hwaddr addr, 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 @@ static void hpet_realize(DeviceState *dev, Error **errp) } 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 cd5214064f..cdbf481951 100644 --- a/hw/timer/i8254.c +++ b/hw/timer/i8254.c @@ -51,7 +51,7 @@ static int pit_get_count(PITChannelState *s) 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 @@ static void pit_set_channel_gate(PITCommonState *s, PITChannelState *sc, 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 @@ static void pit_set_channel_gate(PITCommonState *s, PITChannelState *sc, 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 @@ static inline void pit_load_count(PITChannelState *s, int val) { 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 @@ static void pit_ioport_write(void *opaque, hwaddr addr, /* 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 @@ static void pit_irq_timer_update(PITChannelState *s, int64_t current_time) #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 @@ static void pit_reset(DeviceState *dev) 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 @@ static void pit_irq_control(void *opaque, int n, int enable) 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 @@ static void pit_post_load(PITCommonState *s) 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 @@ static void pit_realizefn(DeviceState *dev, Error **err) 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 4e5bf0b63c..e8fb971488 100644 --- a/hw/timer/i8254_common.c +++ b/hw/timer/i8254_common.c @@ -136,7 +136,7 @@ void pit_get_channel_info_common(PITCommonState *s, PITChannelState *sc, 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 @@ void pit_reset_common(PITCommonState *pit) 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 dc73d6525d..0dbe15c99b 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" diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c index 87db0e195c..f2d1975e70 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 986e6a19d2..8ed138cc0e 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) diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c index 0cc9e5b5ee..d3d78ec5a8 100644 --- a/hw/timer/m48t59.c +++ b/hw/timer/m48t59.c @@ -137,7 +137,7 @@ static void alarm_cb (void *opaque) /* 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); } @@ -146,10 +146,10 @@ static void set_alarm(M48t59State *NVRAM) { 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); } } @@ -188,10 +188,10 @@ static void set_up_watchdog(M48t59State *NVRAM, uint8_t value) 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)); } } @@ -609,10 +609,10 @@ static void m48t59_reset_common(M48t59State *NVRAM) 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) @@ -700,8 +700,8 @@ static void m48t59_realize_common(M48t59State *s, Error **errp) { 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); diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 3c3baaccfa..7230a6e4fa 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -102,7 +102,7 @@ static inline bool rtc_running(RTCState *s) 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 uint64_t get_guest_rtc_ns(RTCState *s) 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 @@ static void periodic_timer_update(RTCState *s, int64_t current_time) 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 @@ static void check_update_timer(RTCState *s) * 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 @@ static void check_update_timer(RTCState *s) * 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 @@ static void rtc_update_timer(void *opaque) 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 @@ static void cmos_ioport_write(void *opaque, hwaddr addr, /* 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 @@ static void cmos_ioport_write(void *opaque, hwaddr addr, 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 @@ static void rtc_set_time(RTCState *s) 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 @@ static int update_in_progress(RTCState *s) 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 @@ static void rtc_set_date_from_host(ISADevice *dev) 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 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) 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 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) } #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/omap_gptimer.c b/hw/timer/omap_gptimer.c index ac389d87ee..016207f626 100644 --- a/hw/timer/omap_gptimer.c +++ b/hw/timer/omap_gptimer.c @@ -103,7 +103,7 @@ static inline uint32_t omap_gp_timer_read(struct omap_gp_timer_s *timer) 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 @@ static inline void omap_gp_timer_sync(struct omap_gp_timer_s *timer) { 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 @@ static inline void omap_gp_timer_update(struct omap_gp_timer_s *timer) 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 @@ static void omap_gp_timer_tick(void *opaque) 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 @@ static void omap_gp_timer_write(void *opaque, hwaddr addr, 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 @@ static void omap_gp_timer_write(void *opaque, hwaddr addr, 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 @@ struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta, 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 a12aca20df..8e50488d17 100644 --- a/hw/timer/omap_synctimer.c +++ b/hw/timer/omap_synctimer.c @@ -28,7 +28,7 @@ struct omap_synctimer_s { /* 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 d5e2f3e265..65928a4819 100644 --- a/hw/timer/pl031.c +++ b/hw/timer/pl031.c @@ -78,7 +78,7 @@ static void pl031_interrupt(void * opaque) 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(); } @@ -91,11 +91,11 @@ static void pl031_set_alarm(PL031State *s) 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()); } } @@ -201,9 +201,10 @@ static int pl031_init(SysBusDevice *dev) 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; } @@ -212,8 +213,8 @@ static void pl031_pre_save(void *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(); } @@ -221,7 +222,7 @@ static int pl031_post_load(void *opaque, int version_id) { 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; diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c index 4bd2b76cb8..fa9eefd925 100644 --- a/hw/timer/puv3_ost.c +++ b/hw/timer/puv3_ost.c @@ -10,6 +10,7 @@ */ #include "hw/sysbus.h" #include "hw/ptimer.h" +#include "qemu/main-loop.h" #undef DEBUG_PUV3 #include "hw/unicore32/puv3.h" diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c index cdabccdd15..0f546c4121 100644 --- a/hw/timer/pxa2xx_timer.c +++ b/hw/timer/pxa2xx_timer.c @@ -123,7 +123,7 @@ static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu) 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); } } @@ -141,7 +141,7 @@ static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n) counter = counters[n]; if (!s->tm4[counter].freq) { - qemu_del_timer(s->tm4[n].tm.qtimer); + timer_del(s->tm4[n].tm.qtimer); return; } @@ -151,7 +151,7 @@ static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n) 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, @@ -188,7 +188,7 @@ static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset, 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 */ @@ -211,7 +211,7 @@ static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset, 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 @@ -220,7 +220,7 @@ static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset, 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; @@ -271,7 +271,7 @@ static void pxa2xx_timer_write(void *opaque, hwaddr offset, /* 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 */ @@ -291,11 +291,11 @@ static void pxa2xx_timer_write(void *opaque, hwaddr offset, 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; @@ -317,7 +317,7 @@ static void pxa2xx_timer_write(void *opaque, hwaddr offset, 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; @@ -351,7 +351,7 @@ static void pxa2xx_timer_write(void *opaque, hwaddr offset, 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 ++; @@ -370,7 +370,7 @@ static void pxa2xx_timer_write(void *opaque, hwaddr offset, 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: @@ -411,7 +411,7 @@ static void pxa2xx_timer_tick4(void *opaque) 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); } @@ -422,7 +422,7 @@ static int pxa25x_timer_post_load(void *opaque, int version_id) 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)) @@ -440,7 +440,7 @@ static int pxa2xx_timer_init(SysBusDevice *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 ++) { @@ -448,7 +448,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev) 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)) { @@ -460,7 +460,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev) 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]); } } diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c index 251a10dbfa..07f0670b5d 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 33e8f6c15c..f75b914951 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. diff --git a/hw/timer/tusb6010.c b/hw/timer/tusb6010.c index c48ecf8ee7..bd2a89e020 100644 --- a/hw/timer/tusb6010.c +++ b/hw/timer/tusb6010.c @@ -516,11 +516,11 @@ static void tusb_async_writew(void *opaque, hwaddr addr, 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: @@ -728,8 +728,8 @@ static void tusb6010_power(TUSBState *s, int on) /* 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); } } @@ -783,8 +783,8 @@ static int tusb6010_init(SysBusDevice *sbd) DeviceState *dev = DEVICE(sbd); TUSBState *s = TUSB(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); + 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(sbd, &s->iomem[0]); diff --git a/hw/timer/twl92230.c b/hw/timer/twl92230.c index b730d853f7..f3ea36503c 100644 --- a/hw/timer/twl92230.c +++ b/hw/timer/twl92230.c @@ -72,14 +72,14 @@ static inline void menelaus_update(MenelausState *s) 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 @@ static void menelaus_rtc_hz(void *opaque) 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 @@ static void menelaus_pre_save(void *opaque) { 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 @@ static int twl92230_init(I2CSlave *i2c) { 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 5f2c9020ea..6113b975bf 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) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index abe384ba9a..6f0a4d2814 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/bus.c b/hw/usb/bus.c index f83d1de6cd..82ca6a13e8 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -67,9 +67,10 @@ const VMStateDescription vmstate_usb_device = { } }; -void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host) +void usb_bus_new(USBBus *bus, size_t bus_size, + USBBusOps *ops, DeviceState *host) { - qbus_create_inplace(&bus->qbus, TYPE_USB_BUS, host, NULL); + qbus_create_inplace(bus, bus_size, TYPE_USB_BUS, host, NULL); bus->ops = ops; bus->busnr = next_usb_bus++; bus->qbus.allow_hotplug = 1; /* Yes, we can */ diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 2233c548fa..8c7a61ebe1 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -1309,7 +1309,8 @@ static int ccid_initfn(USBDevice *dev) usb_desc_create_serial(dev); usb_desc_init(dev); - qbus_create_inplace(&s->bus.qbus, TYPE_CCID_BUS, &dev->qdev, NULL); + qbus_create_inplace(&s->bus, sizeof(s->bus), TYPE_CCID_BUS, DEVICE(dev), + NULL); s->intr = usb_ep_get(dev, USB_TOKEN_IN, CCID_INT_IN_EP); s->bus.qbus.allow_hotplug = 1; s->card = NULL; diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index a8dc2fa960..1d81ac2a6b 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -618,7 +618,8 @@ static int usb_msd_initfn_storage(USBDevice *dev) usb_desc_create_serial(dev); usb_desc_init(dev); - scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_storage, NULL); + scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), + &usb_msd_scsi_info_storage, NULL); scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable, s->conf.bootindex, dev->serial, &err); @@ -646,7 +647,8 @@ static int usb_msd_initfn_bot(USBDevice *dev) usb_desc_create_serial(dev); usb_desc_init(dev); - scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_bot, NULL); + scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev), + &usb_msd_scsi_info_bot, NULL); s->bus.qbus.allow_hotplug = 0; usb_msd_handle_reset(dev); diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index 63ad12ea6b..1569d6e2ef 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -888,7 +888,8 @@ static int usb_uas_init(USBDevice *dev) QTAILQ_INIT(&uas->requests); uas->status_bh = qemu_bh_new(usb_uas_send_status_bh, uas); - scsi_bus_new(&uas->bus, &uas->dev.qdev, &usb_uas_scsi_info, NULL); + scsi_bus_new(&uas->bus, sizeof(uas->bus), DEVICE(dev), + &usb_uas_scsi_info, NULL); return 0; } diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 010a0d0d32..137e200202 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -150,7 +150,7 @@ typedef enum { #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 @@ static void ehci_reset(void *opaque) } 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); } @@ -2296,7 +2296,7 @@ static void ehci_frame_timer(void *opaque) 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 @@ static void ehci_frame_timer(void *opaque) 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); } } @@ -2520,14 +2520,14 @@ void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp) return; } - usb_bus_new(&s->bus, &ehci_bus_ops, dev); + usb_bus_new(&s->bus, sizeof(s->bus), &ehci_bus_ops, dev); for (i = 0; i < s->portnr; i++) { usb_register_port(&s->bus, &s->ports[i], s, i, &ehci_port_ops, USB_SPEED_MASK_HIGH); 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 7968e17c34..66bc61ae1e 100644 --- a/hw/usb/hcd-musb.c +++ b/hw/usb/hcd-musb.c @@ -383,7 +383,7 @@ struct MUSBState *musb_init(DeviceState *parent_device, int gpio_base) musb_reset(s); - usb_bus_new(&s->bus, &musb_bus_ops, parent_device); + usb_bus_new(&s->bus, sizeof(s->bus), &musb_bus_ops, parent_device); usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); @@ -558,9 +558,9 @@ static void musb_schedule_cb(USBPort *port, USBPacket *packey) 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_write_fifo(MUSBEndPoint *ep, uint8_t value) 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 d7836d6803..35f0878409 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1251,8 +1251,8 @@ static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) /* 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); } @@ -1349,12 +1349,12 @@ static void ohci_frame_boundary(void *opaque) */ 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); + fprintf(stderr, "usb-ohci: %s: timer_new_ns failed\n", ohci->name); ohci_die(ohci); return 0; } @@ -1370,7 +1370,7 @@ static int ohci_bus_start(OHCIState *ohci) 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; } @@ -1474,7 +1474,7 @@ static uint32_t ohci_get_frame_remaining(OHCIState *ohci) /* 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) @@ -1881,7 +1881,7 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState *dev, return -1; } } else { - usb_bus_new(&ohci->bus, &ohci_bus_ops, dev); + usb_bus_new(&ohci->bus, sizeof(ohci->bus), &ohci_bus_ops, dev); for (i = 0; i < num_ports; i++) { usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, &ohci_port_ops, diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index ac8283313e..becc7faec1 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 @@ -432,7 +433,7 @@ static int uhci_post_load(void *opaque, int version_id) 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; @@ -475,9 +476,9 @@ static void uhci_port_write(void *opaque, hwaddr addr, 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; @@ -1160,7 +1161,7 @@ static void uhci_frame_timer(void *opaque) 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; @@ -1169,7 +1170,7 @@ static void uhci_frame_timer(void *opaque) /* 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; @@ -1203,7 +1204,7 @@ static void uhci_frame_timer(void *opaque) } 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,14 +1254,14 @@ static int usb_uhci_common_initfn(PCIDevice *dev) return -1; } } else { - usb_bus_new(&s->bus, &uhci_bus_ops, &s->dev.qdev); + usb_bus_new(&s->bus, sizeof(s->bus), &uhci_bus_ops, DEVICE(dev)); for (i = 0; i < NB_PORTS; i++) { usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); } } 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); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 58c88b8a6b..d5c6588053 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -608,7 +608,7 @@ static const char *event_name(XHCIEvent *event) 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 @@ static void xhci_mfwrap_update(XHCIState *xhci) 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 @@ static void xhci_run(XHCIState *xhci) { 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 @@ static XHCIEPContext *xhci_alloc_epctx(XHCIState *xhci, 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 @@ static int xhci_ep_nuke_one_xfer(XHCITransfer *t) 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 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid, 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; @@ -1844,12 +1844,12 @@ static void xhci_check_iso_kick(XHCIState *xhci, XHCITransfer *xfer, 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; } } @@ -2745,7 +2745,7 @@ static void xhci_reset(DeviceState *dev) 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); } @@ -3309,7 +3309,7 @@ static void usb_xhci_init(XHCIState *xhci) usbports = MAX(xhci->numports_2, xhci->numports_3); xhci->numports = xhci->numports_2 + xhci->numports_3; - usb_bus_new(&xhci->bus, &xhci_bus_ops, dev); + usb_bus_new(&xhci->bus, sizeof(xhci->bus), &xhci_bus_ops, dev); for (i = 0; i < usbports; i++) { speedmask = 0; @@ -3366,7 +3366,7 @@ static int usb_xhci_initfn(struct PCIDevice *dev) 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]; @@ -3451,7 +3451,7 @@ static int usb_xhci_post_load(void *opaque, int version_id) 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)); } } } diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c index f660770076..128955dd92 100644 --- a/hw/usb/host-libusb.c +++ b/hw/usb/host-libusb.c @@ -1462,7 +1462,7 @@ static void usb_host_auto_check(void *unused) 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; @@ -1474,13 +1474,13 @@ static void usb_host_auto_check(void *unused) 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 7901f4c01a..65cd3b444c 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -1754,7 +1754,7 @@ static void usb_host_auto_check(void *unused) 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; @@ -1765,13 +1765,13 @@ static void usb_host_auto_check(void *unused) 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 e3b9f324b3..287a505b48 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1297,7 +1297,7 @@ static int usbredir_initfn(USBDevice *udev) } 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"); @@ -1338,8 +1338,8 @@ static void usbredir_handle_destroy(USBDevice *udev) /* 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); @@ -1493,7 +1493,7 @@ static void usbredir_device_connect(void *priv, 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; } @@ -1548,7 +1548,7 @@ static void usbredir_device_connect(void *priv, } 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) @@ -1556,7 +1556,7 @@ static void usbredir_device_disconnect(void *priv) 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"); @@ -1565,7 +1565,7 @@ static void usbredir_device_disconnect(void *priv) * 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 */ @@ -1588,7 +1588,7 @@ static void usbredir_interface_info(void *priv, * 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 " diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index aac7f83ccf..9504877120 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -78,8 +78,8 @@ static bool balloon_stats_enabled(const VirtIOBalloon *s) 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_destroy_timer(VirtIOBalloon *s) 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 @@ static void balloon_stats_set_poll_interval(Object *obj, struct Visitor *v, /* 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); } diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index 4bd29533f3..29cf284d12 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -89,7 +89,8 @@ typedef struct { VirtioBusState bus; } VirtIOMMIOProxy; -static void virtio_mmio_bus_new(VirtioBusState *bus, VirtIOMMIOProxy *dev); +static void virtio_mmio_bus_new(VirtioBusState *bus, size_t bus_size, + VirtIOMMIOProxy *dev); static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size) { @@ -360,7 +361,7 @@ static void virtio_mmio_realizefn(DeviceState *d, Error **errp) VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d); SysBusDevice *sbd = SYS_BUS_DEVICE(d); - virtio_mmio_bus_new(&proxy->bus, proxy); + virtio_mmio_bus_new(&proxy->bus, sizeof(proxy->bus), proxy); sysbus_init_irq(sbd, &proxy->irq); memory_region_init_io(&proxy->iomem, OBJECT(d), &virtio_mem_ops, proxy, TYPE_VIRTIO_MMIO, 0x200); @@ -385,12 +386,13 @@ static const TypeInfo virtio_mmio_info = { /* virtio-mmio-bus. */ -static void virtio_mmio_bus_new(VirtioBusState *bus, VirtIOMMIOProxy *dev) +static void virtio_mmio_bus_new(VirtioBusState *bus, size_t bus_size, + VirtIOMMIOProxy *dev) { DeviceState *qdev = DEVICE(dev); BusState *qbus; - qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_MMIO_BUS, qdev, NULL); + qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_MMIO_BUS, qdev, NULL); qbus = BUS(bus); qbus->allow_hotplug = 0; } diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 41b96cef1e..4825802598 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -92,7 +92,8 @@ /* HACK for virtio to determine if it's running a big endian guest */ bool virtio_is_big_endian(void); -static void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev); +static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, + VirtIOPCIProxy *dev); /* virtio device */ /* DeviceState to VirtIOPCIProxy. For use off data-path. TODO: use QOM. */ @@ -508,7 +509,7 @@ static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy, VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no); EventNotifier *n = virtio_queue_get_guest_notifier(vq); int ret; - ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, irqfd->virq); + ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, NULL, irqfd->virq); return ret; } @@ -917,7 +918,7 @@ static void virtio_9p_pci_class_init(ObjectClass *klass, void *data) static void virtio_9p_pci_instance_init(Object *obj) { V9fsPCIState *dev = VIRTIO_9P_PCI(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_9P); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_9P); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -985,7 +986,7 @@ static int virtio_pci_init(PCIDevice *pci_dev) { VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev); VirtioPCIClass *k = VIRTIO_PCI_GET_CLASS(pci_dev); - virtio_pci_bus_new(&dev->bus, dev); + virtio_pci_bus_new(&dev->bus, sizeof(dev->bus), dev); if (k->init != NULL) { return k->init(dev); } @@ -1077,7 +1078,7 @@ static void virtio_blk_pci_class_init(ObjectClass *klass, void *data) static void virtio_blk_pci_instance_init(Object *obj) { VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BLK); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BLK); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -1147,7 +1148,7 @@ static void virtio_scsi_pci_class_init(ObjectClass *klass, void *data) static void virtio_scsi_pci_instance_init(Object *obj) { VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SCSI); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SCSI); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -1204,7 +1205,7 @@ static void vhost_scsi_pci_class_init(ObjectClass *klass, void *data) static void vhost_scsi_pci_instance_init(Object *obj) { VHostSCSIPCI *dev = VHOST_SCSI_PCI(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VHOST_SCSI); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VHOST_SCSI); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -1285,7 +1286,7 @@ static void virtio_balloon_pci_class_init(ObjectClass *klass, void *data) static void virtio_balloon_pci_instance_init(Object *obj) { VirtIOBalloonPCI *dev = VIRTIO_BALLOON_PCI(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_BALLOON); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_BALLOON); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); object_property_add(obj, "guest-stats", "guest statistics", @@ -1371,7 +1372,7 @@ static void virtio_serial_pci_class_init(ObjectClass *klass, void *data) static void virtio_serial_pci_instance_init(Object *obj) { VirtIOSerialPCI *dev = VIRTIO_SERIAL_PCI(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_SERIAL); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_SERIAL); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -1430,7 +1431,7 @@ static void virtio_net_pci_class_init(ObjectClass *klass, void *data) static void virtio_net_pci_instance_init(Object *obj) { VirtIONetPCI *dev = VIRTIO_NET_PCI(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_NET); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_NET); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); } @@ -1486,7 +1487,7 @@ static void virtio_rng_pci_class_init(ObjectClass *klass, void *data) static void virtio_rng_initfn(Object *obj) { VirtIORngPCI *dev = VIRTIO_RNG_PCI(obj); - object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_RNG); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, (Object **)&dev->vdev.conf.rng, NULL); @@ -1503,13 +1504,14 @@ static const TypeInfo virtio_rng_pci_info = { /* virtio-pci-bus */ -static void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev) +static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, + VirtIOPCIProxy *dev) { DeviceState *qdev = DEVICE(dev); BusState *qbus; char virtio_bus_name[] = "virtio-bus"; - qbus_create_inplace((BusState *)bus, TYPE_VIRTIO_PCI_BUS, qdev, + qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_PCI_BUS, qdev, virtio_bus_name); qbus = BUS(bus); qbus->allow_hotplug = 1; diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c index bac8421a20..314e393520 100644 --- a/hw/virtio/virtio-rng.c +++ b/hw/virtio/virtio-rng.c @@ -129,8 +129,8 @@ static void check_rate_limit(void *opaque) 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 @@ static int virtio_rng_device_init(VirtIODevice *vdev) 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 @@ static int virtio_rng_device_exit(DeviceState *qdev) 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; diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c index 2e064bac81..36d38878ee 100644 --- a/hw/watchdog/wdt_i6300esb.c +++ b/hw/watchdog/wdt_i6300esb.c @@ -130,7 +130,7 @@ static void i6300esb_restart_timer(I6300State *d, int stage) 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 @@ static void i6300esb_disable_timer(I6300State *d) { i6300esb_debug("timer disabled\n"); - qemu_del_timer(d->timer); + timer_del(d->timer); } static void i6300esb_reset(DeviceState *dev) @@ -414,7 +414,7 @@ static int i6300esb_init(PCIDevice *dev) 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, diff --git a/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c index e97b4c3049..bc994a4c32 100644 --- a/hw/watchdog/wdt_ib700.c +++ b/hw/watchdog/wdt_ib700.c @@ -62,7 +62,7 @@ static void ib700_write_enable_reg(void *vp, uint32_t addr, uint32_t data) 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 @@ static void ib700_write_disable_reg(void *vp, uint32_t addr, uint32_t data) 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 @@ static void ib700_timer_expired(void *vp) 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 @@ static void wdt_ib700_realize(DeviceState *dev, Error **errp) 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 @@ static void wdt_ib700_reset(DeviceState *dev) ib700_debug("watchdog reset\n"); - qemu_del_timer(s->timer); + timer_del(s->timer); } static WatchdogTimerModel model = { diff --git a/hw/xtensa/pic_cpu.c b/hw/xtensa/pic_cpu.c index 7f015ff5ab..e2005bd981 100644 --- a/hw/xtensa/pic_cpu.c +++ b/hw/xtensa/pic_cpu.c @@ -52,11 +52,11 @@ void check_interrupts(CPUXtensaState *env) 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 @@ void xtensa_rearm_ccompare_timer(CPUXtensaState *env) } } 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 @@ static void xtensa_ccompare_cb(void *opaque) 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 @@ void xtensa_irq_init(CPUXtensaState *env) 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 5743bf1ba0..2efdf416cf 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -14,10 +14,12 @@ #ifndef QEMU_AIO_H #define QEMU_AIO_H +#include "qemu/typedefs.h" #include "qemu-common.h" #include "qemu/queue.h" #include "qemu/event_notifier.h" #include "qemu/thread.h" +#include "qemu/timer.h" typedef struct BlockDriverAIOCB BlockDriverAIOCB; typedef void BlockDriverCompletionFunc(void *opaque, int ret); @@ -42,7 +44,7 @@ typedef struct AioHandler AioHandler; typedef void QEMUBHFunc(void *opaque); typedef void IOHandler(void *opaque); -typedef struct AioContext { +struct AioContext { GSource source; /* The list of registered AIO handlers */ @@ -72,7 +74,10 @@ typedef struct AioContext { /* Thread pool for performing work and receiving completion callbacks */ struct ThreadPool *thread_pool; -} AioContext; + + /* TimerLists for calling timers - one per clock type */ + QEMUTimerListGroup tlg; +}; /** * aio_context_new: Allocate a new AioContext. @@ -241,4 +246,47 @@ void qemu_aio_set_fd_handler(int fd, 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 e45f2a0d56..8012e253c9 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -34,6 +34,7 @@ #include "monitor/monitor.h" #include "qemu/hbitmap.h" #include "block/snapshot.h" +#include "qemu/main-loop.h" #define BLOCK_FLAG_ENCRYPT 1 #define BLOCK_FLAG_COMPAT6 4 @@ -281,6 +282,9 @@ struct BlockDriverState { /* Whether the disk can expand beyond total_sectors */ int growable; + /* Whether produces zeros when read beyond eof */ + bool zero_beyond_eof; + /* the memory alignment required for the buffers handled by this driver */ int buffer_alignment; diff --git a/include/block/blockjob.h b/include/block/blockjob.h index c290d07bba..d530409ff5 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -141,7 +141,7 @@ void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, * Put the job to sleep (assuming that it wasn't canceled) for @ns * nanoseconds. Canceling the job will interrupt the wait immediately. */ -void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns); +void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns); /** * block_job_completed: diff --git a/include/block/coroutine.h b/include/block/coroutine.h index 1f2db3e8a4..4232569c53 100644 --- a/include/block/coroutine.h +++ b/include/block/coroutine.h @@ -16,6 +16,7 @@ #define QEMU_COROUTINE_H #include <stdbool.h> +#include "qemu/typedefs.h" #include "qemu/queue.h" #include "qemu/timer.h" @@ -212,7 +213,7 @@ void qemu_co_rwlock_unlock(CoRwlock *lock); * Note this function uses timers and hence only works when a main loop is in * use. See main-loop.h and do not use from qemu-tool programs. */ -void coroutine_fn co_sleep_ns(QEMUClock *clock, int64_t ns); +void coroutine_fn co_sleep_ns(QEMUClockType type, int64_t ns); /** * Yield until a file descriptor becomes readable diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 5920f73c90..beb41491b4 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -295,58 +295,42 @@ static inline void tb_add_jump(TranslationBlock *tb, int n, } } -/* The return address may point to the start of the next instruction. - Subtracting one gets us the call instruction itself. */ +/* GETRA is the true target of the return instruction that we'll execute, + defined here for simplicity of defining the follow-up macros. */ #if defined(CONFIG_TCG_INTERPRETER) extern uintptr_t tci_tb_ptr; -# define GETPC() tci_tb_ptr -#elif defined(__s390__) && !defined(__s390x__) -# define GETPC() \ - (((uintptr_t)__builtin_return_address(0) & 0x7fffffffUL) - 1) -#elif defined(__arm__) -/* Thumb return addresses have the low bit set, so we need to subtract two. - This is still safe in ARM mode because instructions are 4 bytes. */ -# define GETPC() ((uintptr_t)__builtin_return_address(0) - 2) +# define GETRA() tci_tb_ptr +#else +# define GETRA() \ + ((uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0))) +#endif + +/* The true return address will often point to a host insn that is part of + the next translated guest insn. Adjust the address backward to point to + the middle of the call insn. Subtracting one would do the job except for + several compressed mode architectures (arm, mips) which set the low bit + to indicate the compressed mode; subtracting two works around that. It + is also the case that there are no host isas that contain a call insn + smaller than 4 bytes, so we don't worry about special-casing this. */ +#if defined(CONFIG_TCG_INTERPRETER) +# define GETPC_ADJ 0 #else -# define GETPC() ((uintptr_t)__builtin_return_address(0) - 1) +# define GETPC_ADJ 2 #endif +#define GETPC() (GETRA() - GETPC_ADJ) + +/* The LDST optimizations splits code generation into fast and slow path. + In some implementations, we pass the "logical" return address manually; + in others, we must infer the logical return from the true return. */ #if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) -/* qemu_ld/st optimization split code generation to fast and slow path, thus, - it needs special handling for an MMU helper which is called from the slow - path, to get the fast path's pc without any additional argument. - It uses a tricky solution which embeds the fast path pc into the slow path. - - Code flow in slow path: - (1) pre-process - (2) call MMU helper - (3) jump to (5) - (4) fast path information (implementation specific) - (5) post-process (e.g. stack adjust) - (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)) -# 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)) +# if defined (_ARCH_PPC) && !defined (_ARCH_PPC64) +# define GETRA_LDST(RA) (*(int32_t *)((RA) - 4)) # elif defined(__arm__) /* We define two insns between the return address and the branch back to straight-line. Find and decode that branch insn. */ -# 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) +# define GETRA_LDST(RA) tcg_getra_ldst(RA) +static inline uintptr_t tcg_getra_ldst(uintptr_t ra) { int32_t b; ra += 8; /* skip the two insns */ @@ -354,31 +338,32 @@ static inline uintptr_t tcg_getpc_ldst(uintptr_t ra) b = (b << 8) >> (8 - 2); /* extract the displacement */ ra += 8; /* branches are relative to pc+8 */ ra += b; /* apply the displacement */ - ra -= 4; /* return a pointer into the current opcode, - 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) +# elif defined(__aarch64__) +# define GETRA_LDST(RA) tcg_getra_ldst(RA) +static inline uintptr_t tcg_getra_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 +#endif /* CONFIG_QEMU_LDST_OPTIMIZATION */ + +/* ??? Delete these once they are no longer used. */ bool is_tcg_gen_code(uintptr_t pc_ptr); -# define GETPC_EXT() (is_tcg_gen_code(GETRA()) ? GETPC_LDST() : GETPC()) +#ifdef GETRA_LDST +# define GETRA_EXT() tcg_getra_ext(GETRA()) +static inline uintptr_t tcg_getra_ext(uintptr_t ra) +{ + return is_tcg_gen_code(ra) ? GETRA_LDST(ra) : ra; +} #else -# define GETPC_EXT() GETPC() +# define GETRA_EXT() GETRA() #endif #if !defined(CONFIG_USER_ONLY) @@ -392,7 +377,10 @@ bool io_mem_write(struct MemoryRegion *mr, hwaddr addr, void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr); -#include "exec/softmmu_defs.h" +uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); +uint16_t helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); +uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); +uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); #define ACCESS_TYPE (NB_MMU_MODES + 1) #define MEMSUFFIX _code diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h index 4fc7b2981d..39a6b61e4f 100644 --- a/include/exec/gen-icount.h +++ b/include/exec/gen-icount.h @@ -39,12 +39,12 @@ static inline void gen_tb_start(void) static void gen_tb_end(TranslationBlock *tb, int num_insns) { gen_set_label(exitreq_label); - tcg_gen_exit_tb((tcg_target_long)tb + TB_EXIT_REQUESTED); + tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_REQUESTED); if (use_icount) { *icount_arg = num_insns; gen_set_label(icount_label); - tcg_gen_exit_tb((tcg_target_long)tb + TB_EXIT_ICOUNT_EXPIRED); + tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_ICOUNT_EXPIRED); } } diff --git a/include/exec/softmmu_defs.h b/include/exec/softmmu_defs.h deleted file mode 100644 index 1f25e33ce4..0000000000 --- a/include/exec/softmmu_defs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Software MMU support - * - * Declare helpers used by TCG for qemu_ld/st ops. - * - * Used by softmmu_exec.h, TCG targets and exec-all.h. - * - */ -#ifndef SOFTMMU_DEFS_H -#define SOFTMMU_DEFS_H - -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); - -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 diff --git a/include/exec/softmmu_exec.h b/include/exec/softmmu_exec.h index 3e4e886a30..6fde154527 100644 --- a/include/exec/softmmu_exec.h +++ b/include/exec/softmmu_exec.h @@ -19,7 +19,8 @@ #define ldul_executive ldl_executive #define ldul_supervisor ldl_supervisor -#include "exec/softmmu_defs.h" +/* The memory helpers for tcg-generated code need tcg_target_long etc. */ +#include "tcg.h" #define ACCESS_TYPE 0 #define MEMSUFFIX MMU_MODE0_SUFFIX diff --git a/include/exec/softmmu_template.h b/include/exec/softmmu_template.h index 8584902cbe..5bbc56afd5 100644 --- a/include/exec/softmmu_template.h +++ b/include/exec/softmmu_template.h @@ -28,24 +28,40 @@ #if DATA_SIZE == 8 #define SUFFIX q -#define USUFFIX q -#define DATA_TYPE uint64_t +#define LSUFFIX q +#define SDATA_TYPE int64_t #elif DATA_SIZE == 4 #define SUFFIX l -#define USUFFIX l -#define DATA_TYPE uint32_t +#define LSUFFIX l +#define SDATA_TYPE int32_t #elif DATA_SIZE == 2 #define SUFFIX w -#define USUFFIX uw -#define DATA_TYPE uint16_t +#define LSUFFIX uw +#define SDATA_TYPE int16_t #elif DATA_SIZE == 1 #define SUFFIX b -#define USUFFIX ub -#define DATA_TYPE uint8_t +#define LSUFFIX ub +#define SDATA_TYPE int8_t #else #error unsupported data size #endif +#define DATA_TYPE glue(u, SDATA_TYPE) + +/* For the benefit of TCG generated code, we want to avoid the complication + of ABI-specific return type promotion and always return a value extended + to the register size of the host. This is tcg_target_long, except in the + case of a 32-bit host and 64-bit data, and for that we always have + uint64_t. Don't bother with this widened value for SOFTMMU_CODE_ACCESS. */ +#if defined(SOFTMMU_CODE_ACCESS) || DATA_SIZE == 8 +# define WORD_TYPE DATA_TYPE +# define USUFFIX SUFFIX +#else +# define WORD_TYPE tcg_target_ulong +# define USUFFIX glue(u, SUFFIX) +# define SSUFFIX glue(s, SUFFIX) +#endif + #ifdef SOFTMMU_CODE_ACCESS #define READ_ACCESS_TYPE 2 #define ADDR_READ addr_code @@ -54,10 +70,6 @@ #define ADDR_READ addr_read #endif -static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, - target_ulong addr, - int mmu_idx, - uintptr_t retaddr); static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env, hwaddr physaddr, target_ulong addr, @@ -78,123 +90,105 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env, } /* handle all cases except unaligned access which span two pages */ -DATA_TYPE -glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, - int mmu_idx) +#ifdef SOFTMMU_CODE_ACCESS +static +#endif +WORD_TYPE +glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)(CPUArchState *env, + target_ulong addr, int mmu_idx, + uintptr_t retaddr) { - DATA_TYPE res; - int index; - target_ulong tlb_addr; - hwaddr ioaddr; - uintptr_t retaddr; + int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); + target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; + uintptr_t haddr; - /* test if there is match for unaligned or IO access */ - /* XXX: could done more in memory macro in a non portable way */ - index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - redo: - tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; - if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - if (tlb_addr & ~TARGET_PAGE_MASK) { - /* IO access */ - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; - retaddr = GETPC_EXT(); - ioaddr = env->iotlb[mmu_idx][index]; - res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - /* slow unaligned access (it spans two pages or IO) */ - do_unaligned_access: - retaddr = GETPC_EXT(); + /* Adjust the given return address. */ + retaddr -= GETPC_ADJ; + + /* If the TLB entry is for a different page, reload and try again. */ + if ((addr & TARGET_PAGE_MASK) + != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { #ifdef ALIGNED_ONLY + if ((addr & (DATA_SIZE - 1)) != 0) { do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); -#endif - res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(env, addr, - mmu_idx, retaddr); - } else { - /* unaligned/aligned access in the same page */ - uintptr_t addend; -#ifdef ALIGNED_ONLY - if ((addr & (DATA_SIZE - 1)) != 0) { - retaddr = GETPC_EXT(); - do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); - } -#endif - addend = env->tlb_table[mmu_idx][index].addend; - res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t) - (addr + addend)); } - } else { - /* the page is not in the TLB : fill it */ - retaddr = GETPC_EXT(); -#ifdef ALIGNED_ONLY - if ((addr & (DATA_SIZE - 1)) != 0) - do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); #endif tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); - goto redo; + tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; } - return res; -} -/* handle all unaligned cases */ -static DATA_TYPE -glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, - target_ulong addr, - int mmu_idx, - uintptr_t retaddr) -{ - DATA_TYPE res, res1, res2; - int index, shift; - hwaddr ioaddr; - target_ulong tlb_addr, addr1, addr2; + /* Handle an IO access. */ + if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) { + hwaddr ioaddr; + if ((addr & (DATA_SIZE - 1)) != 0) { + goto do_unaligned_access; + } + ioaddr = env->iotlb[mmu_idx][index]; + return glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr); + } - index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - redo: - tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; - if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - if (tlb_addr & ~TARGET_PAGE_MASK) { - /* IO access */ - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; - ioaddr = env->iotlb[mmu_idx][index]; - res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - do_unaligned_access: - /* slow unaligned access (it spans two pages) */ - addr1 = addr & ~(DATA_SIZE - 1); - addr2 = addr1 + DATA_SIZE; - res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(env, addr1, - mmu_idx, retaddr); - res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(env, addr2, - mmu_idx, retaddr); - shift = (addr & (DATA_SIZE - 1)) * 8; + /* Handle slow unaligned access (it spans two pages or IO). */ + if (DATA_SIZE > 1 + && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1 + >= TARGET_PAGE_SIZE)) { + target_ulong addr1, addr2; + DATA_TYPE res1, res2, res; + unsigned shift; + do_unaligned_access: +#ifdef ALIGNED_ONLY + do_unaligned_access(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); +#endif + addr1 = addr & ~(DATA_SIZE - 1); + addr2 = addr1 + DATA_SIZE; + /* Note the adjustment at the beginning of the function. + Undo that for the recursion. */ + res1 = glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX) + (env, addr1, mmu_idx, retaddr + GETPC_ADJ); + res2 = glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX) + (env, addr2, mmu_idx, retaddr + GETPC_ADJ); + shift = (addr & (DATA_SIZE - 1)) * 8; #ifdef TARGET_WORDS_BIGENDIAN - res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift)); + res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift)); #else - res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift)); + res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift)); #endif - res = (DATA_TYPE)res; - } else { - /* unaligned/aligned access in the same page */ - uintptr_t addend = env->tlb_table[mmu_idx][index].addend; - res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t) - (addr + addend)); - } - } else { - /* the page is not in the TLB : fill it */ - tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); - goto redo; + return res; } - 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; + /* Note that ldl_raw is defined with type "int". */ + return (DATA_TYPE) glue(glue(ld, LSUFFIX), _raw)((uint8_t *)haddr); +} + +DATA_TYPE +glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, + int mmu_idx) +{ + return glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX)(env, addr, mmu_idx, + GETRA_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); +/* Provide signed versions of the load routines as well. We can of course + avoid this for 64-bit data, or for 32-bit data on 32-bit host. */ +#if DATA_SIZE * 8 < TCG_TARGET_REG_BITS +WORD_TYPE +glue(glue(helper_ret_ld, SSUFFIX), MMUSUFFIX)(CPUArchState *env, + target_ulong addr, int mmu_idx, + uintptr_t retaddr) +{ + return (SDATA_TYPE) glue(glue(helper_ret_ld, USUFFIX), MMUSUFFIX) + (env, addr, mmu_idx, retaddr); +} +#endif static inline void glue(io_write, SUFFIX)(CPUArchState *env, hwaddr physaddr, @@ -214,107 +208,84 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env, io_mem_write(mr, physaddr, val, 1 << SHIFT); } -void glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, - target_ulong addr, DATA_TYPE val, - int mmu_idx) +void +glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, + target_ulong addr, DATA_TYPE val, + int mmu_idx, uintptr_t retaddr) { - hwaddr ioaddr; - target_ulong tlb_addr; - uintptr_t retaddr; - int index; + int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); + target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write; + uintptr_t haddr; - index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - redo: - tlb_addr = env->tlb_table[mmu_idx][index].addr_write; - if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - if (tlb_addr & ~TARGET_PAGE_MASK) { - /* IO access */ - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; - retaddr = GETPC_EXT(); - ioaddr = env->iotlb[mmu_idx][index]; - glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - do_unaligned_access: - retaddr = GETPC_EXT(); + /* Adjust the given return address. */ + retaddr -= GETPC_ADJ; + + /* If the TLB entry is for a different page, reload and try again. */ + if ((addr & TARGET_PAGE_MASK) + != (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { #ifdef ALIGNED_ONLY + if ((addr & (DATA_SIZE - 1)) != 0) { do_unaligned_access(env, addr, 1, mmu_idx, retaddr); -#endif - glue(glue(slow_st, SUFFIX), MMUSUFFIX)(env, addr, val, - mmu_idx, retaddr); - } else { - /* aligned/unaligned access in the same page */ - uintptr_t addend; -#ifdef ALIGNED_ONLY - if ((addr & (DATA_SIZE - 1)) != 0) { - retaddr = GETPC_EXT(); - do_unaligned_access(env, addr, 1, mmu_idx, retaddr); - } -#endif - addend = env->tlb_table[mmu_idx][index].addend; - glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t) - (addr + addend), val); } - } else { - /* the page is not in the TLB : fill it */ - retaddr = GETPC_EXT(); -#ifdef ALIGNED_ONLY - if ((addr & (DATA_SIZE - 1)) != 0) - do_unaligned_access(env, addr, 1, mmu_idx, retaddr); #endif tlb_fill(env, addr, 1, mmu_idx, retaddr); - goto redo; + tlb_addr = env->tlb_table[mmu_idx][index].addr_write; } -} -/* handles all unaligned cases */ -static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, - target_ulong addr, - DATA_TYPE val, - int mmu_idx, - uintptr_t retaddr) -{ - hwaddr ioaddr; - target_ulong tlb_addr; - int index, i; + /* Handle an IO access. */ + if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) { + hwaddr ioaddr; + if ((addr & (DATA_SIZE - 1)) != 0) { + goto do_unaligned_access; + } + ioaddr = env->iotlb[mmu_idx][index]; + glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr); + return; + } - index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - redo: - tlb_addr = env->tlb_table[mmu_idx][index].addr_write; - if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - if (tlb_addr & ~TARGET_PAGE_MASK) { - /* IO access */ - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; - ioaddr = env->iotlb[mmu_idx][index]; - glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - do_unaligned_access: - /* XXX: not efficient, but simple */ - /* Note: relies on the fact that tlb_fill() does not remove the - * previous page from the TLB cache. */ - for(i = DATA_SIZE - 1; i >= 0; i--) { + /* Handle slow unaligned access (it spans two pages or IO). */ + if (DATA_SIZE > 1 + && unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1 + >= TARGET_PAGE_SIZE)) { + int i; + do_unaligned_access: +#ifdef ALIGNED_ONLY + do_unaligned_access(env, addr, 1, mmu_idx, retaddr); +#endif + /* XXX: not efficient, but simple */ + /* Note: relies on the fact that tlb_fill() does not remove the + * previous page from the TLB cache. */ + for (i = DATA_SIZE - 1; i >= 0; i--) { #ifdef TARGET_WORDS_BIGENDIAN - glue(slow_stb, MMUSUFFIX)(env, addr + i, - val >> (((DATA_SIZE - 1) * 8) - (i * 8)), - mmu_idx, retaddr); + uint8_t val8 = val >> (((DATA_SIZE - 1) * 8) - (i * 8)); #else - glue(slow_stb, MMUSUFFIX)(env, addr + i, - val >> (i * 8), - mmu_idx, retaddr); + uint8_t val8 = val >> (i * 8); #endif - } - } else { - /* aligned/unaligned access in the same page */ - uintptr_t addend = env->tlb_table[mmu_idx][index].addend; - glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t) - (addr + addend), val); + /* Note the adjustment at the beginning of the function. + Undo that for the recursion. */ + glue(helper_ret_stb, MMUSUFFIX)(env, addr + i, val8, + mmu_idx, retaddr + GETPC_ADJ); } - } else { - /* the page is not in the TLB : fill it */ - tlb_fill(env, addr, 1, mmu_idx, retaddr); - goto redo; + return; + } + + /* Handle aligned access or unaligned access in the same page. */ +#ifdef ALIGNED_ONLY + if ((addr & (DATA_SIZE - 1)) != 0) { + do_unaligned_access(env, addr, 1, mmu_idx, retaddr); } +#endif + + haddr = addr + env->tlb_table[mmu_idx][index].addend; + glue(glue(st, SUFFIX), _raw)((uint8_t *)haddr, val); +} + +void +glue(glue(helper_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, target_ulong addr, + DATA_TYPE val, int mmu_idx) +{ + glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(env, addr, val, mmu_idx, + GETRA_EXT()); } #endif /* !defined(SOFTMMU_CODE_ACCESS) */ @@ -323,6 +294,10 @@ static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(CPUArchState *env, #undef SHIFT #undef DATA_TYPE #undef SUFFIX -#undef USUFFIX +#undef LSUFFIX #undef DATA_SIZE #undef ADDR_READ +#undef WORD_TYPE +#undef SDATA_TYPE +#undef USUFFIX +#undef SSUFFIX diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h index 635be7be10..51733d3390 100644 --- a/include/hw/acpi/acpi.h +++ b/include/hw/acpi/acpi.h @@ -136,7 +136,7 @@ void acpi_pm_tmr_reset(ACPIREGS *ar); #include "qemu/timer.h" static inline int64_t acpi_pm_tmr_get_clock(void) { - return muldiv64(qemu_get_clock_ns(vm_clock), PM_TIMER_FREQUENCY, + return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY, get_ticks_per_sec()); } diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h index 495bcf3a08..fa45a5b094 100644 --- a/include/hw/isa/isa.h +++ b/include/hw/isa/isa.h @@ -78,7 +78,7 @@ void isa_register_ioport(ISADevice *dev, MemoryRegion *io, uint16_t start); * @dev: the ISADevice against which these are registered; may be NULL. * @start: the base I/O port against which the portio->offset is applied. * @portio: the ports, sorted by offset. - * @opaque: passed into the old_portio callbacks. + * @opaque: passed into the portio callbacks. * @name: passed into memory_region_init_io. */ void isa_register_portio_list(ISADevice *dev, uint16_t start, diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h index 93f9511325..970b4a9e4a 100644 --- a/include/hw/pci-host/spapr.h +++ b/include/hw/pci-host/spapr.h @@ -43,8 +43,7 @@ typedef struct sPAPRPHBState { MemoryRegion memspace, iospace; hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size; - hwaddr msi_win_addr; - MemoryRegion memwindow, iowindow, msiwindow; + MemoryRegion memwindow, iowindow; uint32_t dma_liobn; uint64_t dma_window_start; @@ -73,7 +72,8 @@ typedef struct sPAPRPHBState { #define SPAPR_PCI_MMIO_WIN_SIZE 0x20000000 #define SPAPR_PCI_IO_WIN_OFF 0x80000000 #define SPAPR_PCI_IO_WIN_SIZE 0x10000 -#define SPAPR_PCI_MSI_WIN_OFF 0x90000000 + +#define SPAPR_PCI_MSI_WINDOW 0x40000000000ULL #define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL @@ -88,6 +88,8 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, uint32_t xics_phandle, void *fdt); +void spapr_pci_msi_init(sPAPREnvironment *spapr, hwaddr addr); + void spapr_pci_rtas_init(void); #endif /* __HW_SPAPR_PCI_H__ */ diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 2374aa95ba..37979aa723 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -348,7 +348,7 @@ typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev, bool pci_bus_is_express(PCIBus *bus); bool pci_bus_is_root(PCIBus *bus); -void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent, +void pci_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, const char *name, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 9fc197286c..e37b41983c 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -13,6 +13,8 @@ struct sPAPRNVRAM; typedef struct sPAPREnvironment { struct VIOsPAPRBus *vio_bus; QLIST_HEAD(, sPAPRPHBState) phbs; + hwaddr msi_win_addr; + MemoryRegion msiwindow; struct sPAPRNVRAM *nvram; XICSState *icp; @@ -109,6 +111,15 @@ typedef struct sPAPREnvironment { #define H_NOT_ENOUGH_RESOURCES -44 #define H_R_STATE -45 #define H_RESCINDEND -46 +#define H_P2 -55 +#define H_P3 -56 +#define H_P4 -57 +#define H_P5 -58 +#define H_P6 -59 +#define H_P7 -60 +#define H_P8 -61 +#define H_P9 -62 +#define H_UNSUPPORTED_FLAG -256 #define H_MULTI_THREADS_ACTIVE -9005 @@ -143,6 +154,11 @@ typedef struct sPAPREnvironment { #define H_PP1 (1ULL<<(63-62)) #define H_PP2 (1ULL<<(63-63)) +/* H_SET_MODE flags */ +#define H_SET_MODE_ENDIAN 4 +#define H_SET_MODE_ENDIAN_BIG 0 +#define H_SET_MODE_ENDIAN_LITTLE 1 + /* VASI States */ #define H_VASI_INVALID 0 #define H_VASI_ENABLED 1 @@ -267,7 +283,8 @@ typedef struct sPAPREnvironment { #define H_GET_EM_PARMS 0x2B8 #define H_SET_MPP 0x2D0 #define H_GET_MPP 0x2D4 -#define MAX_HCALL_OPCODE H_GET_MPP +#define H_SET_MODE 0x31C +#define MAX_HCALL_OPCODE H_SET_MODE /* The hcalls above are standardized in PAPR and implemented by pHyp * as well. @@ -303,7 +320,7 @@ target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, target_ulong *args); int spapr_allocate_irq(int hint, bool lsi); -int spapr_allocate_irq_block(int num, bool lsi); +int spapr_allocate_irq_block(int num, bool lsi, bool msi); static inline int spapr_allocate_msi(int hint) { diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 46972f4961..a62f231eb9 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -264,7 +264,7 @@ DeviceState *qdev_find_recursive(BusState *bus, const char *id); typedef int (qbus_walkerfn)(BusState *bus, void *opaque); typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque); -void qbus_create_inplace(void *bus, const char *typename, +void qbus_create_inplace(void *bus, size_t size, const char *typename, DeviceState *parent, const char *name); BusState *qbus_create(const char *typename, DeviceState *parent, const char *name); /* Returns > 0 if either devfn or busfn skip walk somewhere in cursion, diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 87865313eb..1b6651054a 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -152,8 +152,8 @@ struct SCSIBus { const SCSIBusInfo *info; }; -void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info, - const char *bus_name); +void scsi_bus_new(SCSIBus *bus, size_t bus_size, DeviceState *host, + const SCSIBusInfo *info, const char *bus_name); static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) { diff --git a/include/hw/usb.h b/include/hw/usb.h index 901b0da8b0..1b8acba6f6 100644 --- a/include/hw/usb.h +++ b/include/hw/usb.h @@ -496,7 +496,8 @@ struct USBBusOps { void (*wakeup_endpoint)(USBBus *bus, USBEndpoint *ep, unsigned int stream); }; -void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host); +void usb_bus_new(USBBus *bus, size_t bus_size, + USBBusOps *ops, DeviceState *host); USBBus *usb_bus_find(int busnr); void usb_legacy_register(const char *typename, const char *usbdevice_name, USBDevice *(*usbdevice_init)(USBBus *bus, diff --git a/include/monitor/readline.h b/include/monitor/readline.h index fc9806ecf1..0faf6e1db7 100644 --- a/include/monitor/readline.h +++ b/include/monitor/readline.h @@ -8,7 +8,8 @@ #define READLINE_MAX_COMPLETIONS 256 typedef void ReadLineFunc(Monitor *mon, const char *str, void *opaque); -typedef void ReadLineCompletionFunc(const char *cmdline); +typedef void ReadLineCompletionFunc(Monitor *mon, + const char *cmdline); typedef struct ReadLineState { char cmd_buf[READLINE_CMD_BUF_SIZE + 1]; diff --git a/include/qapi/opts-visitor.h b/include/qapi/opts-visitor.h index 5939eeebc7..fd48c14ec8 100644 --- a/include/qapi/opts-visitor.h +++ b/include/qapi/opts-visitor.h @@ -16,6 +16,12 @@ #include "qapi/visitor.h" #include "qemu/option.h" +/* Inclusive upper bound on the size of any flattened range. This is a safety + * (= anti-annoyance) measure; wrong ranges should not cause long startup + * delays nor exhaust virtual memory. + */ +#define OPTS_VISITOR_RANGE_MAX 65536 + typedef struct OptsVisitor OptsVisitor; /* Contrarily to qemu-option.c::parse_option_number(), OptsVisitor's "int" diff --git a/include/qemu/ratelimit.h b/include/qemu/ratelimit.h index d1610f135b..d413a4a696 100644 --- a/include/qemu/ratelimit.h +++ b/include/qemu/ratelimit.h @@ -23,7 +23,7 @@ typedef struct { static inline int64_t ratelimit_calculate_delay(RateLimit *limit, uint64_t n) { - int64_t now = qemu_get_clock_ns(rt_clock); + int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); if (limit->next_slice_time < now) { limit->next_slice_time = now + limit->slice_ns; diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 9dd206ce7f..e4934dd61b 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -1,8 +1,8 @@ #ifndef QEMU_TIMER_H #define QEMU_TIMER_H +#include "qemu/typedefs.h" #include "qemu-common.h" -#include "qemu/main-loop.h" #include "qemu/notify.h" /* timers */ @@ -11,80 +11,643 @@ #define SCALE_US 1000 #define SCALE_NS 1 -typedef struct QEMUClock QEMUClock; +/** + * QEMUClockType: + * + * The following clock types are available: + * + * @QEMU_CLOCK_REALTIME: Real time clock + * + * The real time clock should be used only for stuff which does not + * change the virtual machine state, as it is run even if the virtual + * machine is stopped. The real time clock has a frequency of 1000 + * Hz. + * + * @QEMU_CLOCK_VIRTUAL: virtual clock + * + * The virtual clock is only run during the emulation. It is stopped + * when the virtual machine is stopped. Virtual timers use a high + * precision clock, usually cpu cycles (use ticks_per_sec). + * + * @QEMU_CLOCK_HOST: host clock + * + * The host clock should be use for device models that emulate accurate + * real time sources. It will continue to run when the virtual machine + * is suspended, and it will reflect system time changes the host may + * undergo (e.g. due to NTP). The host clock has the same precision as + * the virtual clock. + */ + +typedef enum { + QEMU_CLOCK_REALTIME = 0, + QEMU_CLOCK_VIRTUAL = 1, + QEMU_CLOCK_HOST = 2, + QEMU_CLOCK_MAX +} QEMUClockType; + +typedef struct QEMUTimerList QEMUTimerList; + +struct QEMUTimerListGroup { + QEMUTimerList *tl[QEMU_CLOCK_MAX]; +}; + typedef void QEMUTimerCB(void *opaque); +typedef void QEMUTimerListNotifyCB(void *opaque); + +struct QEMUTimer { + int64_t expire_time; /* in nanoseconds */ + QEMUTimerList *timer_list; + QEMUTimerCB *cb; + void *opaque; + QEMUTimer *next; + int scale; +}; + +extern QEMUTimerListGroup main_loop_tlg; + +/* + * QEMUClockType + */ + +/* + * qemu_clock_get_ns; + * @type: the clock type + * + * Get the nanosecond value of a clock with + * type @type + * + * Returns: the clock value in nanoseconds + */ +int64_t qemu_clock_get_ns(QEMUClockType type); + +/** + * qemu_clock_get_ms; + * @type: the clock type + * + * Get the millisecond value of a clock with + * type @type + * + * Returns: the clock value in milliseconds + */ +static inline int64_t qemu_clock_get_ms(QEMUClockType type) +{ + return qemu_clock_get_ns(type) / SCALE_MS; +} + +/** + * qemu_clock_get_us; + * @type: the clock type + * + * Get the microsecond value of a clock with + * type @type + * + * Returns: the clock value in microseconds + */ +static inline int64_t qemu_clock_get_us(QEMUClockType type) +{ + return qemu_clock_get_ns(type) / SCALE_US; +} + +/** + * qemu_clock_has_timers: + * @type: the clock type + * + * Determines whether a clock's default timer list + * has timers attached + * + * Returns: true if the clock's default timer list + * has timers attached + */ +bool qemu_clock_has_timers(QEMUClockType type); + +/** + * qemu_clock_expired: + * @type: the clock type + * + * Determines whether a clock's default timer list + * has an expired clock. + * + * Returns: true if the clock's default timer list has + * an expired timer + */ +bool qemu_clock_expired(QEMUClockType type); + +/** + * qemu_clock_use_for_deadline: + * @type: the clock type + * + * Determine whether a clock should be used for deadline + * calculations. Some clocks, for instance vm_clock with + * use_icount set, do not count in nanoseconds. Such clocks + * are not used for deadline calculations, and are presumed + * to interrupt any poll using qemu_notify/aio_notify + * etc. + * + * Returns: true if the clock runs in nanoseconds and + * should be used for a deadline. + */ +bool qemu_clock_use_for_deadline(QEMUClockType type); + +/** + * qemu_clock_deadline_ns_all: + * @type: the clock type + * + * Calculate the deadline across all timer lists associated + * with a clock (as opposed to just the default one) + * in nanoseconds, or -1 if no timer is set to expire. + * + * Returns: time until expiry in nanoseconds or -1 + */ +int64_t qemu_clock_deadline_ns_all(QEMUClockType type); + +/** + * qemu_clock_get_main_loop_timerlist: + * @type: the clock type + * + * Return the default timer list assocatiated with a clock. + * + * Returns: the default timer list + */ +QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type); -/* The real time clock should be used only for stuff which does not - change the virtual machine state, as it is run even if the virtual - machine is stopped. The real time clock has a frequency of 1000 - Hz. */ -extern QEMUClock *rt_clock; - -/* The virtual clock is only run during the emulation. It is stopped - when the virtual machine is stopped. Virtual timers use a high - precision clock, usually cpu cycles (use ticks_per_sec). */ -extern QEMUClock *vm_clock; - -/* The host clock should be use for device models that emulate accurate - real time sources. It will continue to run when the virtual machine - is suspended, and it will reflect system time changes the host may - undergo (e.g. due to NTP). The host clock has the same precision as - the virtual clock. */ -extern QEMUClock *host_clock; - -int64_t qemu_get_clock_ns(QEMUClock *clock); -int64_t qemu_clock_has_timers(QEMUClock *clock); -int64_t qemu_clock_expired(QEMUClock *clock); -int64_t qemu_clock_deadline(QEMUClock *clock); -void qemu_clock_enable(QEMUClock *clock, bool enabled); -void qemu_clock_warp(QEMUClock *clock); - -void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier); -void qemu_unregister_clock_reset_notifier(QEMUClock *clock, +/** + * qemu_clock_nofify: + * @type: the clock type + * + * Call the notifier callback connected with the default timer + * list linked to the clock, or qemu_notify() if none. + */ +void qemu_clock_notify(QEMUClockType type); + +/** + * qemu_clock_enable: + * @type: the clock type + * @enabled: true to enable, false to disable + * + * Enable or disable a clock + */ +void qemu_clock_enable(QEMUClockType type, bool enabled); + +/** + * qemu_clock_warp: + * @type: the clock type + * + * Warp a clock to a new value + */ +void qemu_clock_warp(QEMUClockType type); + +/** + * qemu_clock_register_reset_notifier: + * @type: the clock type + * @notifier: the notifier function + * + * Register a notifier function to call when the clock + * concerned is reset. + */ +void qemu_clock_register_reset_notifier(QEMUClockType type, + Notifier *notifier); + +/** + * qemu_clock_unregister_reset_notifier: + * @type: the clock type + * @notifier: the notifier function + * + * Unregister a notifier function to call when the clock + * concerned is reset. + */ +void qemu_clock_unregister_reset_notifier(QEMUClockType type, Notifier *notifier); -QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale, - QEMUTimerCB *cb, void *opaque); -void qemu_free_timer(QEMUTimer *ts); -void qemu_del_timer(QEMUTimer *ts); -void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time); -void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time); -bool qemu_timer_pending(QEMUTimer *ts); -bool qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time); -uint64_t qemu_timer_expire_time_ns(QEMUTimer *ts); - -void qemu_run_timers(QEMUClock *clock); -void qemu_run_all_timers(void); -void configure_alarms(char const *opt); -void init_clocks(void); -int init_timer_alarm(void); +/** + * qemu_clock_run_timers: + * @type: clock on which to operate + * + * Run all the timers associated with the default timer list + * of a clock. + * + * Returns: true if any timer ran. + */ +bool qemu_clock_run_timers(QEMUClockType type); -int64_t cpu_get_ticks(void); -void cpu_enable_ticks(void); -void cpu_disable_ticks(void); +/** + * qemu_clock_run_all_timers: + * + * Run all the timers associated with the default timer list + * of every clock. + * + * Returns: true if any timer ran. + */ +bool qemu_clock_run_all_timers(void); + +/* + * QEMUTimerList + */ + +/** + * timerlist_new: + * @type: the clock type to associate with the timerlist + * @cb: the callback to call on notification + * @opaque: the opaque pointer to pass to the callback + * + * Create a new timerlist associated with the clock of + * type @type. + * + * Returns: a pointer to the QEMUTimerList created + */ +QEMUTimerList *timerlist_new(QEMUClockType type, + QEMUTimerListNotifyCB *cb, void *opaque); + +/** + * timerlist_free: + * @timer_list: the timer list to free + * + * Frees a timer_list. It must have no active timers. + */ +void timerlist_free(QEMUTimerList *timer_list); + +/** + * timerlist_has_timers: + * @timer_list: the timer list to operate on + * + * Determine whether a timer list has active timers + * + * Returns: true if the timer list has timers. + */ +bool timerlist_has_timers(QEMUTimerList *timer_list); + +/** + * timerlist_expired: + * @timer_list: the timer list to operate on + * + * Determine whether a timer list has any timers which + * are expired. + * + * Returns: true if the timer list has timers which + * have expired. + */ +bool timerlist_expired(QEMUTimerList *timer_list); + +/** + * timerlist_deadline_ns: + * @timer_list: the timer list to operate on + * + * Determine the deadline for a timer_list, i.e. + * the number of nanoseconds until the first timer + * expires. Return -1 if there are no timers. + * + * Returns: the number of nanoseconds until the earliest + * timer expires -1 if none + */ +int64_t timerlist_deadline_ns(QEMUTimerList *timer_list); + +/** + * timerlist_get_clock: + * @timer_list: the timer list to operate on + * + * Determine the clock type associated with a timer list. + * + * Returns: the clock type associated with the + * timer list. + */ +QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list); + +/** + * timerlist_run_timers: + * @timer_list: the timer list to use + * + * Call all expired timers associated with the timer list. + * + * Returns: true if any timer expired + */ +bool timerlist_run_timers(QEMUTimerList *timer_list); + +/** + * timerlist_notify: + * @timer_list: the timer list to use + * + * call the notifier callback associated with the timer list. + */ +void timerlist_notify(QEMUTimerList *timer_list); + +/* + * QEMUTimerListGroup + */ + +/** + * timerlistgroup_init: + * @tlg: the timer list group + * @cb: the callback to call when a notify is required + * @opaque: the opaque pointer to be passed to the callback. + * + * Initialise a timer list group. This must already be + * allocated in memory and zeroed. The notifier callback is + * called whenever a clock in the timer list group is + * reenabled or whenever a timer associated with any timer + * list is modified. If @cb is specified as null, qemu_notify() + * is used instead. + */ +void timerlistgroup_init(QEMUTimerListGroup *tlg, + QEMUTimerListNotifyCB *cb, void *opaque); + +/** + * timerlistgroup_deinit: + * @tlg: the timer list group + * + * Deinitialise a timer list group. This must already be + * initialised. Note the memory is not freed. + */ +void timerlistgroup_deinit(QEMUTimerListGroup *tlg); + +/** + * timerlistgroup_run_timers: + * @tlg: the timer list group + * + * Run the timers associated with a timer list group. + * This will run timers on multiple clocks. + * + * Returns: true if any timer callback ran + */ +bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg); + +/** + * timerlistgroup_deadline_ns: + * @tlg: the timer list group + * + * Determine the deadline of the soonest timer to + * expire associated with any timer list linked to + * the timer list group. Only clocks suitable for + * deadline calculation are included. + * + * Returns: the deadline in nanoseconds or -1 if no + * timers are to expire. + */ +int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg); + +/* + * QEMUTimer + */ + +/** + * timer_init: + * @ts: the timer to be initialised + * @timer_list: the timer list to attach the timer to + * @scale: the scale value for the tiemr + * @cb: the callback to be called when the timer expires + * @opaque: the opaque pointer to be passed to the callback + * + * Initialise a new timer and associate it with @timer_list. + * The caller is responsible for allocating the memory. + * + * You need not call an explicit deinit call. Simply make + * sure it is not on a list with timer_del. + */ +void timer_init(QEMUTimer *ts, + QEMUTimerList *timer_list, int scale, + QEMUTimerCB *cb, void *opaque); + +/** + * timer_new_tl: + * @timer_list: the timer list to attach the timer to + * @scale: the scale value for the tiemr + * @cb: the callback to be called when the timer expires + * @opaque: the opaque pointer to be passed to the callback + * + * Creeate a new timer and associate it with @timer_list. + * The memory is allocated by the function. + * + * This is not the preferred interface unless you know you + * are going to call timer_free. Use timer_init instead. + * + * Returns: a pointer to the timer + */ +static inline QEMUTimer *timer_new_tl(QEMUTimerList *timer_list, + int scale, + QEMUTimerCB *cb, + void *opaque) +{ + QEMUTimer *ts = g_malloc0(sizeof(QEMUTimer)); + timer_init(ts, timer_list, scale, cb, opaque); + return ts; +} -static inline QEMUTimer *qemu_new_timer_ns(QEMUClock *clock, QEMUTimerCB *cb, - void *opaque) +/** + * timer_new: + * @type: the clock type to use + * @scale: the scale value for the tiemr + * @cb: the callback to be called when the timer expires + * @opaque: the opaque pointer to be passed to the callback + * + * Creeate a new timer and associate it with the default + * timer list for the clock type @type. + * + * Returns: a pointer to the timer + */ +static inline QEMUTimer *timer_new(QEMUClockType type, int scale, + QEMUTimerCB *cb, void *opaque) { - return qemu_new_timer(clock, SCALE_NS, cb, opaque); + return timer_new_tl(main_loop_tlg.tl[type], scale, cb, opaque); } -static inline QEMUTimer *qemu_new_timer_ms(QEMUClock *clock, QEMUTimerCB *cb, - void *opaque) +/** + * timer_new_ns: + * @clock: the clock to associate with the timer + * @callback: the callback to call when the timer expires + * @opaque: the opaque pointer to pass to the callback + * + * Create a new timer with nanosecond scale on the default timer list + * associated with the clock. + * + * Returns: a pointer to the newly created timer + */ +static inline QEMUTimer *timer_new_ns(QEMUClockType type, QEMUTimerCB *cb, + void *opaque) { - return qemu_new_timer(clock, SCALE_MS, cb, opaque); + return timer_new(type, SCALE_NS, cb, opaque); } -static inline int64_t qemu_get_clock_ms(QEMUClock *clock) +/** + * timer_new_us: + * @clock: the clock to associate with the timer + * @callback: the callback to call when the timer expires + * @opaque: the opaque pointer to pass to the callback + * + * Create a new timer with microsecond scale on the default timer list + * associated with the clock. + * + * Returns: a pointer to the newly created timer + */ +static inline QEMUTimer *timer_new_us(QEMUClockType type, QEMUTimerCB *cb, + void *opaque) { - return qemu_get_clock_ns(clock) / SCALE_MS; + return timer_new(type, SCALE_US, cb, opaque); } +/** + * timer_new_ms: + * @clock: the clock to associate with the timer + * @callback: the callback to call when the timer expires + * @opaque: the opaque pointer to pass to the callback + * + * Create a new timer with millisecond scale on the default timer list + * associated with the clock. + * + * Returns: a pointer to the newly created timer + */ +static inline QEMUTimer *timer_new_ms(QEMUClockType type, QEMUTimerCB *cb, + void *opaque) +{ + return timer_new(type, SCALE_MS, cb, opaque); +} + +/** + * timer_free: + * @ts: the timer + * + * Free a timer (it must not be on the active list) + */ +void timer_free(QEMUTimer *ts); + +/** + * timer_del: + * @ts: the timer + * + * Delete a timer from the active list. + */ +void timer_del(QEMUTimer *ts); + +/** + * timer_mod_ns: + * @ts: the timer + * @expire_time: the expiry time in nanoseconds + * + * Modify a timer to expire at @expire_time + */ +void timer_mod_ns(QEMUTimer *ts, int64_t expire_time); + +/** + * timer_mod: + * @ts: the timer + * @expire_time: the expire time in the units associated with the timer + * + * Modify a timer to expiry at @expire_time, taking into + * account the scale associated with the timer. + */ +void timer_mod(QEMUTimer *ts, int64_t expire_timer); + +/** + * timer_pending: + * @ts: the timer + * + * Determines whether a timer is pending (i.e. is on the + * active list of timers, whether or not it has not yet expired). + * + * Returns: true if the timer is pending + */ +bool timer_pending(QEMUTimer *ts); + +/** + * timer_expired: + * @ts: the timer + * + * Determines whether a timer has expired. + * + * Returns: true if the timer has expired + */ +bool timer_expired(QEMUTimer *timer_head, int64_t current_time); + +/** + * timer_expire_time_ns: + * @ts: the timer + * + * Determine the expiry time of a timer + * + * Returns: the expiry time in nanoseconds + */ +uint64_t timer_expire_time_ns(QEMUTimer *ts); + +/** + * timer_get: + * @f: the file + * @ts: the timer + * + * Read a timer @ts from a file @f + */ +void timer_get(QEMUFile *f, QEMUTimer *ts); + +/** + * timer_put: + * @f: the file + * @ts: the timer + */ +void timer_put(QEMUFile *f, QEMUTimer *ts); + +/* + * General utility functions + */ + +/** + * qemu_timeout_ns_to_ms: + * @ns: nanosecond timeout value + * + * Convert a nanosecond timeout value (or -1) to + * a millisecond value (or -1), always rounding up. + * + * Returns: millisecond timeout value + */ +int qemu_timeout_ns_to_ms(int64_t ns); + +/** + * qemu_poll_ns: + * @fds: Array of file descriptors + * @nfds: number of file descriptors + * @timeout: timeout in nanoseconds + * + * Perform a poll like g_poll but with a timeout in nanoseconds. + * See g_poll documentation for further details. + * + * Returns: number of fds ready + */ +int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout); + +/** + * qemu_soonest_timeout: + * @timeout1: first timeout in nanoseconds (or -1 for infinite) + * @timeout2: second timeout in nanoseconds (or -1 for infinite) + * + * Calculates the soonest of two timeout values. -1 means infinite, which + * is later than any other value. + * + * Returns: soonest timeout value in nanoseconds (or -1 for infinite) + */ +static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2) +{ + /* we can abuse the fact that -1 (which means infinite) is a maximal + * value when cast to unsigned. As this is disgusting, it's kept in + * one inline function. + */ + return ((uint64_t) timeout1 < (uint64_t) timeout2) ? timeout1 : timeout2; +} + +/** + * initclocks: + * + * Initialise the clock & timer infrastructure + */ +void init_clocks(void); + +int64_t cpu_get_ticks(void); +void cpu_enable_ticks(void); +void cpu_disable_ticks(void); + static inline int64_t get_ticks_per_sec(void) { return 1000000000LL; } +/* + * Low level clock functions + */ + /* real time host monotonic timer */ static inline int64_t get_clock_realtime(void) { @@ -128,9 +691,6 @@ static inline int64_t get_clock(void) } #endif -void qemu_get_timer(QEMUFile *f, QEMUTimer *ts); -void qemu_put_timer(QEMUFile *f, QEMUTimer *ts); - /* icount */ int64_t cpu_get_icount(void); int64_t cpu_get_clock(void); diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index ac9f8d41a3..3205540059 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -4,9 +4,12 @@ /* A load of opaque types so that device init declarations don't have to pull in all the real definitions. */ typedef struct QEMUTimer QEMUTimer; +typedef struct QEMUTimerListGroup QEMUTimerListGroup; typedef struct QEMUFile QEMUFile; typedef struct QEMUBH QEMUBH; +typedef struct AioContext AioContext; + struct Monitor; typedef struct Monitor Monitor; typedef struct MigrationParams MigrationParams; diff --git a/include/qom/object.h b/include/qom/object.h index 9b69065b7a..1a7b71aba5 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -249,7 +249,7 @@ typedef struct InterfaceInfo InterfaceInfo; * MyClass parent_class; * * MyDoSomething parent_do_something; - * } MyClass; + * } DerivedClass; * * static void derived_do_something(MyState *obj) * { @@ -585,25 +585,27 @@ Object *object_new_with_type(Type type); /** * object_initialize_with_type: - * @obj: A pointer to the memory to be used for the object. + * @data: A pointer to the memory to be used for the object. + * @size: The maximum size available at @data for the object. * @type: The type of the object to instantiate. * * This function will initialize an object. The memory for the object should * have already been allocated. The returned object has a reference count of 1, * and will be finalized when the last reference is dropped. */ -void object_initialize_with_type(void *data, Type type); +void object_initialize_with_type(void *data, size_t size, Type type); /** * object_initialize: * @obj: A pointer to the memory to be used for the object. + * @size: The maximum size available at @obj for the object. * @typename: The name of the type of the object to instantiate. * * This function will initialize an object. The memory for the object should * have already been allocated. The returned object has a reference count of 1, * and will be finalized when the last reference is dropped. */ -void object_initialize(void *obj, const char *typename); +void object_initialize(void *obj, size_t size, const char *typename); /** * object_dynamic_cast: diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index de74411f41..8e7668524b 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -309,7 +309,8 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg); int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg); void kvm_irqchip_release_virq(KVMState *s, int virq); -int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq); +int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, + EventNotifier *rn, int virq); int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq); void kvm_pc_gsi_handler(void *opaque, int n, int level); void kvm_pc_setup_irq_routing(bool pci_enabled); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index d7a77b6488..b1aa059102 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -124,7 +124,7 @@ extern int boot_menu; extern uint8_t *boot_splash_filedata; extern size_t boot_splash_filedata_size; extern uint8_t qemu_extra_params_fw[2]; -extern QEMUClock *rtc_clock; +extern QEMUClockType rtc_clock; #define MAX_NODES 64 #define MAX_CPUMASK_BITS 255 @@ -1230,7 +1230,8 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) return kvm_update_routing_entry(s, &kroute); } -static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign) +static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int rfd, int virq, + bool assign) { struct kvm_irqfd irqfd = { .fd = fd, @@ -1238,6 +1239,11 @@ static int kvm_irqchip_assign_irqfd(KVMState *s, int fd, int virq, bool assign) .flags = assign ? 0 : KVM_IRQFD_FLAG_DEASSIGN, }; + if (rfd != -1) { + irqfd.flags |= KVM_IRQFD_FLAG_RESAMPLE; + irqfd.resamplefd = rfd; + } + if (!kvm_irqfds_enabled()) { return -ENOSYS; } @@ -1276,14 +1282,17 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) } #endif /* !KVM_CAP_IRQ_ROUTING */ -int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq) +int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, + EventNotifier *rn, int virq) { - return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), virq, true); + return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), + rn ? event_notifier_get_fd(rn) : -1, virq, true); } int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq) { - return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), virq, false); + return kvm_irqchip_assign_irqfd(s, event_notifier_get_fd(n), -1, virq, + false); } static int kvm_irqchip_create(KVMState *s) @@ -1391,6 +1400,13 @@ int kvm_init(void) goto err; } + if (max_cpus > max_vcpus) { + ret = -EINVAL; + fprintf(stderr, "Number of hotpluggable cpus requested (%d) exceeds max cpus " + "supported by KVM (%d)\n", max_cpus, max_vcpus); + goto err; + } + s->vmfd = kvm_ioctl(s, KVM_CREATE_VM, 0); if (s->vmfd < 0) { #ifdef TARGET_S390X @@ -1499,32 +1515,8 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size, uint8_t *ptr = data; for (i = 0; i < count; i++) { - if (direction == KVM_EXIT_IO_IN) { - switch (size) { - case 1: - stb_p(ptr, cpu_inb(port)); - break; - case 2: - stw_p(ptr, cpu_inw(port)); - break; - case 4: - stl_p(ptr, cpu_inl(port)); - break; - } - } else { - switch (size) { - case 1: - cpu_outb(port, ldub_p(ptr)); - break; - case 2: - cpu_outw(port, lduw_p(ptr)); - break; - case 4: - cpu_outl(port, ldl_p(ptr)); - break; - } - } - + address_space_rw(&address_space_io, port, ptr, size, + direction == KVM_EXIT_IO_OUT); ptr += size; } } diff --git a/kvm-stub.c b/kvm-stub.c index 771360b3ca..548f471c17 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -135,7 +135,8 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) return -ENOSYS; } -int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, int virq) +int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n, + EventNotifier *rn, int virq) { return -ENOSYS; } diff --git a/main-loop.c b/main-loop.c index 2d9774ef75..1c38ea2b93 100644 --- a/main-loop.c +++ b/main-loop.c @@ -131,10 +131,6 @@ int qemu_init_main_loop(void) 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 max_priority; 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 @@ static void glib_pollfds_fill(uint32_t *cur_timeout) 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 @@ static void glib_pollfds_poll(void) #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 @@ static int os_host_main_loop_wait(uint32_t timeout) * 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 @@ static int os_host_main_loop_wait(uint32_t timeout) 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 void pollfds_poll(GArray *pollfds, int nfds, fd_set *rfds, } } -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 @@ static int os_host_main_loop_wait(uint32_t timeout) 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 @@ static int os_host_main_loop_wait(uint32_t timeout) 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 main_loop_wait(int nonblocking) { int ret; uint32_t timeout = UINT32_MAX; + int64_t timeout_ns; if (nonblocking) { timeout = 0; @@ -462,13 +470,24 @@ int main_loop_wait(int nonblocking) 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; } diff --git a/migration-exec.c b/migration-exec.c index deab4e378e..479024752f 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 3d4613cbaf..d2e523af74 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-tcp.c b/migration-tcp.c index b20ee58f55..782572de82 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 94b7022fc8..651fc5b707 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 1402fa7680..200d404547 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 @@ MigrationInfo *qmp_query_migrate(Error **errp) 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; @@ -375,7 +376,7 @@ static MigrationState *migrate_init(const MigrationParams *params) 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; } @@ -544,8 +545,8 @@ int64_t migrate_xbzrle_cache_size(void) 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; @@ -554,7 +555,7 @@ static void *migration_thread(void *opaque) 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"); @@ -574,7 +575,7 @@ static void *migration_thread(void *opaque) 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(); @@ -601,7 +602,7 @@ static void *migration_thread(void *opaque) 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; @@ -632,7 +633,7 @@ static void *migration_thread(void *opaque) 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); @@ -83,6 +83,7 @@ * 'F' filename * 'B' block device name * 's' string (accept optional quote) + * 'S' it just appends the rest of the string (accept optional quote) * 'O' option string of the form NAME=VALUE,... * parsed according to QemuOptsList given by its name * Example: 'device:O' uses qemu_device_opts. @@ -195,6 +196,7 @@ struct Monitor { CPUState *mon_cpu; BlockDriverCompletionFunc *password_completion_cb; void *password_opaque; + mon_cmd_t *cmd_table; QError *error; QLIST_HEAD(,mon_fd_t) fds; QLIST_ENTRY(Monitor) entry; @@ -537,7 +539,7 @@ monitor_protocol_event_queue(MonitorEvent event, 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 +566,7 @@ monitor_protocol_event_queue(MonitorEvent event, 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 +586,7 @@ monitor_protocol_event_queue(MonitorEvent event, 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 +624,7 @@ monitor_protocol_event_throttle(MonitorEvent event, 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); @@ -683,14 +685,26 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params, static void handle_user_command(Monitor *mon, const char *cmdline); +static void monitor_data_init(Monitor *mon) +{ + memset(mon, 0, sizeof(Monitor)); + mon->outbuf = qstring_new(); + /* Use *mon_cmds by default. */ + mon->cmd_table = mon_cmds; +} + +static void monitor_data_destroy(Monitor *mon) +{ + QDECREF(mon->outbuf); +} + char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index, int64_t cpu_index, Error **errp) { char *output = NULL; Monitor *old_mon, hmp; - memset(&hmp, 0, sizeof(hmp)); - hmp.outbuf = qstring_new(); + monitor_data_init(&hmp); hmp.skip_flush = true; old_mon = cur_mon; @@ -716,7 +730,7 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index, } out: - QDECREF(hmp.outbuf); + monitor_data_destroy(&hmp); return output; } @@ -740,33 +754,202 @@ static int compare_cmd(const char *name, const char *list) return 0; } +static int get_str(char *buf, int buf_size, const char **pp) +{ + const char *p; + char *q; + int c; + + q = buf; + p = *pp; + while (qemu_isspace(*p)) { + p++; + } + if (*p == '\0') { + fail: + *q = '\0'; + *pp = p; + return -1; + } + if (*p == '\"') { + p++; + while (*p != '\0' && *p != '\"') { + if (*p == '\\') { + p++; + c = *p++; + switch (c) { + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case '\\': + case '\'': + case '\"': + break; + default: + qemu_printf("unsupported escape code: '\\%c'\n", c); + goto fail; + } + if ((q - buf) < buf_size - 1) { + *q++ = c; + } + } else { + if ((q - buf) < buf_size - 1) { + *q++ = *p; + } + p++; + } + } + if (*p != '\"') { + qemu_printf("unterminated string\n"); + goto fail; + } + p++; + } else { + while (*p != '\0' && !qemu_isspace(*p)) { + if ((q - buf) < buf_size - 1) { + *q++ = *p; + } + p++; + } + } + *q = '\0'; + *pp = p; + return 0; +} + +#define MAX_ARGS 16 + +static void free_cmdline_args(char **args, int nb_args) +{ + int i; + + assert(nb_args <= MAX_ARGS); + + for (i = 0; i < nb_args; i++) { + g_free(args[i]); + } + +} + +/* + * Parse the command line to get valid args. + * @cmdline: command line to be parsed. + * @pnb_args: location to store the number of args, must NOT be NULL. + * @args: location to store the args, which should be freed by caller, must + * NOT be NULL. + * + * Returns 0 on success, negative on failure. + * + * NOTE: this parser is an approximate form of the real command parser. Number + * of args have a limit of MAX_ARGS. If cmdline contains more, it will + * return with failure. + */ +static int parse_cmdline(const char *cmdline, + int *pnb_args, char **args) +{ + const char *p; + int nb_args, ret; + char buf[1024]; + + p = cmdline; + nb_args = 0; + for (;;) { + while (qemu_isspace(*p)) { + p++; + } + if (*p == '\0') { + break; + } + if (nb_args >= MAX_ARGS) { + goto fail; + } + ret = get_str(buf, sizeof(buf), &p); + if (ret < 0) { + goto fail; + } + args[nb_args] = g_strdup(buf); + nb_args++; + } + *pnb_args = nb_args; + return 0; + + fail: + free_cmdline_args(args, nb_args); + return -1; +} + +static void help_cmd_dump_one(Monitor *mon, + const mon_cmd_t *cmd, + char **prefix_args, + int prefix_args_nb) +{ + int i; + + for (i = 0; i < prefix_args_nb; i++) { + monitor_printf(mon, "%s ", prefix_args[i]); + } + monitor_printf(mon, "%s %s -- %s\n", cmd->name, cmd->params, cmd->help); +} + +/* @args[@arg_index] is the valid command need to find in @cmds */ static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds, - const char *prefix, const char *name) + char **args, int nb_args, int arg_index) { const mon_cmd_t *cmd; - for(cmd = cmds; cmd->name != NULL; cmd++) { - if (!name || !strcmp(name, cmd->name)) - monitor_printf(mon, "%s%s %s -- %s\n", prefix, cmd->name, - cmd->params, cmd->help); + /* No valid arg need to compare with, dump all in *cmds */ + if (arg_index >= nb_args) { + for (cmd = cmds; cmd->name != NULL; cmd++) { + help_cmd_dump_one(mon, cmd, args, arg_index); + } + return; + } + + /* Find one entry to dump */ + for (cmd = cmds; cmd->name != NULL; cmd++) { + if (compare_cmd(args[arg_index], cmd->name)) { + if (cmd->sub_table) { + /* continue with next arg */ + help_cmd_dump(mon, cmd->sub_table, + args, nb_args, arg_index + 1); + } else { + help_cmd_dump_one(mon, cmd, args, arg_index); + } + break; + } } } static void help_cmd(Monitor *mon, const char *name) { - if (name && !strcmp(name, "info")) { - help_cmd_dump(mon, info_cmds, "info ", NULL); - } else { - help_cmd_dump(mon, mon_cmds, "", name); - if (name && !strcmp(name, "log")) { + char *args[MAX_ARGS]; + int nb_args = 0; + + /* 1. parse user input */ + if (name) { + /* special case for log, directly dump and return */ + if (!strcmp(name, "log")) { const QEMULogItem *item; monitor_printf(mon, "Log items (comma separated):\n"); monitor_printf(mon, "%-10s %s\n", "none", "remove all logs"); for (item = qemu_log_items; item->mask != 0; item++) { monitor_printf(mon, "%-10s %s\n", item->name, item->help); } + return; + } + + if (parse_cmdline(name, &nb_args, args) < 0) { + return; } } + + /* 2. dump the contents according to parsed args */ + help_cmd_dump(mon, mon->cmd_table, args, nb_args, 0); + + free_cmdline_args(args, nb_args); } static void do_help_cmd(Monitor *mon, const QDict *qdict) @@ -3171,9 +3354,14 @@ static const MonitorDef monitor_defs[] = { { NULL }, }; -static void expr_error(Monitor *mon, const char *msg) +static void GCC_FMT_ATTR(2, 3) QEMU_NORETURN +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 +3479,7 @@ static int64_t expr_unary(Monitor *mon) 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)) @@ -3416,71 +3604,6 @@ static int get_double(Monitor *mon, double *pval, const char **pp) return 0; } -static int get_str(char *buf, int buf_size, const char **pp) -{ - const char *p; - char *q; - int c; - - q = buf; - p = *pp; - while (qemu_isspace(*p)) - p++; - if (*p == '\0') { - fail: - *q = '\0'; - *pp = p; - return -1; - } - if (*p == '\"') { - p++; - while (*p != '\0' && *p != '\"') { - if (*p == '\\') { - p++; - c = *p++; - switch(c) { - case 'n': - c = '\n'; - break; - case 'r': - c = '\r'; - break; - case '\\': - case '\'': - case '\"': - break; - default: - qemu_printf("unsupported escape code: '\\%c'\n", c); - goto fail; - } - if ((q - buf) < buf_size - 1) { - *q++ = c; - } - } else { - if ((q - buf) < buf_size - 1) { - *q++ = *p; - } - p++; - } - } - if (*p != '\"') { - qemu_printf("unterminated string\n"); - goto fail; - } - p++; - } else { - while (*p != '\0' && !qemu_isspace(*p)) { - if ((q - buf) < buf_size - 1) { - *q++ = *p; - } - p++; - } - } - *q = '\0'; - *pp = p; - return 0; -} - /* * Store the command-name in cmdname, and return a pointer to * the remaining of the command string. @@ -3537,8 +3660,6 @@ static char *key_get_info(const char *type, char **key) static int default_fmt_format = 'x'; static int default_fmt_size = 4; -#define MAX_ARGS 16 - static int is_valid_option(const char *c, const char *typestr) { char option[3]; @@ -3927,6 +4048,31 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon, } } break; + case 'S': + { + /* package all remaining string */ + int len; + + while (qemu_isspace(*p)) { + p++; + } + if (*typestr == '?') { + typestr++; + if (*p == '\0') { + /* no remaining string: NULL argument */ + break; + } + } + len = strlen(p); + if (len <= 0) { + monitor_printf(mon, "%s: string expected\n", + cmdname); + break; + } + qdict_put(qdict, key, qstring_from_str(p)); + p += len; + } + break; default: bad_type: monitor_printf(mon, "%s: unknown type '%c'\n", cmdname, c); @@ -3980,7 +4126,7 @@ static void handle_user_command(Monitor *mon, const char *cmdline) qdict = qdict_new(); - cmd = monitor_parse_command(mon, cmdline, 0, mon_cmds, qdict); + cmd = monitor_parse_command(mon, cmdline, 0, mon->cmd_table, qdict); if (!cmd) goto out; @@ -4004,7 +4150,7 @@ out: QDECREF(qdict); } -static void cmd_completion(const char *name, const char *list) +static void cmd_completion(Monitor *mon, const char *name, const char *list) { const char *p, *pstart; char cmd[128]; @@ -4022,7 +4168,7 @@ static void cmd_completion(const char *name, const char *list) memcpy(cmd, pstart, len); cmd[len] = '\0'; if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) { - readline_add_completion(cur_mon->rs, cmd); + readline_add_completion(mon->rs, cmd); } if (*p == '\0') break; @@ -4030,7 +4176,7 @@ static void cmd_completion(const char *name, const char *list) } } -static void file_completion(const char *input) +static void file_completion(Monitor *mon, const char *input) { DIR *ffs; struct dirent *d; @@ -4053,7 +4199,7 @@ static void file_completion(const char *input) pstrcpy(file_prefix, sizeof(file_prefix), p + 1); } #ifdef DEBUG_COMPLETION - monitor_printf(cur_mon, "input='%s' path='%s' prefix='%s'\n", + monitor_printf(mon, "input='%s' path='%s' prefix='%s'\n", input, path, file_prefix); #endif ffs = opendir(path); @@ -4080,98 +4226,72 @@ static void file_completion(const char *input) if (stat(file, &sb) == 0 && S_ISDIR(sb.st_mode)) { pstrcat(file, sizeof(file), "/"); } - readline_add_completion(cur_mon->rs, file); + readline_add_completion(mon->rs, file); } } closedir(ffs); } +typedef struct MonitorBlockComplete { + Monitor *mon; + const char *input; +} MonitorBlockComplete; + static void block_completion_it(void *opaque, BlockDriverState *bs) { const char *name = bdrv_get_device_name(bs); - const char *input = opaque; + MonitorBlockComplete *mbc = opaque; + Monitor *mon = mbc->mon; + const char *input = mbc->input; if (input[0] == '\0' || !strncmp(name, (char *)input, strlen(input))) { - readline_add_completion(cur_mon->rs, name); + readline_add_completion(mon->rs, name); } } -/* NOTE: this parser is an approximate form of the real command parser */ -static void parse_cmdline(const char *cmdline, - int *pnb_args, char **args) -{ - const char *p; - int nb_args, ret; - char buf[1024]; - - p = cmdline; - nb_args = 0; - for(;;) { - while (qemu_isspace(*p)) - p++; - if (*p == '\0') - break; - if (nb_args >= MAX_ARGS) - break; - ret = get_str(buf, sizeof(buf), &p); - args[nb_args] = g_strdup(buf); - nb_args++; - if (ret < 0) - break; - } - *pnb_args = nb_args; -} - static const char *next_arg_type(const char *typestr) { const char *p = strchr(typestr, ':'); return (p != NULL ? ++p : typestr); } -static void monitor_find_completion(const char *cmdline) +static void monitor_find_completion_by_table(Monitor *mon, + const mon_cmd_t *cmd_table, + char **args, + int nb_args) { const char *cmdname; - char *args[MAX_ARGS]; - int nb_args, i, len; + int i; const char *ptype, *str; const mon_cmd_t *cmd; + MonitorBlockComplete mbs; - parse_cmdline(cmdline, &nb_args, args); -#ifdef DEBUG_COMPLETION - for(i = 0; i < nb_args; i++) { - monitor_printf(cur_mon, "arg%d = '%s'\n", i, (char *)args[i]); - } -#endif - - /* if the line ends with a space, it means we want to complete the - next arg */ - len = strlen(cmdline); - if (len > 0 && qemu_isspace(cmdline[len - 1])) { - if (nb_args >= MAX_ARGS) { - goto cleanup; - } - args[nb_args++] = g_strdup(""); - } if (nb_args <= 1) { /* command completion */ if (nb_args == 0) cmdname = ""; else cmdname = args[0]; - readline_set_completion_index(cur_mon->rs, strlen(cmdname)); - for(cmd = mon_cmds; cmd->name != NULL; cmd++) { - cmd_completion(cmdname, cmd->name); + readline_set_completion_index(mon->rs, strlen(cmdname)); + for (cmd = cmd_table; cmd->name != NULL; cmd++) { + cmd_completion(mon, cmdname, cmd->name); } } else { /* find the command */ - for (cmd = mon_cmds; cmd->name != NULL; cmd++) { + for (cmd = cmd_table; cmd->name != NULL; cmd++) { if (compare_cmd(args[0], cmd->name)) { break; } } if (!cmd->name) { - goto cleanup; + return; + } + + if (cmd->sub_table) { + /* do the job again */ + return monitor_find_completion_by_table(mon, cmd->sub_table, + &args[1], nb_args - 1); } ptype = next_arg_type(cmd->args_type); @@ -4189,45 +4309,68 @@ static void monitor_find_completion(const char *cmdline) switch(*ptype) { case 'F': /* file completion */ - readline_set_completion_index(cur_mon->rs, strlen(str)); - file_completion(str); + readline_set_completion_index(mon->rs, strlen(str)); + file_completion(mon, str); break; case 'B': /* block device name completion */ - readline_set_completion_index(cur_mon->rs, strlen(str)); - bdrv_iterate(block_completion_it, (void *)str); + mbs.mon = mon; + mbs.input = str; + readline_set_completion_index(mon->rs, strlen(str)); + bdrv_iterate(block_completion_it, &mbs); break; case 's': - /* XXX: more generic ? */ - if (!strcmp(cmd->name, "info")) { - readline_set_completion_index(cur_mon->rs, strlen(str)); - for(cmd = info_cmds; cmd->name != NULL; cmd++) { - cmd_completion(str, cmd->name); - } - } else if (!strcmp(cmd->name, "sendkey")) { + case 'S': + if (!strcmp(cmd->name, "sendkey")) { char *sep = strrchr(str, '-'); if (sep) str = sep + 1; - readline_set_completion_index(cur_mon->rs, strlen(str)); + readline_set_completion_index(mon->rs, strlen(str)); for (i = 0; i < Q_KEY_CODE_MAX; i++) { - cmd_completion(str, QKeyCode_lookup[i]); + cmd_completion(mon, str, QKeyCode_lookup[i]); } } else if (!strcmp(cmd->name, "help|?")) { - readline_set_completion_index(cur_mon->rs, strlen(str)); - for (cmd = mon_cmds; cmd->name != NULL; cmd++) { - cmd_completion(str, cmd->name); - } + monitor_find_completion_by_table(mon, cmd_table, + &args[1], nb_args - 1); } break; default: break; } } +} -cleanup: +static void monitor_find_completion(Monitor *mon, + const char *cmdline) +{ + char *args[MAX_ARGS]; + int nb_args, len; + + /* 1. parse the cmdline */ + if (parse_cmdline(cmdline, &nb_args, args) < 0) { + return; + } +#ifdef DEBUG_COMPLETION for (i = 0; i < nb_args; i++) { - g_free(args[i]); + monitor_printf(mon, "arg%d = '%s'\n", i, args[i]); + } +#endif + + /* if the line ends with a space, it means we want to complete the + next arg */ + len = strlen(cmdline); + if (len > 0 && qemu_isspace(cmdline[len - 1])) { + if (nb_args >= MAX_ARGS) { + goto cleanup; + } + args[nb_args++] = g_strdup(""); } + + /* 2. auto complete according to args */ + monitor_find_completion_by_table(mon, mon->cmd_table, args, nb_args); + +cleanup: + free_cmdline_args(args, nb_args); } static int monitor_can_read(void *opaque) @@ -4747,11 +4890,12 @@ void monitor_init(CharDriverState *chr, int flags) if (is_first_init) { monitor_protocol_event_init(); + sortcmdlist(); is_first_init = 0; } - mon = g_malloc0(sizeof(*mon)); - mon->outbuf = qstring_new(); + mon = g_malloc(sizeof(*mon)); + monitor_data_init(mon); mon->chr = chr; mon->flags = flags; @@ -4776,8 +4920,6 @@ void monitor_init(CharDriverState *chr, int flags) QLIST_INSERT_HEAD(&mon_list, mon, entry); if (!default_mon || (flags & MONITOR_IS_DEFAULT)) default_mon = mon; - - sortcmdlist(); } static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque) @@ -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 4119721720..9d3a09e334 100644 --- a/net/dump.c +++ b/net/dump.c @@ -69,7 +69,7 @@ static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size) 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; @@ -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 87af1d3d39..e61309d8d5 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/qapi/opts-visitor.c b/qapi/opts-visitor.c index 174bd8bdb0..96ed85899d 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 @@ struct OptsVisitor /* 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 @@ opts_start_list(Visitor *v, const char *name, Error **errp) 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 @@ opts_next_list(Visitor *v, GenericList **list, Error **errp) 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 @@ opts_next_list(Visitor *v, GenericList **list, Error **errp) return NULL; } link = &(*list)->next; + break; + } + + default: + abort(); } *link = g_malloc0(sizeof **link); @@ -192,14 +261,19 @@ opts_end_list(Visitor *v, Error **errp) { 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 @@ lookup_scalar(const OptsVisitor *ov, const char *name, Error **errp) 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 @@ lookup_scalar(const OptsVisitor *ov, const char *name, Error **errp) 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 @@ opts_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp) 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 @@ opts_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp) 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; - } - if (*str != '-' && *str != '\0') { - unsigned long long val; - char *endptr; + /* we've gotten past lookup_scalar() */ + assert(ov->list_mode == LM_NONE || ov->list_mode == LM_IN_PROGRESS); - /* 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); + 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; + + 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; + + /* 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 @@ opts_start_optional(Visitor *v, bool *present, const char *name, 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/qemu-char.c b/qemu-char.c index 1be1cf676e..62594965bd 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -281,7 +281,7 @@ static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len) 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; @@ -3344,7 +3344,7 @@ CharDriverState *qemu_chr_new(const char *label, const char *filename, void (*in 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)) { diff --git a/qemu-coroutine-io.c b/qemu-coroutine-io.c index c4df35a640..054ca70627 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-sleep.c b/qemu-coroutine-sleep.c index 169ce5ccc9..f6db978c1d 100644 --- a/qemu-coroutine-sleep.c +++ b/qemu-coroutine-sleep.c @@ -26,14 +26,14 @@ static void co_sleep_cb(void *opaque) 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-io-cmds.c b/qemu-io-cmds.c index ffbcf31cfc..f91b6c4f02 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-nbd.c b/qemu-nbd.c index 9c31d45706..f044546c28 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-timer.c b/qemu-timer.c index b2d95e2fec..95ff47fef3 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 */ - QEMUClock *clock; - QEMUTimerCB *cb; - void *opaque; - QEMUTimer *next; - int scale; -}; +QEMUTimerListGroup main_loop_tlg; +QEMUClock qemu_clocks[QEMU_CLOCK_MAX]; -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; +/* 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; + QEMUTimer *active_timers; + QLIST_ENTRY(QEMUTimerList) list; + QEMUTimerListNotifyCB *notify_cb; + void *notify_opaque; }; -static struct qemu_alarm_timer *alarm_timer; +/** + * 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 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; - - 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; - } - } + QEMUTimerList *timer_list; + QEMUClock *clock = qemu_clock_ptr(type); - 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 void qemu_clock_init(QEMUClockType type) +{ + QEMUClock *clock = qemu_clock_ptr(type); -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, } -}; + clock->type = type; + clock->enabled = true; + clock->last = INT64_MIN; + QLIST_INIT(&clock->timerlists); + notifier_list_init(&clock->reset_notifiers); + main_loop_tlg.tl[type] = timerlist_new(type, NULL, NULL); +} -static void show_available_alarms(void) +bool qemu_clock_use_for_deadline(QEMUClockType type) { - int i; - - printf("Available alarm timers, in order of precedence:\n"); - for (i = 0; alarm_timers[i].name; i++) - printf("%s\n", alarm_timers[i].name); + return !(use_icount && (type == QEMU_CLOCK_VIRTUAL)); } -void configure_alarms(char const *opt) +void qemu_clock_notify(QEMUClockType type) { - int i; - int cur = 0; - int count = ARRAY_SIZE(alarm_timers) - 1; - char *arg; - char *name; - struct qemu_alarm_timer tmp; + QEMUTimerList *timer_list; + QEMUClock *clock = qemu_clock_ptr(type); + QLIST_FOREACH(timer_list, &clock->timerlists, list) { + timerlist_notify(timer_list); + } +} - if (is_help_option(opt)) { - show_available_alarms(); - exit(0); +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_clock_notify(type); } +} - arg = g_strdup(opt); +bool timerlist_has_timers(QEMUTimerList *timer_list) +{ + return !!timer_list->active_timers; +} - /* 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; - } +bool qemu_clock_has_timers(QEMUClockType type) +{ + return timerlist_has_timers( + main_loop_tlg.tl[type]); +} - if (i == count) { - fprintf(stderr, "Unknown clock %s\n", name); - goto next; - } +bool timerlist_expired(QEMUTimerList *timer_list) +{ + return (timer_list->active_timers && + timer_list->active_timers->expire_time < + qemu_clock_get_ns(timer_list->clock->type)); +} - if (i < cur) - /* Ignore */ - goto next; +bool qemu_clock_expired(QEMUClockType type) +{ + return timerlist_expired( + main_loop_tlg.tl[type]); +} - /* Swap */ - tmp = alarm_timers[i]; - alarm_timers[i] = alarm_timers[cur]; - alarm_timers[cur] = tmp; +/* + * 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; - cur++; -next: - name = strtok(NULL, ","); + if (!timer_list->clock->enabled || !timer_list->active_timers) { + return -1; } - g_free(arg); + delta = timer_list->active_timers->expire_time - + qemu_clock_get_ns(timer_list->clock->type); - if (cur) { - /* Disable remaining timers */ - for (i = cur; i < count; i++) - alarm_timers[i].name = NULL; - } else { - show_available_alarms(); - exit(1); + if (delta <= 0) { + return 0; } -} -QEMUClock *rt_clock; -QEMUClock *vm_clock; -QEMUClock *host_clock; + return delta; +} -static QEMUClock *qemu_new_clock(int type) +/* 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) { - QEMUClock *clock; - - clock = g_malloc0(sizeof(QEMUClock)); - clock->type = type; - clock->enabled = true; - clock->last = INT64_MIN; - notifier_list_init(&clock->reset_notifiers); - return clock; + 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; } -void qemu_clock_enable(QEMUClock *clock, bool enabled) +QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list) { - bool old = clock->enabled; - clock->enabled = enabled; - if (enabled && !old) { - qemu_rearm_alarm_timer(alarm_timer); - } + return timer_list->clock->type; } -int64_t qemu_clock_has_timers(QEMUClock *clock) +QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type) { - return !!clock->active_timers; + return main_loop_tlg.tl[type]; } -int64_t qemu_clock_expired(QEMUClock *clock) +void timerlist_notify(QEMUTimerList *timer_list) { - return (clock->active_timers && - clock->active_timers->expire_time < qemu_get_clock_ns(clock)); + if (timer_list->notify_cb) { + timer_list->notify_cb(timer_list->notify_opaque); + } else { + qemu_notify_event(); + } } -int64_t qemu_clock_deadline(QEMUClock *clock) +/* 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) { - /* To avoid problems with overflow limit this to 2^32. */ - int64_t delta = INT32_MAX; + int64_t ms; + if (ns < 0) { + return -1; + } - if (clock->active_timers) { - delta = clock->active_timers->expire_time - qemu_get_clock_ns(clock); + if (!ns) { + return 0; } - if (delta < 0) { - delta = 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 delta; + + return (int) ms; } -QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale, - QEMUTimerCB *cb, void *opaque) + +/* 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) { - QEMUTimer *ts; +#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 +} - ts = g_malloc0(sizeof(QEMUTimer)); - ts->clock = clock; + +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 @@ void qemu_del_timer(QEMUTimer *ts) /* 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 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) *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 @@ bool qemu_timer_pending(QEMUTimer *ts) 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 @@ int64_t qemu_get_clock_ns(QEMUClock *clock) } } -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); - } -} - -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); + QEMUClockType type; + for (type = 0; type < QEMU_CLOCK_MAX; type++) { + qemu_clock_init(type); } -} -#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) -{ - 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; -} - -static void dynticks_stop_timer(struct qemu_alarm_timer *t) -{ - timer_t host_timer = t->timer; - - timer_delete(host_timer); -} - -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) +uint64_t timer_expire_time_ns(QEMUTimer *ts) { - timeGetDevCaps(&mm_tc, sizeof(mm_tc)); - return 0; + return timer_pending(ts) ? ts->expire_time : -1; } -static void mm_stop_timer(struct qemu_alarm_timer *t) +bool qemu_clock_run_all_timers(void) { - if (mm_timer) { - timeKillEvent(mm_timer); - } -} + bool progress = false; + QEMUClockType type; -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; + for (type = 0; type < QEMU_CLOCK_MAX; type++) { + progress |= qemu_clock_run_timers(type); } - 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); - } + return progress; } - -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/qmp-commands.hx b/qmp-commands.hx index cf47e3fe72..bb09e72712 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -487,7 +487,7 @@ Example: <- { "return": {} } Note: inject-nmi fails when the guest doesn't support injecting. - Currently, only x86 guests do. + Currently, only x86 (NMI) and s390x (RESTART) guests do. EQMP diff --git a/qom/object.c b/qom/object.c index 74fd241a02..e90e3827d9 100644 --- a/qom/object.c +++ b/qom/object.c @@ -311,7 +311,7 @@ static void object_post_init_with_type(Object *obj, TypeImpl *ti) } } -void object_initialize_with_type(void *data, TypeImpl *type) +void object_initialize_with_type(void *data, size_t size, TypeImpl *type) { Object *obj = data; @@ -320,6 +320,7 @@ void object_initialize_with_type(void *data, TypeImpl *type) g_assert(type->instance_size >= sizeof(Object)); g_assert(type->abstract == false); + g_assert(size >= type->instance_size); memset(obj, 0, type->instance_size); obj->class = type->class; @@ -329,11 +330,11 @@ void object_initialize_with_type(void *data, TypeImpl *type) object_post_init_with_type(obj, type); } -void object_initialize(void *data, const char *typename) +void object_initialize(void *data, size_t size, const char *typename) { TypeImpl *type = type_get_by_name(typename); - object_initialize_with_type(data, type); + object_initialize_with_type(data, size, type); } static inline bool object_property_is_child(ObjectProperty *prop) @@ -424,7 +425,7 @@ Object *object_new_with_type(Type type) type_initialize(type); obj = g_malloc(type->instance_size); - object_initialize_with_type(obj, type); + object_initialize_with_type(obj, type->instance_size, type); obj->free = g_free; return obj; @@ -47,7 +47,7 @@ static bool qtest_opened; * * 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. * @@ -177,7 +177,7 @@ static void qtest_send_prefix(CharDriverState *chr) qtest_get_time(&tv); fprintf(qtest_log_fp, "[S +" FMT_timeval "] ", - tv.tv_sec, (long) tv.tv_usec); + (long) tv.tv_sec, (long) tv.tv_usec); } static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr, @@ -225,7 +225,7 @@ static void qtest_process_command(CharDriverState *chr, gchar **words) qtest_get_time(&tv); fprintf(qtest_log_fp, "[R +" FMT_timeval "]", - tv.tv_sec, (long) tv.tv_usec); + (long) tv.tv_sec, (long) tv.tv_usec); for (i = 0; words[i]; i++) { fprintf(qtest_log_fp, " %s", words[i]); } @@ -412,11 +412,11 @@ static void qtest_process_command(CharDriverState *chr, gchar **words) 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 @@ static void qtest_process_command(CharDriverState *chr, gchar **words) 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]); @@ -485,7 +485,7 @@ static void qtest_event(void *opaque, int event) qtest_opened = true; if (qtest_log_fp) { fprintf(qtest_log_fp, "[I " FMT_timeval "] OPENED\n", - start_time.tv_sec, (long) start_time.tv_usec); + (long) start_time.tv_sec, (long) start_time.tv_usec); } break; case CHR_EVENT_CLOSED: @@ -494,7 +494,7 @@ static void qtest_event(void *opaque, int event) qemu_timeval tv; qtest_get_time(&tv); fprintf(qtest_log_fp, "[I +" FMT_timeval "] CLOSED\n", - tv.tv_sec, (long) tv.tv_usec); + (long) tv.tv_sec, (long) tv.tv_usec); } break; default: diff --git a/readline.c b/readline.c index 1c0f7ee26b..abf27ddec3 100644 --- a/readline.c +++ b/readline.c @@ -276,7 +276,6 @@ void readline_set_completion_index(ReadLineState *rs, int index) static void readline_completion(ReadLineState *rs) { - Monitor *mon = cur_mon; int len, i, j, max_width, nb_cols, max_prefix; char *cmdline; @@ -285,7 +284,7 @@ static void readline_completion(ReadLineState *rs) cmdline = g_malloc(rs->cmd_buf_index + 1); memcpy(cmdline, rs->cmd_buf, rs->cmd_buf_index); cmdline[rs->cmd_buf_index] = '\0'; - rs->completion_finder(cmdline); + rs->completion_finder(rs->mon, cmdline); g_free(cmdline); /* no completion found */ @@ -300,7 +299,7 @@ static void readline_completion(ReadLineState *rs) if (len > 0 && rs->completions[0][len - 1] != '/') readline_insert_char(rs, ' '); } else { - monitor_printf(mon, "\n"); + monitor_printf(rs->mon, "\n"); max_width = 0; max_prefix = 0; for(i = 0; i < rs->nb_completions; i++) { @@ -97,18 +97,18 @@ static void qemu_announce_self_once(void *opaque) 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 @@ uint64_t qemu_get_be64(QEMUFile *f) /* 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 @@ const VMStateInfo vmstate_info_float64 = { 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 @@ void do_savevm(Monitor *mon, const QDict *qdict) 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 0000000000..8f7e8182a1 --- /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.py b/scripts/qapi.py index 0ebea945bb..1069310f8d 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -161,7 +161,7 @@ class QAPISchema: def parse_schema(fp): try: schema = QAPISchema(fp) - except QAPISchemaError as e: + except QAPISchemaError, e: print >>sys.stderr, e exit(1) diff --git a/scripts/switch-timer-api b/scripts/switch-timer-api new file mode 100755 index 0000000000..a369a083d1 --- /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 dcd5fafe5d..87ca8a53a9 100644 --- a/slirp/if.c +++ b/slirp/if.c @@ -154,7 +154,7 @@ diddit: */ 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 0bcc481939..c0d489950a 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 80b28ea89e..5c3dabba93 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -448,7 +448,7 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error) 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 @@ int if_encap(Slirp *slirp, struct mbuf *ifm) 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/clock-warp.c b/stubs/clock-warp.c index b64c462e73..5565118d11 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/target-alpha/sys_helper.c b/target-alpha/sys_helper.c index 97cf9ebfc9..035810c27c 100644 --- a/target-alpha/sys_helper.c +++ b/target-alpha/sys_helper.c @@ -30,9 +30,9 @@ uint64_t helper_load_pcc(CPUAlphaState *env) 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 @@ -88,12 +88,12 @@ void helper_halt(uint64_t restart) 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) @@ -102,9 +102,9 @@ void helper_set_alarm(CPUAlphaState *env, uint64_t expire) 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); } } diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 309dea6ff0..28ce4363f1 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -415,7 +415,7 @@ static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp) } else if (use_goto_tb(ctx, dest)) { tcg_gen_goto_tb(0); tcg_gen_movi_i64(cpu_pc, dest); - tcg_gen_exit_tb((tcg_target_long)ctx->tb); + tcg_gen_exit_tb((uintptr_t)ctx->tb); return EXIT_GOTO_TB; } else { tcg_gen_movi_i64(cpu_pc, dest); @@ -434,12 +434,12 @@ static ExitStatus gen_bcond_internal(DisasContext *ctx, TCGCond cond, tcg_gen_goto_tb(0); tcg_gen_movi_i64(cpu_pc, ctx->pc); - tcg_gen_exit_tb((tcg_target_long)ctx->tb); + tcg_gen_exit_tb((uintptr_t)ctx->tb); gen_set_label(lab_true); tcg_gen_goto_tb(1); tcg_gen_movi_i64(cpu_pc, dest); - tcg_gen_exit_tb((tcg_target_long)ctx->tb + 1); + tcg_gen_exit_tb((uintptr_t)ctx->tb + 1); return EXIT_GOTO_TB; } else { @@ -1629,7 +1629,7 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode) 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); + tcg_gen_exit_tb((uintptr_t)ctx->tb); return EXIT_GOTO_TB; } diff --git a/target-arm/cpu.c b/target-arm/cpu.c index f01ce03682..b2556c66b4 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -204,9 +204,9 @@ static void arm_cpu_initfn(Object *obj) qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 2); } - cpu->gt_timer[GTIMER_PHYS] = qemu_new_timer(vm_clock, GTIMER_SCALE, + cpu->gt_timer[GTIMER_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, GTIMER_SCALE, arm_gt_ptimer_cb, cpu); - cpu->gt_timer[GTIMER_VIRT] = qemu_new_timer(vm_clock, GTIMER_SCALE, + 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)); diff --git a/target-arm/helper.c b/target-arm/helper.c index f4e1b06d23..e51ef20aea 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -699,7 +699,7 @@ static const ARMCPRegInfo v6k_cp_reginfo[] = { static uint64_t gt_get_countervalue(CPUARMState *env) { - return qemu_get_clock_ns(vm_clock) / GTIMER_SCALE; + return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / GTIMER_SCALE; } static void gt_recalc_timer(ARMCPU *cpu, int timeridx) @@ -733,12 +733,12 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx) if (nexttick > INT64_MAX / GTIMER_SCALE) { nexttick = INT64_MAX / GTIMER_SCALE; } - qemu_mod_timer(cpu->gt_timer[timeridx], nexttick); + 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); - qemu_del_timer(cpu->gt_timer[timeridx]); + timer_del(cpu->gt_timer[timeridx]); } } @@ -758,7 +758,7 @@ static void gt_cnt_reset(CPUARMState *env, const ARMCPRegInfo *ri) ARMCPU *cpu = arm_env_get_cpu(env); int timeridx = ri->opc1 & 1; - qemu_del_timer(cpu->gt_timer[timeridx]); + timer_del(cpu->gt_timer[timeridx]); } static int gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri, @@ -941,7 +941,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { #else /* In user-mode none of the generic timer registers are accessible, - * and their implementation depends on vm_clock and qdev gpio outputs, + * 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[] = { diff --git a/target-arm/translate.c b/target-arm/translate.c index d1e8538142..9160ced4fe 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -3356,7 +3356,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { tcg_gen_goto_tb(n); gen_set_pc_im(dest); - tcg_gen_exit_tb((tcg_target_long)tb + n); + tcg_gen_exit_tb((uintptr_t)tb + n); } else { gen_set_pc_im(dest); tcg_gen_exit_tb(0); diff --git a/target-cris/translate.c b/target-cris/translate.c index 2a4beeb869..617e1b4242 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -558,7 +558,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { tcg_gen_goto_tb(n); tcg_gen_movi_tl(env_pc, dest); - tcg_gen_exit_tb((tcg_target_long)tb + n); + tcg_gen_exit_tb((uintptr_t)tb + n); } else { tcg_gen_movi_tl(env_pc, dest); tcg_gen_exit_tb(0); diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 6e3825220d..42c5de034e 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1852,7 +1852,7 @@ X86CPU *cpu_x86_init(const char *cpu_model) 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)); diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 8a3d0fda32..5723eff9a8 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -37,9 +37,9 @@ #define TARGET_HAS_ICE 1 #ifdef TARGET_X86_64 -#define ELF_MACHINE EM_X86_64 +#define ELF_MACHINE EM_X86_64 #else -#define ELF_MACHINE EM_386 +#define ELF_MACHINE EM_386 #endif #define CPUArchState struct CPUX86State @@ -98,10 +98,10 @@ #define DESC_TSS_BUSY_MASK (1 << 9) /* eflags masks */ -#define CC_C 0x0001 -#define CC_P 0x0004 -#define CC_A 0x0010 -#define CC_Z 0x0040 +#define CC_C 0x0001 +#define CC_P 0x0004 +#define CC_A 0x0010 +#define CC_Z 0x0040 #define CC_S 0x0080 #define CC_O 0x0800 @@ -109,14 +109,14 @@ #define IOPL_SHIFT 12 #define VM_SHIFT 17 -#define TF_MASK 0x00000100 -#define IF_MASK 0x00000200 -#define DF_MASK 0x00000400 -#define IOPL_MASK 0x00003000 -#define NT_MASK 0x00004000 -#define RF_MASK 0x00010000 -#define VM_MASK 0x00020000 -#define AC_MASK 0x00040000 +#define TF_MASK 0x00000100 +#define IF_MASK 0x00000200 +#define DF_MASK 0x00000400 +#define IOPL_MASK 0x00003000 +#define NT_MASK 0x00004000 +#define RF_MASK 0x00010000 +#define VM_MASK 0x00020000 +#define AC_MASK 0x00040000 #define VIF_MASK 0x00080000 #define VIP_MASK 0x00100000 #define ID_MASK 0x00200000 @@ -238,28 +238,28 @@ #define DR7_TYPE_IO_RW 0x2 #define DR7_TYPE_DATA_RW 0x3 -#define PG_PRESENT_BIT 0 -#define PG_RW_BIT 1 -#define PG_USER_BIT 2 -#define PG_PWT_BIT 3 -#define PG_PCD_BIT 4 -#define PG_ACCESSED_BIT 5 -#define PG_DIRTY_BIT 6 -#define PG_PSE_BIT 7 -#define PG_GLOBAL_BIT 8 -#define PG_NX_BIT 63 +#define PG_PRESENT_BIT 0 +#define PG_RW_BIT 1 +#define PG_USER_BIT 2 +#define PG_PWT_BIT 3 +#define PG_PCD_BIT 4 +#define PG_ACCESSED_BIT 5 +#define PG_DIRTY_BIT 6 +#define PG_PSE_BIT 7 +#define PG_GLOBAL_BIT 8 +#define PG_NX_BIT 63 #define PG_PRESENT_MASK (1 << PG_PRESENT_BIT) -#define PG_RW_MASK (1 << PG_RW_BIT) -#define PG_USER_MASK (1 << PG_USER_BIT) -#define PG_PWT_MASK (1 << PG_PWT_BIT) -#define PG_PCD_MASK (1 << PG_PCD_BIT) +#define PG_RW_MASK (1 << PG_RW_BIT) +#define PG_USER_MASK (1 << PG_USER_BIT) +#define PG_PWT_MASK (1 << PG_PWT_BIT) +#define PG_PCD_MASK (1 << PG_PCD_BIT) #define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT) -#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT) -#define PG_PSE_MASK (1 << PG_PSE_BIT) -#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT) +#define PG_DIRTY_MASK (1 << PG_DIRTY_BIT) +#define PG_PSE_MASK (1 << PG_PSE_BIT) +#define PG_GLOBAL_MASK (1 << PG_GLOBAL_BIT) #define PG_HI_USER_MASK 0x7ff0000000000000LL -#define PG_NX_MASK (1LL << PG_NX_BIT) +#define PG_NX_MASK (1LL << PG_NX_BIT) #define PG_ERROR_W_BIT 1 @@ -269,45 +269,48 @@ #define PG_ERROR_RSVD_MASK 0x08 #define PG_ERROR_I_D_MASK 0x10 -#define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */ -#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */ +#define MCG_CTL_P (1ULL<<8) /* MCG_CAP register available */ +#define MCG_SER_P (1ULL<<24) /* MCA recovery/new status bits */ -#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P) -#define MCE_BANKS_DEF 10 +#define MCE_CAP_DEF (MCG_CTL_P|MCG_SER_P) +#define MCE_BANKS_DEF 10 -#define MCG_STATUS_RIPV (1ULL<<0) /* restart ip valid */ -#define MCG_STATUS_EIPV (1ULL<<1) /* ip points to correct instruction */ -#define MCG_STATUS_MCIP (1ULL<<2) /* machine check in progress */ +#define MCG_STATUS_RIPV (1ULL<<0) /* restart ip valid */ +#define MCG_STATUS_EIPV (1ULL<<1) /* ip points to correct instruction */ +#define MCG_STATUS_MCIP (1ULL<<2) /* machine check in progress */ -#define MCI_STATUS_VAL (1ULL<<63) /* valid error */ -#define MCI_STATUS_OVER (1ULL<<62) /* previous errors lost */ -#define MCI_STATUS_UC (1ULL<<61) /* uncorrected error */ -#define MCI_STATUS_EN (1ULL<<60) /* error enabled */ -#define MCI_STATUS_MISCV (1ULL<<59) /* misc error reg. valid */ -#define MCI_STATUS_ADDRV (1ULL<<58) /* addr reg. valid */ -#define MCI_STATUS_PCC (1ULL<<57) /* processor context corrupt */ -#define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */ -#define MCI_STATUS_AR (1ULL<<55) /* Action required */ +#define MCI_STATUS_VAL (1ULL<<63) /* valid error */ +#define MCI_STATUS_OVER (1ULL<<62) /* previous errors lost */ +#define MCI_STATUS_UC (1ULL<<61) /* uncorrected error */ +#define MCI_STATUS_EN (1ULL<<60) /* error enabled */ +#define MCI_STATUS_MISCV (1ULL<<59) /* misc error reg. valid */ +#define MCI_STATUS_ADDRV (1ULL<<58) /* addr reg. valid */ +#define MCI_STATUS_PCC (1ULL<<57) /* processor context corrupt */ +#define MCI_STATUS_S (1ULL<<56) /* Signaled machine check */ +#define MCI_STATUS_AR (1ULL<<55) /* Action required */ /* MISC register defines */ -#define MCM_ADDR_SEGOFF 0 /* segment offset */ -#define MCM_ADDR_LINEAR 1 /* linear address */ -#define MCM_ADDR_PHYS 2 /* physical address */ -#define MCM_ADDR_MEM 3 /* memory address */ -#define MCM_ADDR_GENERIC 7 /* generic */ +#define MCM_ADDR_SEGOFF 0 /* segment offset */ +#define MCM_ADDR_LINEAR 1 /* linear address */ +#define MCM_ADDR_PHYS 2 /* physical address */ +#define MCM_ADDR_MEM 3 /* memory address */ +#define MCM_ADDR_GENERIC 7 /* generic */ #define MSR_IA32_TSC 0x10 #define MSR_IA32_APICBASE 0x1b #define MSR_IA32_APICBASE_BSP (1<<8) #define MSR_IA32_APICBASE_ENABLE (1<<11) #define MSR_IA32_APICBASE_BASE (0xfffff<<12) +#define MSR_IA32_FEATURE_CONTROL 0x0000003a #define MSR_TSC_ADJUST 0x0000003b #define MSR_IA32_TSCDEADLINE 0x6e0 -#define MSR_MTRRcap 0xfe -#define MSR_MTRRcap_VCNT 8 -#define MSR_MTRRcap_FIXRANGE_SUPPORT (1 << 8) -#define MSR_MTRRcap_WC_SUPPORTED (1 << 10) +#define MSR_P6_PERFCTR0 0xc1 + +#define MSR_MTRRcap 0xfe +#define MSR_MTRRcap_VCNT 8 +#define MSR_MTRRcap_FIXRANGE_SUPPORT (1 << 8) +#define MSR_MTRRcap_WC_SUPPORTED (1 << 10) #define MSR_IA32_SYSENTER_CS 0x174 #define MSR_IA32_SYSENTER_ESP 0x175 @@ -317,35 +320,45 @@ #define MSR_MCG_STATUS 0x17a #define MSR_MCG_CTL 0x17b +#define MSR_P6_EVNTSEL0 0x186 + #define MSR_IA32_PERF_STATUS 0x198 -#define MSR_IA32_MISC_ENABLE 0x1a0 +#define MSR_IA32_MISC_ENABLE 0x1a0 /* Indicates good rep/movs microcode on some processors: */ #define MSR_IA32_MISC_ENABLE_DEFAULT 1 -#define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) -#define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) - -#define MSR_MTRRfix64K_00000 0x250 -#define MSR_MTRRfix16K_80000 0x258 -#define MSR_MTRRfix16K_A0000 0x259 -#define MSR_MTRRfix4K_C0000 0x268 -#define MSR_MTRRfix4K_C8000 0x269 -#define MSR_MTRRfix4K_D0000 0x26a -#define MSR_MTRRfix4K_D8000 0x26b -#define MSR_MTRRfix4K_E0000 0x26c -#define MSR_MTRRfix4K_E8000 0x26d -#define MSR_MTRRfix4K_F0000 0x26e -#define MSR_MTRRfix4K_F8000 0x26f +#define MSR_MTRRphysBase(reg) (0x200 + 2 * (reg)) +#define MSR_MTRRphysMask(reg) (0x200 + 2 * (reg) + 1) + +#define MSR_MTRRfix64K_00000 0x250 +#define MSR_MTRRfix16K_80000 0x258 +#define MSR_MTRRfix16K_A0000 0x259 +#define MSR_MTRRfix4K_C0000 0x268 +#define MSR_MTRRfix4K_C8000 0x269 +#define MSR_MTRRfix4K_D0000 0x26a +#define MSR_MTRRfix4K_D8000 0x26b +#define MSR_MTRRfix4K_E0000 0x26c +#define MSR_MTRRfix4K_E8000 0x26d +#define MSR_MTRRfix4K_F0000 0x26e +#define MSR_MTRRfix4K_F8000 0x26f #define MSR_PAT 0x277 -#define MSR_MTRRdefType 0x2ff +#define MSR_MTRRdefType 0x2ff + +#define MSR_CORE_PERF_FIXED_CTR0 0x309 +#define MSR_CORE_PERF_FIXED_CTR1 0x30a +#define MSR_CORE_PERF_FIXED_CTR2 0x30b +#define MSR_CORE_PERF_FIXED_CTR_CTRL 0x38d +#define MSR_CORE_PERF_GLOBAL_STATUS 0x38e +#define MSR_CORE_PERF_GLOBAL_CTRL 0x38f +#define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x390 -#define MSR_MC0_CTL 0x400 -#define MSR_MC0_STATUS 0x401 -#define MSR_MC0_ADDR 0x402 -#define MSR_MC0_MISC 0x403 +#define MSR_MC0_CTL 0x400 +#define MSR_MC0_STATUS 0x401 +#define MSR_MC0_ADDR 0x402 +#define MSR_MC0_MISC 0x403 #define MSR_EFER 0xc0000080 @@ -724,6 +737,9 @@ typedef struct { #define CPU_NB_REGS CPU_NB_REGS32 #endif +#define MAX_FIXED_COUNTERS 3 +#define MAX_GP_COUNTERS (MSR_IA32_PERF_STATUS - MSR_P6_EVNTSEL0) + #define NB_MMU_MODES 3 typedef enum TPRAccess { @@ -817,6 +833,15 @@ typedef struct CPUX86State { uint64_t mcg_status; uint64_t msr_ia32_misc_enable; + uint64_t msr_ia32_feature_control; + + uint64_t msr_fixed_ctr_ctrl; + uint64_t msr_global_ctrl; + uint64_t msr_global_status; + uint64_t msr_global_ovf_ctrl; + uint64_t msr_fixed_counters[MAX_FIXED_COUNTERS]; + uint64_t msr_gp_counters[MAX_GP_COUNTERS]; + uint64_t msr_gp_evtsel[MAX_GP_COUNTERS]; /* exception/interrupt handling */ int error_code; @@ -1089,7 +1114,7 @@ static inline CPUX86State *cpu_init(const char *cpu_model) #define cpu_gen_code cpu_x86_gen_code #define cpu_signal_handler cpu_x86_signal_handler #define cpu_list x86_cpu_list -#define cpudef_setup x86_cpudef_setup +#define cpudef_setup x86_cpudef_setup /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kernel diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 0b6eb0155c..749aa09a21 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -65,12 +65,16 @@ static bool has_msr_star; static bool has_msr_hsave_pa; static bool has_msr_tsc_adjust; static bool has_msr_tsc_deadline; +static bool has_msr_feature_control; static bool has_msr_async_pf_en; static bool has_msr_pv_eoi_en; static bool has_msr_misc_enable; static bool has_msr_kvm_steal_time; static int lm_capable_kernel; +static bool has_msr_architectural_pmu; +static uint32_t num_architectural_pmu_counters; + bool kvm_allows_irq0_override(void) { return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing(); @@ -597,6 +601,25 @@ int kvm_arch_init_vcpu(CPUState *cs) break; } } + + if (limit >= 0x0a) { + uint32_t ver; + + cpu_x86_cpuid(env, 0x0a, 0, &ver, &unused, &unused, &unused); + if ((ver & 0xff) > 0) { + has_msr_architectural_pmu = true; + num_architectural_pmu_counters = (ver & 0xff00) >> 8; + + /* Shouldn't be more than 32, since that's the number of bits + * available in EBX to tell us _which_ counters are available. + * Play it safe. + */ + if (num_architectural_pmu_counters > MAX_GP_COUNTERS) { + num_architectural_pmu_counters = MAX_GP_COUNTERS; + } + } + } + cpu_x86_cpuid(env, 0x80000000, 0, &limit, &unused, &unused, &unused); for (i = 0x80000000; i <= limit; i++) { @@ -660,6 +683,12 @@ int kvm_arch_init_vcpu(CPUState *cs) qemu_add_vm_change_state_handler(cpu_update_state, env); + c = cpuid_find_entry(&cpuid_data.cpuid, 1, 0); + if (c) { + has_msr_feature_control = !!(c->ecx & CPUID_EXT_VMX) || + !!(c->ecx & CPUID_EXT_SMX); + } + cpuid_data.cpuid.padding = 0; r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data); if (r) { @@ -1060,6 +1089,26 @@ static void kvm_msr_entry_set(struct kvm_msr_entry *entry, entry->data = value; } +static int kvm_put_tscdeadline_msr(X86CPU *cpu) +{ + CPUX86State *env = &cpu->env; + struct { + struct kvm_msrs info; + struct kvm_msr_entry entries[1]; + } msr_data; + struct kvm_msr_entry *msrs = msr_data.entries; + + if (!has_msr_tsc_deadline) { + return 0; + } + + kvm_msr_entry_set(&msrs[0], MSR_IA32_TSCDEADLINE, env->tsc_deadline); + + msr_data.info.nmsrs = 1; + + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, &msr_data); +} + static int kvm_put_msrs(X86CPU *cpu, int level) { CPUX86State *env = &cpu->env; @@ -1068,7 +1117,7 @@ static int kvm_put_msrs(X86CPU *cpu, int level) struct kvm_msr_entry entries[100]; } msr_data; struct kvm_msr_entry *msrs = msr_data.entries; - int n = 0; + int n = 0, i; kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs); kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp); @@ -1083,9 +1132,6 @@ static int kvm_put_msrs(X86CPU *cpu, int level) if (has_msr_tsc_adjust) { kvm_msr_entry_set(&msrs[n++], MSR_TSC_ADJUST, env->tsc_adjust); } - if (has_msr_tsc_deadline) { - kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSCDEADLINE, env->tsc_deadline); - } if (has_msr_misc_enable) { kvm_msr_entry_set(&msrs[n++], MSR_IA32_MISC_ENABLE, env->msr_ia32_misc_enable); @@ -1110,9 +1156,8 @@ static int kvm_put_msrs(X86CPU *cpu, int level) } } /* - * The following paravirtual MSRs have side effects on the guest or are - * too heavy for normal writeback. Limit them to reset or full state - * updates. + * The following MSRs have side effects on the guest or are too heavy + * for normal writeback. Limit them to reset or full state updates. */ if (level >= KVM_PUT_RESET_STATE) { kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME, @@ -1130,6 +1175,33 @@ static int kvm_put_msrs(X86CPU *cpu, int level) kvm_msr_entry_set(&msrs[n++], MSR_KVM_STEAL_TIME, env->steal_time_msr); } + if (has_msr_architectural_pmu) { + /* Stop the counter. */ + kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR_CTRL, 0); + kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_CTRL, 0); + + /* Set the counter values. */ + for (i = 0; i < MAX_FIXED_COUNTERS; i++) { + kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR0 + i, + env->msr_fixed_counters[i]); + } + for (i = 0; i < num_architectural_pmu_counters; i++) { + kvm_msr_entry_set(&msrs[n++], MSR_P6_PERFCTR0 + i, + env->msr_gp_counters[i]); + kvm_msr_entry_set(&msrs[n++], MSR_P6_EVNTSEL0 + i, + env->msr_gp_evtsel[i]); + } + kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_STATUS, + env->msr_global_status); + kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_OVF_CTRL, + env->msr_global_ovf_ctrl); + + /* Now start the PMU. */ + kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_FIXED_CTR_CTRL, + env->msr_fixed_ctr_ctrl); + kvm_msr_entry_set(&msrs[n++], MSR_CORE_PERF_GLOBAL_CTRL, + env->msr_global_ctrl); + } 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); @@ -1137,6 +1209,10 @@ static int kvm_put_msrs(X86CPU *cpu, int level) if (cpu->hyperv_vapic) { kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_APIC_ASSIST_PAGE, 0); } + if (has_msr_feature_control) { + kvm_msr_entry_set(&msrs[n++], MSR_IA32_FEATURE_CONTROL, + env->msr_ia32_feature_control); + } } if (env->mcg_cap) { int i; @@ -1361,6 +1437,9 @@ static int kvm_get_msrs(X86CPU *cpu) if (has_msr_misc_enable) { msrs[n++].index = MSR_IA32_MISC_ENABLE; } + if (has_msr_feature_control) { + msrs[n++].index = MSR_IA32_FEATURE_CONTROL; + } if (!env->tsc_valid) { msrs[n++].index = MSR_IA32_TSC; @@ -1386,6 +1465,19 @@ static int kvm_get_msrs(X86CPU *cpu) if (has_msr_kvm_steal_time) { msrs[n++].index = MSR_KVM_STEAL_TIME; } + if (has_msr_architectural_pmu) { + msrs[n++].index = MSR_CORE_PERF_FIXED_CTR_CTRL; + msrs[n++].index = MSR_CORE_PERF_GLOBAL_CTRL; + msrs[n++].index = MSR_CORE_PERF_GLOBAL_STATUS; + msrs[n++].index = MSR_CORE_PERF_GLOBAL_OVF_CTRL; + for (i = 0; i < MAX_FIXED_COUNTERS; i++) { + msrs[n++].index = MSR_CORE_PERF_FIXED_CTR0 + i; + } + for (i = 0; i < num_architectural_pmu_counters; i++) { + msrs[n++].index = MSR_P6_PERFCTR0 + i; + msrs[n++].index = MSR_P6_EVNTSEL0 + i; + } + } if (env->mcg_cap) { msrs[n++].index = MSR_MCG_STATUS; @@ -1402,7 +1494,8 @@ static int kvm_get_msrs(X86CPU *cpu) } for (i = 0; i < ret; i++) { - switch (msrs[i].index) { + uint32_t index = msrs[i].index; + switch (index) { case MSR_IA32_SYSENTER_CS: env->sysenter_cs = msrs[i].data; break; @@ -1459,6 +1552,9 @@ static int kvm_get_msrs(X86CPU *cpu) case MSR_IA32_MISC_ENABLE: env->msr_ia32_misc_enable = msrs[i].data; break; + case MSR_IA32_FEATURE_CONTROL: + env->msr_ia32_feature_control = msrs[i].data; + break; default: if (msrs[i].index >= MSR_MC0_CTL && msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) { @@ -1474,6 +1570,27 @@ static int kvm_get_msrs(X86CPU *cpu) case MSR_KVM_STEAL_TIME: env->steal_time_msr = msrs[i].data; break; + case MSR_CORE_PERF_FIXED_CTR_CTRL: + env->msr_fixed_ctr_ctrl = msrs[i].data; + break; + case MSR_CORE_PERF_GLOBAL_CTRL: + env->msr_global_ctrl = msrs[i].data; + break; + case MSR_CORE_PERF_GLOBAL_STATUS: + env->msr_global_status = msrs[i].data; + break; + case MSR_CORE_PERF_GLOBAL_OVF_CTRL: + env->msr_global_ovf_ctrl = msrs[i].data; + break; + case MSR_CORE_PERF_FIXED_CTR0 ... MSR_CORE_PERF_FIXED_CTR0 + MAX_FIXED_COUNTERS - 1: + env->msr_fixed_counters[index - MSR_CORE_PERF_FIXED_CTR0] = msrs[i].data; + break; + case MSR_P6_PERFCTR0 ... MSR_P6_PERFCTR0 + MAX_GP_COUNTERS - 1: + env->msr_gp_counters[index - MSR_P6_PERFCTR0] = msrs[i].data; + break; + case MSR_P6_EVNTSEL0 ... MSR_P6_EVNTSEL0 + MAX_GP_COUNTERS - 1: + env->msr_gp_evtsel[index - MSR_P6_EVNTSEL0] = msrs[i].data; + break; } } @@ -1724,6 +1841,12 @@ int kvm_arch_put_registers(CPUState *cpu, int level) return ret; } } + + ret = kvm_put_tscdeadline_msr(x86_cpu); + if (ret < 0) { + return ret; + } + ret = kvm_put_vcpu_events(x86_cpu, level); if (ret < 0) { return ret; diff --git a/target-i386/machine.c b/target-i386/machine.c index f9ec581faa..dc81cde535 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -435,6 +435,14 @@ static bool misc_enable_needed(void *opaque) return env->msr_ia32_misc_enable != MSR_IA32_MISC_ENABLE_DEFAULT; } +static bool feature_control_needed(void *opaque) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + + return env->msr_ia32_feature_control != 0; +} + static const VMStateDescription vmstate_msr_ia32_misc_enable = { .name = "cpu/msr_ia32_misc_enable", .version_id = 1, @@ -446,6 +454,58 @@ static const VMStateDescription vmstate_msr_ia32_misc_enable = { } }; +static const VMStateDescription vmstate_msr_ia32_feature_control = { + .name = "cpu/msr_ia32_feature_control", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT64(env.msr_ia32_feature_control, X86CPU), + VMSTATE_END_OF_LIST() + } +}; + +static bool pmu_enable_needed(void *opaque) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + int i; + + if (env->msr_fixed_ctr_ctrl || env->msr_global_ctrl || + env->msr_global_status || env->msr_global_ovf_ctrl) { + return true; + } + for (i = 0; i < MAX_FIXED_COUNTERS; i++) { + if (env->msr_fixed_counters[i]) { + return true; + } + } + for (i = 0; i < MAX_GP_COUNTERS; i++) { + if (env->msr_gp_counters[i] || env->msr_gp_evtsel[i]) { + return true; + } + } + + return false; +} + +static const VMStateDescription vmstate_msr_architectural_pmu = { + .name = "cpu/msr_architectural_pmu", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_UINT64(env.msr_fixed_ctr_ctrl, X86CPU), + VMSTATE_UINT64(env.msr_global_ctrl, X86CPU), + VMSTATE_UINT64(env.msr_global_status, X86CPU), + VMSTATE_UINT64(env.msr_global_ovf_ctrl, X86CPU), + VMSTATE_UINT64_ARRAY(env.msr_fixed_counters, X86CPU, MAX_FIXED_COUNTERS), + VMSTATE_UINT64_ARRAY(env.msr_gp_counters, X86CPU, MAX_GP_COUNTERS), + VMSTATE_UINT64_ARRAY(env.msr_gp_evtsel, X86CPU, MAX_GP_COUNTERS), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_x86_cpu = { .name = "cpu", .version_id = 12, @@ -571,6 +631,12 @@ const VMStateDescription vmstate_x86_cpu = { }, { .vmsd = &vmstate_msr_ia32_misc_enable, .needed = misc_enable_needed, + }, { + .vmsd = &vmstate_msr_ia32_feature_control, + .needed = feature_control_needed, + }, { + .vmsd = &vmstate_msr_architectural_pmu, + .needed = pmu_enable_needed, } , { /* empty */ } diff --git a/target-i386/translate.c b/target-i386/translate.c index 065a9d320e..6d879003b3 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -2413,7 +2413,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip) /* jump to same page: we can use a direct jump */ tcg_gen_goto_tb(tb_num); gen_jmp_im(eip); - tcg_gen_exit_tb((tcg_target_long)tb + tb_num); + tcg_gen_exit_tb((uintptr_t)tb + tb_num); } else { /* jump to another page: currently not optimized */ gen_jmp_im(eip); diff --git a/target-lm32/op_helper.c b/target-lm32/op_helper.c index 2dab9f27b4..8f5ef554d5 100644 --- a/target-lm32/op_helper.c +++ b/target-lm32/op_helper.c @@ -6,6 +6,8 @@ #include "hw/lm32/lm32_pic.h" #include "hw/char/lm32_juart.h" +#include "exec/softmmu_exec.h" + #if !defined(CONFIG_USER_ONLY) #define MMUSUFFIX _mmu #define SHIFT 0 diff --git a/target-lm32/translate.c b/target-lm32/translate.c index 1247287050..6ea0ecd63b 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -129,7 +129,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) likely(!dc->singlestep_enabled)) { tcg_gen_goto_tb(n); tcg_gen_movi_tl(cpu_pc, dest); - tcg_gen_exit_tb((tcg_target_long)tb + n); + tcg_gen_exit_tb((uintptr_t)tb + n); } else { tcg_gen_movi_tl(cpu_pc, dest); if (dc->singlestep_enabled) { diff --git a/target-m68k/translate.c b/target-m68k/translate.c index d562eebef3..0be0a96732 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -869,7 +869,7 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest) (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { tcg_gen_goto_tb(n); tcg_gen_movi_i32(QREG_PC, dest); - tcg_gen_exit_tb((tcg_target_long)tb + n); + tcg_gen_exit_tb((uintptr_t)tb + n); } else { gen_jmp_im(s, dest); tcg_gen_exit_tb(0); diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index cd4357703f..0673176957 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -138,7 +138,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { tcg_gen_goto_tb(n); tcg_gen_movi_tl(cpu_SR[SR_PC], dest); - tcg_gen_exit_tb((tcg_target_long)tb + n); + tcg_gen_exit_tb((uintptr_t)tb + n); } else { tcg_gen_movi_tl(cpu_SR[SR_PC], dest); tcg_gen_exit_tb(0); diff --git a/target-mips/helper.c b/target-mips/helper.c index 6feef7bcd6..33e0e88637 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -193,7 +193,7 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, } } #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/translate.c b/target-mips/translate.c index e2eb908cf3..ad43d59103 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -3581,7 +3581,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) likely(!ctx->singlestep_enabled)) { tcg_gen_goto_tb(n); gen_save_pc(dest); - tcg_gen_exit_tb((tcg_target_long)tb + n); + tcg_gen_exit_tb((uintptr_t)tb + n); } else { gen_save_pc(dest); if (ctx->singlestep_enabled) { diff --git a/target-moxie/helper.c b/target-moxie/helper.c index b12e4ffcaf..7859102ab7 100644 --- a/target-moxie/helper.c +++ b/target-moxie/helper.c @@ -25,6 +25,7 @@ #include "cpu.h" #include "mmu.h" #include "exec/exec-all.h" +#include "exec/softmmu_exec.h" #include "qemu/host-utils.h" #include "helper.h" diff --git a/target-moxie/translate.c b/target-moxie/translate.c index 8cc0bb7bfb..a93196f47b 100644 --- a/target-moxie/translate.c +++ b/target-moxie/translate.c @@ -135,7 +135,7 @@ static inline void gen_goto_tb(CPUMoxieState *env, DisasContext *ctx, !ctx->singlestep_enabled) { tcg_gen_goto_tb(n); tcg_gen_movi_i32(cpu_pc, dest); - tcg_gen_exit_tb((tcg_target_long)tb + n); + tcg_gen_exit_tb((uintptr_t)tb + n); } else { tcg_gen_movi_i32(cpu_pc, dest); if (ctx->singlestep_enabled) { diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index a6050ba6d8..723b77d3b4 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -198,7 +198,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) likely(!dc->singlestep_enabled)) { tcg_gen_movi_tl(cpu_pc, dest); tcg_gen_goto_tb(n); - tcg_gen_exit_tb((tcg_target_long)tb + n); + tcg_gen_exit_tb((uintptr_t)tb + n); } else { tcg_gen_movi_tl(cpu_pc, dest); if (dc->singlestep_enabled) { diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 711db083e0..422a6bbd2e 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -453,6 +453,8 @@ struct ppc_slb_t { #define MSR_RI 1 /* Recoverable interrupt 1 */ #define MSR_LE 0 /* Little-endian mode 1 hflags */ +#define LPCR_ILE (1 << (63-38)) + #define msr_sf ((env->msr >> MSR_SF) & 1) #define msr_isf ((env->msr >> MSR_ISF) & 1) #define msr_shv ((env->msr >> MSR_SHV) & 1) diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index e9fcad8ef6..e957761109 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -611,9 +611,19 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) tlb_flush(env, 1); } +#ifdef TARGET_PPC64 + if (excp_model == POWERPC_EXCP_POWER7) { + if (env->spr[SPR_LPCR] & LPCR_ILE) { + new_msr |= (target_ulong)1 << MSR_LE; + } + } else if (msr_ile) { + new_msr |= (target_ulong)1 << MSR_LE; + } +#else if (msr_ile) { new_msr |= (target_ulong)1 << MSR_LE; } +#endif /* Jump to handler */ vector = env->excp_vectors[excp]; diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 30a870ecb1..8a196c6cc1 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -419,7 +419,7 @@ int kvm_arch_init_vcpu(CPUState *cs) 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) { @@ -1136,7 +1136,7 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) } /* 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)); } @@ -1807,7 +1807,7 @@ int kvmppc_get_htab_fd(bool write) int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns) { - int64_t starttime = qemu_get_clock_ns(rt_clock); + int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); uint8_t buf[bufsize]; ssize_t rc; @@ -1823,7 +1823,7 @@ int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns) } } while ((rc != 0) && ((max_ns < 0) - || ((qemu_get_clock_ns(rt_clock) - starttime) < max_ns))); + || ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) < max_ns))); return (rc == 0) ? 1 : 0; } diff --git a/target-ppc/kvm_ppc.c b/target-ppc/kvm_ppc.c index 1b192a8038..f769acd44c 100644 --- a/target-ppc/kvm_ppc.c +++ b/target-ppc/kvm_ppc.c @@ -15,6 +15,7 @@ #include "qemu/timer.h" #include "kvm_ppc.h" #include "sysemu/device_tree.h" +#include "qemu/main-loop.h" #define PROC_DEVTREE_PATH "/proc/device-tree" @@ -24,7 +25,7 @@ static unsigned int kvmppc_timer_rate; 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 +35,7 @@ void kvmppc_init(void) * 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/mmu_helper.c b/target-ppc/mmu_helper.c index 5dd4e05f78..04a840b016 100644 --- a/target-ppc/mmu_helper.c +++ b/target-ppc/mmu_helper.c @@ -2061,7 +2061,7 @@ void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value) /* ESID = srnum */ rb |= ((uint32_t)srnum & 0xf) << 28; /* Set the valid bit */ - rb |= 1 << 27; + rb |= SLB_ESID_V; /* Index = ESID */ rb |= (uint32_t)srnum; @@ -2871,6 +2871,8 @@ void helper_booke206_tlbflush(CPUPPCState *env, uint32_t type) /*****************************************************************************/ +#include "exec/softmmu_exec.h" + #define MMUSUFFIX _mmu #define SHIFT 0 diff --git a/target-ppc/translate.c b/target-ppc/translate.c index f07d70d866..2da7bc740f 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -428,9 +428,9 @@ EXTRACT_HELPER(CRM, 12, 8); EXTRACT_HELPER(SR, 16, 4); /* mtfsf/mtfsfi */ -EXTRACT_HELPER(FPBF, 19, 3); +EXTRACT_HELPER(FPBF, 23, 3); EXTRACT_HELPER(FPIMM, 12, 4); -EXTRACT_HELPER(FPL, 21, 1); +EXTRACT_HELPER(FPL, 25, 1); EXTRACT_HELPER(FPFLM, 17, 8); EXTRACT_HELPER(FPW, 16, 1); @@ -3551,7 +3551,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) likely(!ctx->singlestep_enabled)) { tcg_gen_goto_tb(n); tcg_gen_movi_tl(cpu_nip, dest & ~3); - tcg_gen_exit_tb((tcg_target_long)tb + n); + tcg_gen_exit_tb((uintptr_t)tb + n); } else { tcg_gen_movi_tl(cpu_nip, dest & ~3); if (unlikely(ctx->singlestep_enabled)) { diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 13b290c597..d2645bad28 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 @@ -7226,7 +7227,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) PPC_SEGMENT_64B | PPC_SLBI | PPC_POPCNTB | PPC_POPCNTWD; pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX | PPC2_ISA205; - pcc->msr_mask = 0x800000000204FF36ULL; + pcc->msr_mask = 0x800000000204FF37ULL; pcc->mmu_model = POWERPC_MMU_2_06; #if defined(CONFIG_SOFTMMU) pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; @@ -8281,7 +8282,7 @@ PowerPCCPU *cpu_ppc_init(const char *cpu_model) 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; diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h index cbe2341b3b..ac0460eb30 100644 --- a/target-s390x/cpu-qom.h +++ b/target-s390x/cpu-qom.h @@ -36,6 +36,9 @@ * S390CPUClass: * @parent_realize: The parent class' realize handler. * @parent_reset: The parent class' reset handler. + * @load_normal: Performs a load normal. + * @cpu_reset: Performs a CPU reset. + * @initial_cpu_reset: Performs an initial CPU reset. * * An S/390 CPU model. */ @@ -46,6 +49,9 @@ typedef struct S390CPUClass { DeviceRealize parent_realize; void (*parent_reset)(CPUState *cpu); + void (*load_normal)(CPUState *cpu); + void (*cpu_reset)(CPUState *cpu); + void (*initial_cpu_reset)(CPUState *cpu); } S390CPUClass; /** diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index 6be6c084a7..3c89f8a767 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -65,7 +65,18 @@ static void s390_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.psw.addr = value; } -/* CPUClass::reset() */ +#if !defined(CONFIG_USER_ONLY) +/* S390CPUClass::load_normal() */ +static void s390_cpu_load_normal(CPUState *s) +{ + S390CPU *cpu = S390_CPU(s); + cpu->env.psw.addr = ldl_phys(4) & PSW_MASK_ESA_ADDR; + cpu->env.psw.mask = PSW_MASK_32 | PSW_MASK_64; + s390_add_running_cpu(cpu); +} +#endif + +/* S390CPUClass::cpu_reset() */ static void s390_cpu_reset(CPUState *s) { S390CPU *cpu = S390_CPU(s); @@ -73,6 +84,37 @@ static void s390_cpu_reset(CPUState *s) CPUS390XState *env = &cpu->env; s390_del_running_cpu(cpu); + scc->parent_reset(s); +#if !defined(CONFIG_USER_ONLY) + s->halted = 1; +#endif + tlb_flush(env, 1); +} + +/* S390CPUClass::initial_reset() */ +static void s390_cpu_initial_reset(CPUState *s) +{ + S390CPU *cpu = S390_CPU(s); + CPUS390XState *env = &cpu->env; + + s390_cpu_reset(s); + /* initial reset does not touch regs,fregs and aregs */ + memset(&env->fpc, 0, offsetof(CPUS390XState, breakpoints) - + offsetof(CPUS390XState, fpc)); + + /* architectured initial values for CR 0 and 14 */ + env->cregs[0] = CR0_RESET; + env->cregs[14] = CR14_RESET; +} + +/* CPUClass:reset() */ +static void s390_cpu_full_reset(CPUState *s) +{ + S390CPU *cpu = S390_CPU(s); + S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); + CPUS390XState *env = &cpu->env; + + s390_del_running_cpu(cpu); scc->parent_reset(s); @@ -129,8 +171,8 @@ static void s390_cpu_initfn(Object *obj) 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 */ @@ -169,8 +211,12 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) dc->realize = s390_cpu_realizefn; scc->parent_reset = cc->reset; - cc->reset = s390_cpu_reset; - +#if !defined(CONFIG_USER_ONLY) + scc->load_normal = s390_cpu_load_normal; +#endif + scc->cpu_reset = s390_cpu_reset; + scc->initial_cpu_reset = s390_cpu_initial_reset; + cc->reset = s390_cpu_full_reset; cc->do_interrupt = s390_cpu_do_interrupt; cc->dump_state = s390_cpu_dump_state; cc->set_pc = s390_cpu_set_pc; diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 65bef8625f..8be5648806 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -228,6 +228,8 @@ typedef struct CPUS390XState { #undef PSW_MASK_CC #undef PSW_MASK_PM #undef PSW_MASK_64 +#undef PSW_MASK_32 +#undef PSW_MASK_ESA_ADDR #define PSW_MASK_PER 0x4000000000000000ULL #define PSW_MASK_DAT 0x0400000000000000ULL @@ -243,6 +245,7 @@ typedef struct CPUS390XState { #define PSW_MASK_PM 0x00000F0000000000ULL #define PSW_MASK_64 0x0000000100000000ULL #define PSW_MASK_32 0x0000000080000000ULL +#define PSW_MASK_ESA_ADDR 0x000000007fffffffULL #undef PSW_ASC_PRIMARY #undef PSW_ASC_ACCREG @@ -400,6 +403,7 @@ void cpu_unlock(void); typedef struct SubchDev SubchDev; #ifndef CONFIG_USER_ONLY +extern void io_subsystem_reset(void); SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, uint16_t schid); bool css_subch_visible(SubchDev *sch); @@ -1047,6 +1051,9 @@ uint32_t set_cc_nz_f64(float64 v); uint32_t set_cc_nz_f128(float128 v); /* misc_helper.c */ +#ifndef CONFIG_USER_ONLY +void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3); +#endif void program_interrupt(CPUS390XState *env, uint32_t code, int ilen); void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, uintptr_t retaddr); @@ -1062,6 +1069,7 @@ void kvm_s390_enable_css_support(S390CPU *cpu); int kvm_s390_get_registers_partial(CPUState *cpu); int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, int vq, bool assign); +int kvm_s390_cpu_restart(S390CPU *cpu); #else static inline void kvm_s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id, @@ -1086,8 +1094,20 @@ static inline int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, { return -ENOSYS; } +static inline int kvm_s390_cpu_restart(S390CPU *cpu) +{ + return -ENOSYS; +} #endif +static inline int s390_cpu_restart(S390CPU *cpu) +{ + if (kvm_enabled()) { + return kvm_s390_cpu_restart(cpu); + } + return -ENOSYS; +} + static inline void s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id, uint16_t subchannel_nr, diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 26d18e3bcf..185c8f5a45 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -72,6 +72,7 @@ #define PRIV_XSCH 0x76 #define PRIV_SQBS 0x8a #define PRIV_EQBS 0x9c +#define DIAG_IPL 0x308 #define DIAG_KVM_HYPERCALL 0x500 #define DIAG_KVM_BREAKPOINT 0x501 @@ -578,32 +579,45 @@ static int handle_hypercall(S390CPU *cpu, struct kvm_run *run) return 0; } +static void kvm_handle_diag_308(S390CPU *cpu, struct kvm_run *run) +{ + uint64_t r1, r3; + + cpu_synchronize_state(CPU(cpu)); + r1 = (run->s390_sieic.ipa & 0x00f0) >> 8; + r3 = run->s390_sieic.ipa & 0x000f; + handle_diag_308(&cpu->env, r1, r3); +} + static int handle_diag(S390CPU *cpu, struct kvm_run *run, int ipb_code) { int r = 0; switch (ipb_code) { - case DIAG_KVM_HYPERCALL: - r = handle_hypercall(cpu, run); - break; - case DIAG_KVM_BREAKPOINT: - sleep(10); - break; - default: - DPRINTF("KVM: unknown DIAG: 0x%x\n", ipb_code); - r = -1; - break; + case DIAG_IPL: + kvm_handle_diag_308(cpu, run); + break; + case DIAG_KVM_HYPERCALL: + r = handle_hypercall(cpu, run); + break; + case DIAG_KVM_BREAKPOINT: + sleep(10); + break; + default: + DPRINTF("KVM: unknown DIAG: 0x%x\n", ipb_code); + r = -1; + break; } return r; } -static int s390_cpu_restart(S390CPU *cpu) +int kvm_s390_cpu_restart(S390CPU *cpu) { 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: KVM cpu restart: %p\n", &cpu->env); return 0; } @@ -672,7 +686,7 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) switch (order_code) { case SIGP_RESTART: - r = s390_cpu_restart(target_cpu); + r = kvm_s390_cpu_restart(target_cpu); break; case SIGP_STORE_STATUS_ADDR: r = s390_store_status(target_env, parameter); diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index 09301d0a6f..4afd7dab1c 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -31,6 +31,7 @@ #if !defined(CONFIG_USER_ONLY) #include "exec/softmmu_exec.h" +#include "sysemu/cpus.h" #include "sysemu/sysemu.h" #endif @@ -179,6 +180,75 @@ uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2) return r; } +#ifndef CONFIG_USER_ONLY +static void cpu_reset_all(void) +{ + CPUState *cpu; + S390CPUClass *scc; + + for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) { + scc = S390_CPU_GET_CLASS(CPU(cpu)); + scc->cpu_reset(CPU(cpu)); + } +} + +static int load_normal_reset(S390CPU *cpu) +{ + S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); + + pause_all_vcpus(); + cpu_synchronize_all_states(); + cpu_reset_all(); + io_subsystem_reset(); + scc->initial_cpu_reset(CPU(cpu)); + scc->load_normal(CPU(cpu)); + cpu_synchronize_all_post_reset(); + resume_all_vcpus(); + return 0; +} + +#define DIAG_308_RC_NO_CONF 0x0102 +#define DIAG_308_RC_INVALID 0x0402 +void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) +{ + uint64_t addr = env->regs[r1]; + uint64_t subcode = env->regs[r3]; + + if (env->psw.mask & PSW_MASK_PSTATE) { + program_interrupt(env, PGM_PRIVILEGED, ILEN_LATER_INC); + return; + } + + if ((subcode & ~0x0ffffULL) || (subcode > 6)) { + program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); + return; + } + + switch (subcode) { + case 1: + load_normal_reset(s390_env_get_cpu(env)); + break; + case 5: + if ((r1 & 1) || (addr & 0x0fffULL)) { + program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); + return; + } + env->regs[r1+1] = DIAG_308_RC_INVALID; + return; + case 6: + if ((r1 & 1) || (addr & 0x0fffULL)) { + program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); + return; + } + env->regs[r1+1] = DIAG_308_RC_NO_CONF; + return; + default: + hw_error("Unhandled diag308 subcode %" PRIx64, subcode); + break; + } +} +#endif + /* DIAG */ uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem, uint64_t code) @@ -225,7 +295,7 @@ static inline uint64_t clock_value(CPUS390XState *env) 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 +318,7 @@ void HELPER(sckc)(CPUS390XState *env, uint64_t time) /* 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 +338,7 @@ void HELPER(spt)(CPUS390XState *env, uint64_t time) /* 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-s390x/translate.c b/target-s390x/translate.c index 1fb76c5264..afe90eb8be 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -1169,7 +1169,7 @@ static ExitStatus help_goto_direct(DisasContext *s, uint64_t dest) update_cc_op(s); tcg_gen_goto_tb(0); tcg_gen_movi_i64(psw_addr, dest); - tcg_gen_exit_tb((tcg_target_long)s->tb); + tcg_gen_exit_tb((uintptr_t)s->tb); return EXIT_GOTO_TB; } else { tcg_gen_movi_i64(psw_addr, dest); @@ -1227,13 +1227,13 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c, /* Branch not taken. */ tcg_gen_goto_tb(0); tcg_gen_movi_i64(psw_addr, s->next_pc); - tcg_gen_exit_tb((tcg_target_long)s->tb + 0); + tcg_gen_exit_tb((uintptr_t)s->tb + 0); /* Branch taken. */ gen_set_label(lab); tcg_gen_goto_tb(1); tcg_gen_movi_i64(psw_addr, dest); - tcg_gen_exit_tb((tcg_target_long)s->tb + 1); + tcg_gen_exit_tb((uintptr_t)s->tb + 1); ret = EXIT_GOTO_TB; } else { @@ -1256,7 +1256,7 @@ static ExitStatus help_branch(DisasContext *s, DisasCompare *c, update_cc_op(s); tcg_gen_goto_tb(0); tcg_gen_movi_i64(psw_addr, s->next_pc); - tcg_gen_exit_tb((tcg_target_long)s->tb + 0); + tcg_gen_exit_tb((uintptr_t)s->tb + 0); gen_set_label(lab); if (is_imm) { diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 59f3d47023..c06b29f1dc 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -186,7 +186,7 @@ static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest) /* Use a direct jump if in same page and singlestep not enabled */ tcg_gen_goto_tb(n); tcg_gen_movi_i32(cpu_pc, dest); - tcg_gen_exit_tb((tcg_target_long)tb + n); + tcg_gen_exit_tb((uintptr_t)tb + n); } else { tcg_gen_movi_i32(cpu_pc, dest); if (ctx->singlestep_enabled) diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 093e0e2c78..36615f1979 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -322,7 +322,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, tcg_gen_goto_tb(tb_num); tcg_gen_movi_tl(cpu_pc, pc); tcg_gen_movi_tl(cpu_npc, npc); - tcg_gen_exit_tb((tcg_target_long)tb + tb_num); + tcg_gen_exit_tb((uintptr_t)tb + tb_num); } else { /* jump to another page: currently not optimized */ tcg_gen_movi_tl(cpu_pc, pc); diff --git a/target-unicore32/op_helper.c b/target-unicore32/op_helper.c index 6443ffec1c..4f9f41eb36 100644 --- a/target-unicore32/op_helper.c +++ b/target-unicore32/op_helper.c @@ -239,6 +239,8 @@ uint32_t HELPER(ror_cc)(CPUUniCore32State *env, uint32_t x, uint32_t i) } #ifndef CONFIG_USER_ONLY +#include "exec/softmmu_exec.h" + #define MMUSUFFIX _mmu #define SHIFT 0 diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index 68be1c64e0..1246895f86 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -1100,7 +1100,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { tcg_gen_goto_tb(n); gen_set_pc_im(dest); - tcg_gen_exit_tb((tcg_target_long)tb + n); + tcg_gen_exit_tb((uintptr_t)tb + n); } else { gen_set_pc_im(dest); tcg_gen_exit_tb(0); diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c index 6ca912c5bb..cf970257db 100644 --- a/target-xtensa/op_helper.c +++ b/target-xtensa/op_helper.c @@ -28,6 +28,7 @@ #include "cpu.h" #include "helper.h" #include "qemu/host-utils.h" +#include "exec/softmmu_exec.h" static void do_unaligned_access(CPUXtensaState *env, target_ulong addr, int is_write, int is_user, uintptr_t retaddr); @@ -390,7 +391,7 @@ void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, uint32_t intlevel) } 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); diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 504cc539e3..24343bdf60 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -400,7 +400,7 @@ static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot) } else { if (slot >= 0) { tcg_gen_goto_tb(slot); - tcg_gen_exit_tb((tcg_target_long)dc->tb + slot); + tcg_gen_exit_tb((uintptr_t)dc->tb + slot); } else { tcg_gen_exit_tb(0); } diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c index 41a17f8a62..6379df1f68 100644 --- a/tcg/aarch64/tcg-target.c +++ b/tcg/aarch64/tcg-target.c @@ -88,7 +88,7 @@ static inline void reloc_pc19(void *code_ptr, tcg_target_long target) } static inline void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) + intptr_t value, intptr_t addend) { value += addend; @@ -423,14 +423,14 @@ static inline void tcg_out_mov(TCGContext *s, } static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { tcg_out_ldst(s, (type == TCG_TYPE_I64) ? LDST_64 : LDST_32, LDST_LD, arg, arg1, arg2); } static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { tcg_out_ldst(s, (type == TCG_TYPE_I64) ? LDST_64 : LDST_32, LDST_ST, arg, arg1, arg2); @@ -778,8 +778,6 @@ static inline void tcg_out_nop(TCGContext *s) } #ifdef CONFIG_SOFTMMU -#include "exec/softmmu_defs.h" - /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h index 51e50920b2..d3a1bc2437 100644 --- a/tcg/aarch64/tcg-target.h +++ b/tcg/aarch64/tcg-target.h @@ -61,6 +61,8 @@ typedef enum { #define TCG_TARGET_HAS_sub2_i32 0 #define TCG_TARGET_HAS_mulu2_i32 0 #define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_div_i64 0 #define TCG_TARGET_HAS_rem_i64 0 @@ -87,13 +89,14 @@ typedef enum { #define TCG_TARGET_HAS_sub2_i64 0 #define TCG_TARGET_HAS_mulu2_i64 0 #define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 enum { TCG_AREG0 = TCG_REG_X19, }; -static inline void flush_icache_range(tcg_target_ulong start, - tcg_target_ulong stop) +static inline void flush_icache_range(uintptr_t start, uintptr_t stop) { __builtin___clear_cache((char *)start, (char *)stop); } diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 6c4854dbb0..eb0e84ce44 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -108,21 +108,21 @@ static const int tcg_target_call_oarg_regs[2] = { #define TCG_REG_TMP TCG_REG_R12 -static inline void reloc_abs32(void *code_ptr, tcg_target_long target) +static inline void reloc_abs32(void *code_ptr, intptr_t target) { *(uint32_t *) code_ptr = target; } -static inline void reloc_pc24(void *code_ptr, tcg_target_long target) +static inline void reloc_pc24(void *code_ptr, intptr_t target) { - uint32_t offset = ((target - ((tcg_target_long) code_ptr + 8)) >> 2); + uint32_t offset = ((target - ((intptr_t)code_ptr + 8)) >> 2); *(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & ~0xffffff) | (offset & 0xffffff); } static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) + intptr_t value, intptr_t addend) { switch (type) { case R_ARM_ABS32: @@ -1058,8 +1058,6 @@ static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index) #ifdef CONFIG_SOFTMMU -#include "exec/softmmu_defs.h" - /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -2065,13 +2063,13 @@ static void tcg_target_init(TCGContext *s) } static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { tcg_out_ld32u(s, COND_AL, arg, arg1, arg2); } static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { tcg_out_st32(s, COND_AL, arg, arg1, arg2); } diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 5cd9d6a679..9482bfa993 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -80,6 +80,8 @@ extern bool use_idiv_instructions; #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_muls2_i32 1 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_div_i32 use_idiv_instructions #define TCG_TARGET_HAS_rem_i32 0 @@ -90,15 +92,14 @@ enum { TCG_AREG0 = TCG_REG_R6, }; -static inline void flush_icache_range(tcg_target_ulong start, - tcg_target_ulong stop) +static inline void flush_icache_range(uintptr_t start, uintptr_t stop) { #if QEMU_GNUC_PREREQ(4, 1) __builtin___clear_cache((char *) start, (char *) stop); #else - register unsigned long _beg __asm ("a1") = start; - register unsigned long _end __asm ("a2") = stop; - register unsigned long _flg __asm ("a3") = 0; + register uintptr_t _beg __asm("a1") = start; + register uintptr_t _end __asm("a2") = stop; + register uintptr_t _flg __asm("a3") = 0; __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); #endif } diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 68f77ba4dd..236b39c31f 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -22,6 +22,10 @@ * THE SOFTWARE. */ +#if TCG_TARGET_REG_BITS != 32 +#error unsupported +#endif + #ifndef NDEBUG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { "%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7", @@ -145,14 +149,14 @@ static int reassemble_21(int as21) #define R_PARISC_PCREL12F R_PARISC_NONE static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) + intptr_t value, intptr_t addend) { uint32_t *insn_ptr = (uint32_t *)code_ptr; uint32_t insn = *insn_ptr; - tcg_target_long pcrel; + intptr_t pcrel; value += addend; - pcrel = (value - ((tcg_target_long)code_ptr + 8)) >> 2; + pcrel = (value - ((intptr_t)code_ptr + 8)) >> 2; switch (type) { case R_PARISC_PCREL12F: @@ -388,14 +392,14 @@ static void tcg_out_ldst(TCGContext *s, int ret, int addr, /* This function is required by tcg.c. */ static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { tcg_out_ldst(s, ret, arg1, arg2, INSN_LDW); } /* This function is required by tcg.c. */ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg ret, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { tcg_out_ldst(s, ret, arg1, arg2, INSN_STW); } @@ -906,8 +910,6 @@ static void tcg_out_movcond(TCGContext *s, int cond, TCGArg ret, } #if defined(CONFIG_SOFTMMU) -#include "exec/softmmu_defs.h" - /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h index 25467bdd43..122edce7a7 100644 --- a/tcg/hppa/tcg-target.h +++ b/tcg/hppa/tcg-target.h @@ -25,10 +25,6 @@ #ifndef TCG_TARGET_HPPA #define TCG_TARGET_HPPA 1 -#if TCG_TARGET_REG_BITS != 32 -#error unsupported -#endif - #define TCG_TARGET_WORDS_BIGENDIAN #define TCG_TARGET_NB_REGS 32 @@ -100,6 +96,8 @@ typedef enum { #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, 0, rs */ @@ -109,8 +107,7 @@ typedef enum { #define TCG_AREG0 TCG_REG_R17 -static inline void flush_icache_range(tcg_target_ulong start, - tcg_target_ulong stop) +static inline void flush_icache_range(uintptr_t start, uintptr_t stop) { start &= ~31; while (start <= stop) { diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 87eeab3d30..c1f07415ab 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -112,7 +112,7 @@ static bool have_cmov; static uint8_t *tb_ret_addr; static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) + intptr_t value, intptr_t addend) { value += addend; switch(type) { @@ -190,11 +190,11 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) /* 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; @@ -430,8 +430,7 @@ static void tcg_out_modrm(TCGContext *s, int opc, int r, int rm) that will follow the instruction. */ static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm, - int index, int shift, - tcg_target_long offset) + int index, int shift, intptr_t offset) { int mod, len; @@ -439,8 +438,8 @@ static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm, if (TCG_TARGET_REG_BITS == 64) { /* Try for a rip-relative addressing mode. This has replaced the 32-bit-mode absolute addressing encoding. */ - tcg_target_long pc = (tcg_target_long)s->code_ptr + 5 + ~rm; - tcg_target_long disp = offset - pc; + intptr_t pc = (intptr_t)s->code_ptr + 5 + ~rm; + intptr_t disp = offset - pc; if (disp == (int32_t)disp) { tcg_out_opc(s, opc, r, 0, 0); tcg_out8(s, (LOWREGMASK(r) << 3) | 5); @@ -514,7 +513,7 @@ static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm, /* A simplification of the above with no index or shift. */ static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, - int rm, tcg_target_long offset) + int rm, intptr_t offset) { tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset); } @@ -541,20 +540,34 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type, 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 - ((uintptr_t)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) @@ -581,19 +594,27 @@ static inline void tcg_out_pop(TCGContext *s, int reg) } static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0); tcg_out_modrm_offset(s, opc, ret, arg1, arg2); } static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0); 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. */ @@ -735,7 +756,7 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small) TCGLabel *l = &s->labels[label_index]; if (l->has_value) { - val = l->u.value - (tcg_target_long)s->code_ptr; + val = l->u.value - (intptr_t)s->code_ptr; val1 = val - 2; if ((int8_t)val1 == val1) { if (opc == -1) { @@ -975,9 +996,9 @@ static void tcg_out_movcond64(TCGContext *s, TCGCond cond, TCGArg dest, } #endif -static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest) +static void tcg_out_branch(TCGContext *s, int call, uintptr_t dest) { - tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5; + intptr_t disp = dest - (intptr_t)s->code_ptr - 5; if (disp == (int32_t)disp) { tcg_out_opc(s, call ? OPC_CALL_Jz : OPC_JMP_long, 0, 0, 0); @@ -989,36 +1010,35 @@ static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest) } } -static inline void tcg_out_calli(TCGContext *s, tcg_target_long dest) +static inline void tcg_out_calli(TCGContext *s, uintptr_t dest) { tcg_out_branch(s, 1, dest); } -static void tcg_out_jmp(TCGContext *s, tcg_target_long dest) +static void tcg_out_jmp(TCGContext *s, uintptr_t dest) { tcg_out_branch(s, 0, dest); } #if defined(CONFIG_SOFTMMU) - -#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_ldub_mmu, + helper_ret_lduw_mmu, + helper_ret_ldul_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, @@ -1062,33 +1082,46 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, const int addrlo = args[addrlo_idx]; const int r0 = TCG_REG_L0; const int r1 = TCG_REG_L1; - TCGType type = TCG_TYPE_I32; - int rexw = 0; + TCGType ttype = TCG_TYPE_I32; + TCGType htype = TCG_TYPE_I32; + int trexw = 0, hrexw = 0; - if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 64) { - type = TCG_TYPE_I64; - rexw = P_REXW; + if (TCG_TARGET_REG_BITS == 64) { + if (TARGET_LONG_BITS == 64) { + ttype = TCG_TYPE_I64; + trexw = P_REXW; + } + if (TCG_TYPE_PTR == TCG_TYPE_I64) { + htype = TCG_TYPE_I64; + hrexw = P_REXW; + } } - tcg_out_mov(s, type, r0, addrlo); - tcg_out_mov(s, type, r1, addrlo); + tcg_out_mov(s, htype, r0, addrlo); + tcg_out_mov(s, ttype, r1, addrlo); - tcg_out_shifti(s, SHIFT_SHR + rexw, r0, + tcg_out_shifti(s, SHIFT_SHR + hrexw, r0, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); - tgen_arithi(s, ARITH_AND + rexw, r1, + tgen_arithi(s, ARITH_AND + trexw, r1, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0); - tgen_arithi(s, ARITH_AND + rexw, r0, + tgen_arithi(s, ARITH_AND + hrexw, r0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0); - tcg_out_modrm_sib_offset(s, OPC_LEA + P_REXW, r0, TCG_AREG0, r0, 0, + tcg_out_modrm_sib_offset(s, OPC_LEA + hrexw, r0, TCG_AREG0, r0, 0, offsetof(CPUArchState, tlb_table[mem_index][0]) + which); /* cmp 0(r0), r1 */ - tcg_out_modrm_offset(s, OPC_CMP_GvEv + rexw, r1, r0, 0); + tcg_out_modrm_offset(s, OPC_CMP_GvEv + trexw, r1, r0, 0); - tcg_out_mov(s, type, r1, addrlo); + /* Prepare for both the fast path add of the tlb addend, and the slow + path function argument setup. There are two cases worth note: + For 32-bit guest and x86_64 host, MOVL zero-extends the guest address + before the fastpath ADDQ below. For 64-bit guest and x32 host, MOVQ + copies the entire guest address for the slow path, while truncation + for the 32-bit host happens with the fastpath ADDL below. */ + tcg_out_mov(s, ttype, r1, addrlo); /* jne slow_path */ tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0); @@ -1108,7 +1141,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, /* TLB Hit. */ /* add addend(r0), r1 */ - tcg_out_modrm_offset(s, OPC_ADD_GvEv + P_REXW, r1, r0, + tcg_out_modrm_offset(s, OPC_ADD_GvEv + hrexw, r1, r0, offsetof(CPUTLBEntry, addend) - which); } #elif defined(__x86_64__) && defined(__linux__) @@ -1130,8 +1163,7 @@ static inline void setup_guest_base_seg(void) { } #endif /* SOFTMMU */ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi, - int base, tcg_target_long ofs, int seg, - int sizeop) + int base, intptr_t ofs, int seg, int sizeop) { #ifdef TARGET_WORDS_BIGENDIAN const int bswap = 1; @@ -1281,7 +1313,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, } static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi, - int base, tcg_target_long ofs, int seg, + int base, intptr_t ofs, int seg, int sizeop) { #ifdef TARGET_WORDS_BIGENDIAN @@ -1449,22 +1481,12 @@ static void add_qemu_ldst_label(TCGContext *s, /* * 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 +1494,36 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *label) *(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; - } - 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 + 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; - tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]); + if (TARGET_LONG_BITS == 64) { + tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs); + ofs += 4; + } - /* 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; + tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, l->mem_index); + ofs += 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); + tcg_out_sti(s, TCG_TYPE_I32, TCG_REG_ESP, ofs, (uintptr_t)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], + (uintptr_t)l->raddr); } -#endif + tcg_out_calli(s, (uintptr_t)qemu_ld_helpers[s_bits]); + + data_reg = l->datalo_reg; switch(opc) { case 0 | 4: tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW); @@ -1525,30 +1531,27 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *label) case 1 | 4: tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW); break; - case 0: - tcg_out_ext8u(s, data_reg, TCG_REG_EAX); - break; - case 1: - tcg_out_ext16u(s, data_reg, TCG_REG_EAX); - break; - case 2: - tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX); - break; #if TCG_TARGET_REG_BITS == 64 case 2 | 4: tcg_out_ext32s(s, data_reg, TCG_REG_EAX); break; #endif + case 0: + case 1: + /* Note that the helpers have zero-extended to tcg_target_long. */ + case 2: + tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX); + break; case 3: if (TCG_TARGET_REG_BITS == 64) { tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX); } 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 +1559,18 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *label) } /* Jump to the code corresponding to next IR of qemu_st */ - tcg_out_jmp(s, (tcg_target_long)raddr); + tcg_out_jmp(s, (uintptr_t)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]; + TCGReg retaddr; /* resolve label address */ *(uint32_t *)label_ptr[0] = (uint32_t)(s->code_ptr - label_ptr[0] - 4); @@ -1585,61 +1578,55 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *label) *(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; - tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]); + if (TARGET_LONG_BITS == 64) { + tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs); + ofs += 4; + } - /* 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; + 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; - 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); + retaddr = TCG_REG_EAX; + tcg_out_movi(s, TCG_TYPE_I32, retaddr, (uintptr_t)l->raddr); + tcg_out_st(s, TCG_TYPE_I32, retaddr, TCG_REG_ESP, ofs); + } 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_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); + + if (ARRAY_SIZE(tcg_target_call_iarg_regs) > 4) { + retaddr = tcg_target_call_iarg_regs[4]; + tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr); + } else { + retaddr = TCG_REG_RAX; + tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr); + tcg_out_st(s, TCG_TYPE_PTR, retaddr, TCG_REG_ESP, 0); + } } - /* Jump to the code corresponding to next IR of qemu_st */ - tcg_out_jmp(s, (tcg_target_long)raddr); + /* "Tail call" to the helper, with the return address back inline. */ + tcg_out_push(s, retaddr); + tcg_out_jmp(s, (uintptr_t)qemu_st_helpers[s_bits]); } /* @@ -1680,7 +1667,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, switch(opc) { case INDEX_op_exit_tb: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, args[0]); - tcg_out_jmp(s, (tcg_target_long) tb_ret_addr); + tcg_out_jmp(s, (uintptr_t)tb_ret_addr); break; case INDEX_op_goto_tb: if (s->tb_jmp_offset) { @@ -1691,7 +1678,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, } else { /* indirect jump method */ tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1, - (tcg_target_long)(s->tb_next + args[0])); + (intptr_t)(s->tb_next + args[0])); } s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; break; @@ -2384,7 +2371,7 @@ static DebugFrame debug_frame = { #if defined(ELF_HOST_MACHINE) void tcg_register_jit(void *buf, size_t buf_size) { - debug_frame.fde.func_start = (tcg_target_long) buf; + debug_frame.fde.func_start = (uintptr_t)buf; debug_frame.fde.func_len = buf_size; tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index e3f6bb965f..d32d7ef6f0 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -24,12 +24,14 @@ #ifndef TCG_TARGET_I386 #define TCG_TARGET_I386 1 -//#define TCG_TARGET_WORDS_BIGENDIAN +#undef TCG_TARGET_WORDS_BIGENDIAN -#if TCG_TARGET_REG_BITS == 64 -# define TCG_TARGET_NB_REGS 16 +#ifdef __x86_64__ +# define TCG_TARGET_REG_BITS 64 +# define TCG_TARGET_NB_REGS 16 #else -# define TCG_TARGET_NB_REGS 8 +# define TCG_TARGET_REG_BITS 32 +# define TCG_TARGET_NB_REGS 8 #endif typedef enum { @@ -96,6 +98,8 @@ typedef enum { #define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_mulu2_i32 1 #define TCG_TARGET_HAS_muls2_i32 1 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div2_i64 1 @@ -122,6 +126,8 @@ typedef enum { #define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_mulu2_i64 1 #define TCG_TARGET_HAS_muls2_i64 1 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 #endif #define TCG_TARGET_deposit_i32_valid(ofs, len) \ @@ -135,8 +141,7 @@ typedef enum { # define TCG_AREG0 TCG_REG_EBP #endif -static inline void flush_icache_range(tcg_target_ulong start, - tcg_target_ulong stop) +static inline void flush_icache_range(uintptr_t start, uintptr_t stop) { } diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index 2373d9ef79..cd4f1ae1db 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -668,16 +668,16 @@ static inline uint64_t tcg_opc_x3(int qp, uint64_t opc, uint64_t imm) * Relocations */ -static inline void reloc_pcrel21b (void *pc, tcg_target_long target) +static inline void reloc_pcrel21b(void *pc, intptr_t target) { uint64_t imm; int64_t disp; int slot; - slot = (tcg_target_long) pc & 3; - pc = (void *)((tcg_target_long) pc & ~3); + slot = (intptr_t)pc & 3; + pc = (void *)((intptr_t)pc & ~3); - disp = target - (tcg_target_long) pc; + disp = target - (intptr_t)pc; imm = (uint64_t) disp >> 4; switch(slot) { @@ -728,12 +728,12 @@ static inline uint64_t get_reloc_pcrel21b (void *pc) } } -static inline void reloc_pcrel60b (void *pc, tcg_target_long target) +static inline void reloc_pcrel60b(void *pc, intptr_t target) { int64_t disp; uint64_t imm; - disp = target - (tcg_target_long) pc; + disp = target - (intptr_t)pc; imm = (uint64_t) disp >> 4; *(uint64_t *)(pc + 8) = (*(uint64_t *)(pc + 8) & 0xf700000fff800000ull) @@ -759,7 +759,7 @@ static inline uint64_t get_reloc_pcrel60b (void *pc) static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) + intptr_t value, intptr_t addend) { value += addend; switch (type) { @@ -993,7 +993,7 @@ static inline void tcg_out_st_rel(TCGContext *s, uint64_t opc_m4, TCGArg arg, } static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { if (type == TCG_TYPE_I32) { tcg_out_ld_rel(s, OPC_LD4_M1, arg, arg1, arg2); @@ -1003,7 +1003,7 @@ static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, } static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { if (type == TCG_TYPE_I32) { tcg_out_st_rel(s, OPC_ST4_M4, arg, arg1, arg2); @@ -1490,9 +1490,6 @@ static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret, } #if defined(CONFIG_SOFTMMU) - -#include "exec/softmmu_defs.h" - /* Load and compare a TLB entry, and return the result in (p6, p7). R2 is loaded with the address of the addend TLB entry. R57 is loaded with the address, zero extented on 32-bit targets. */ diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index f32d5199cb..4330c9cdd3 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -146,6 +146,10 @@ typedef enum { #define TCG_TARGET_HAS_mulu2_i64 0 #define TCG_TARGET_HAS_muls2_i32 0 #define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_mulsh_i64 0 #define TCG_TARGET_deposit_i32_valid(ofs, len) ((len) <= 16) #define TCG_TARGET_deposit_i64_valid(ofs, len) ((len) <= 16) @@ -158,8 +162,7 @@ typedef enum { #define TCG_AREG0 TCG_REG_R7 -static inline void flush_icache_range(tcg_target_ulong start, - tcg_target_ulong stop) +static inline void flush_icache_range(uintptr_t start, uintptr_t stop) { start = start & ~(32UL - 1UL); stop = (stop + (32UL - 1UL)) & ~(32UL - 1UL); diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index 793532ec95..5f0a65b4ea 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -108,33 +108,33 @@ static const TCGReg tcg_target_call_oarg_regs[2] = { static uint8_t *tb_ret_addr; -static inline uint32_t reloc_lo16_val (void *pc, tcg_target_long target) +static inline uint32_t reloc_lo16_val(void *pc, intptr_t target) { return target & 0xffff; } -static inline void reloc_lo16 (void *pc, tcg_target_long target) +static inline void reloc_lo16(void *pc, intptr_t target) { *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff) | reloc_lo16_val(pc, target); } -static inline uint32_t reloc_hi16_val (void *pc, tcg_target_long target) +static inline uint32_t reloc_hi16_val(void *pc, intptr_t target) { return (target >> 16) & 0xffff; } -static inline void reloc_hi16 (void *pc, tcg_target_long target) +static inline void reloc_hi16(void *pc, intptr_t target) { *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff) | reloc_hi16_val(pc, target); } -static inline uint32_t reloc_pc16_val (void *pc, tcg_target_long target) +static inline uint32_t reloc_pc16_val(void *pc, intptr_t target) { int32_t disp; - disp = target - (tcg_target_long) pc - 4; + disp = target - (intptr_t)pc - 4; if (disp != (disp << 14) >> 14) { tcg_abort (); } @@ -157,14 +157,14 @@ static inline uint32_t reloc_26_val (void *pc, tcg_target_long target) return (target >> 2) & 0x3ffffff; } -static inline void reloc_pc26 (void *pc, tcg_target_long target) +static inline void reloc_pc26(void *pc, intptr_t target) { *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3ffffff) | reloc_26_val(pc, target); } static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) + intptr_t value, intptr_t addend) { value += addend; switch(type) { @@ -422,83 +422,83 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg) { -#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) - tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); -#else - /* ret and arg can't be register at */ - if (ret == TCG_REG_AT || arg == TCG_REG_AT) { - tcg_abort(); - } + if (use_mips32r2_instructions) { + tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); + } else { + /* ret and arg can't be register at */ + if (ret == TCG_REG_AT || arg == TCG_REG_AT) { + tcg_abort(); + } - tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8); - tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8); - tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00); - tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); -#endif + tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8); + tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8); + tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); + } } static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg) { -#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) - tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); - tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret); -#else - /* ret and arg can't be register at */ - if (ret == TCG_REG_AT || arg == TCG_REG_AT) { - tcg_abort(); - } + if (use_mips32r2_instructions) { + tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); + tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret); + } else { + /* ret and arg can't be register at */ + if (ret == TCG_REG_AT || arg == TCG_REG_AT) { + tcg_abort(); + } - tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8); - tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); - tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16); - tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); -#endif + tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8); + tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); + tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); + } } static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg) { -#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) - tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); - tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16); -#else - /* ret and arg must be different and can't be register at */ - if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) { - tcg_abort(); - } + if (use_mips32r2_instructions) { + tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg); + tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16); + } else { + /* ret and arg must be different and can't be register at */ + if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) { + tcg_abort(); + } - tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); + tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); - tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24); - tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); + tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); - tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00); - tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8); - tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); + tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00); + tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); - tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8); - tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00); - tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); -#endif + tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8); + tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00); + tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT); + } } static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) { -#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) - tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg); -#else - tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); - tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24); -#endif + if (use_mips32r2_instructions) { + tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg); + } else { + tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24); + tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24); + } } static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg) { -#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) - tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg); -#else - tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16); - tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16); -#endif + if (use_mips32r2_instructions) { + tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg); + } else { + tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16); + tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16); + } } static inline void tcg_out_ldst(TCGContext *s, int opc, TCGArg arg, @@ -514,13 +514,13 @@ static inline void tcg_out_ldst(TCGContext *s, int opc, TCGArg arg, } static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { tcg_out_ldst(s, OPC_LW, arg, arg1, arg2); } static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { tcg_out_ldst(s, OPC_SW, arg, arg1, arg2); } @@ -919,9 +919,6 @@ static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret, } #if defined(CONFIG_SOFTMMU) - -#include "exec/softmmu_defs.h" - /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -1406,12 +1403,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT); break; case INDEX_op_mul_i32: -#if defined(__mips_isa_rev) && (__mips_isa_rev >= 1) - tcg_out_opc_reg(s, OPC_MUL, args[0], args[1], args[2]); -#else - tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]); - tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0); -#endif + if (use_mips32_instructions) { + tcg_out_opc_reg(s, OPC_MUL, args[0], args[1], args[2]); + } else { + tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]); + tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0); + } break; case INDEX_op_muls2_i32: tcg_out_opc_reg(s, OPC_MULT, 0, args[2], args[3]); @@ -1423,6 +1420,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0); tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0); break; + case INDEX_op_mulsh_i32: + tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]); + tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0); + break; + case INDEX_op_muluh_i32: + tcg_out_opc_reg(s, OPC_MULTU, 0, args[1], args[2]); + tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0); + break; case INDEX_op_div_i32: tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]); tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0); @@ -1506,20 +1511,19 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, } break; - /* The bswap routines do not work on non-R2 CPU. In that case - we let TCG generating the corresponding code. */ case INDEX_op_bswap16_i32: - tcg_out_bswap16(s, args[0], args[1]); + tcg_out_opc_reg(s, OPC_WSBH, args[0], 0, args[1]); break; case INDEX_op_bswap32_i32: - tcg_out_bswap32(s, args[0], args[1]); + tcg_out_opc_reg(s, OPC_WSBH, args[0], 0, args[1]); + tcg_out_opc_sa(s, OPC_ROTR, args[0], args[0], 16); break; case INDEX_op_ext8s_i32: - tcg_out_ext8s(s, args[0], args[1]); + tcg_out_opc_reg(s, OPC_SEB, args[0], 0, args[1]); break; case INDEX_op_ext16s_i32: - tcg_out_ext16s(s, args[0], args[1]); + tcg_out_opc_reg(s, OPC_SEH, args[0], 0, args[1]); break; case INDEX_op_deposit_i32: @@ -1602,6 +1606,8 @@ static const TCGTargetOpDef mips_op_defs[] = { { INDEX_op_mul_i32, { "r", "rZ", "rZ" } }, { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } }, { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } }, + { INDEX_op_mulsh_i32, { "r", "rZ", "rZ" } }, + { INDEX_op_muluh_i32, { "r", "rZ", "rZ" } }, { INDEX_op_div_i32, { "r", "rZ", "rZ" } }, { INDEX_op_divu_i32, { "r", "rZ", "rZ" } }, { INDEX_op_rem_i32, { "r", "rZ", "rZ" } }, @@ -1617,29 +1623,19 @@ static const TCGTargetOpDef mips_op_defs[] = { { 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" } }, @@ -1688,6 +1684,86 @@ static int tcg_target_callee_save_regs[] = { TCG_REG_RA, /* should be last for ABI compliance */ }; +/* The Linux kernel doesn't provide any information about the available + instruction set. Probe it using a signal handler. */ + +#include <signal.h> + +#ifndef use_movnz_instructions +bool use_movnz_instructions = false; +#endif + +#ifndef use_mips32_instructions +bool use_mips32_instructions = false; +#endif + +#ifndef use_mips32r2_instructions +bool use_mips32r2_instructions = false; +#endif + +static volatile sig_atomic_t got_sigill; + +static void sigill_handler(int signo, siginfo_t *si, void *data) +{ + /* Skip the faulty instruction */ + ucontext_t *uc = (ucontext_t *)data; + uc->uc_mcontext.pc += 4; + + got_sigill = 1; +} + +static void tcg_target_detect_isa(void) +{ + struct sigaction sa_old, sa_new; + + memset(&sa_new, 0, sizeof(sa_new)); + sa_new.sa_flags = SA_SIGINFO; + sa_new.sa_sigaction = sigill_handler; + sigaction(SIGILL, &sa_new, &sa_old); + + /* Probe for movn/movz, necessary to implement movcond. */ +#ifndef use_movnz_instructions + got_sigill = 0; + asm volatile(".set push\n" + ".set mips32\n" + "movn $zero, $zero, $zero\n" + "movz $zero, $zero, $zero\n" + ".set pop\n" + : : : ); + use_movnz_instructions = !got_sigill; +#endif + + /* Probe for MIPS32 instructions. As no subsetting is allowed + by the specification, it is only necessary to probe for one + of the instructions. */ +#ifndef use_mips32_instructions + got_sigill = 0; + asm volatile(".set push\n" + ".set mips32\n" + "mul $zero, $zero\n" + ".set pop\n" + : : : ); + use_mips32_instructions = !got_sigill; +#endif + + /* Probe for MIPS32r2 instructions if MIPS32 instructions are + available. As no subsetting is allowed by the specification, + it is only necessary to probe for one of the instructions. */ +#ifndef use_mips32r2_instructions + if (use_mips32_instructions) { + got_sigill = 0; + asm volatile(".set push\n" + ".set mips32r2\n" + "seb $zero, $zero\n" + ".set pop\n" + : : : ); + use_mips32r2_instructions = !got_sigill; + } +#endif + + sigaction(SIGILL, &sa_old, NULL); +} + /* Generate global QEMU prologue and epilogue code */ static void tcg_target_qemu_prologue(TCGContext *s) { @@ -1727,6 +1803,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) static void tcg_target_init(TCGContext *s) { + tcg_target_detect_isa(); tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff); tcg_regset_set(tcg_target_call_clobber_regs, (1 << TCG_REG_V0) | diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index a438950bc1..c37252269f 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -77,40 +77,50 @@ typedef enum { #define TCG_TARGET_CALL_STACK_OFFSET 16 #define TCG_TARGET_CALL_ALIGN_ARGS 1 +/* MOVN/MOVZ instructions detection */ +#if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \ + defined(_MIPS_ARCH_LOONGSON2E) || defined(_MIPS_ARCH_LOONGSON2F) || \ + defined(_MIPS_ARCH_MIPS4) +#define use_movnz_instructions 1 +#else +extern bool use_movnz_instructions; +#endif + +/* MIPS32 instruction set detection */ +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 1) +#define use_mips32_instructions 1 +#else +extern bool use_mips32_instructions; +#endif + +/* MIPS32R2 instruction set detection */ +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) +#define use_mips32r2_instructions 1 +#else +extern bool use_mips32r2_instructions; +#endif + /* optional instructions */ #define TCG_TARGET_HAS_div_i32 1 #define TCG_TARGET_HAS_rem_i32 1 #define TCG_TARGET_HAS_not_i32 1 #define TCG_TARGET_HAS_nor_i32 1 -#define TCG_TARGET_HAS_ext8s_i32 1 -#define TCG_TARGET_HAS_ext16s_i32 1 #define TCG_TARGET_HAS_andc_i32 0 #define TCG_TARGET_HAS_orc_i32 0 #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_muls2_i32 1 +#define TCG_TARGET_HAS_muluh_i32 1 +#define TCG_TARGET_HAS_mulsh_i32 1 -/* optional instructions only implemented on MIPS4, MIPS32 and Loongson 2 */ -#if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \ - defined(_MIPS_ARCH_LOONGSON2E) || defined(_MIPS_ARCH_LOONGSON2F) || \ - defined(_MIPS_ARCH_MIPS4) -#define TCG_TARGET_HAS_movcond_i32 1 -#else -#define TCG_TARGET_HAS_movcond_i32 0 -#endif - -/* optional instructions only implemented on MIPS32R2 */ -#if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) -#define TCG_TARGET_HAS_bswap16_i32 1 -#define TCG_TARGET_HAS_bswap32_i32 1 -#define TCG_TARGET_HAS_rot_i32 1 -#define TCG_TARGET_HAS_deposit_i32 1 -#else -#define TCG_TARGET_HAS_bswap16_i32 0 -#define TCG_TARGET_HAS_bswap32_i32 0 -#define TCG_TARGET_HAS_rot_i32 0 -#define TCG_TARGET_HAS_deposit_i32 0 -#endif +/* optional instructions detected at runtime */ +#define TCG_TARGET_HAS_movcond_i32 use_movnz_instructions +#define TCG_TARGET_HAS_bswap16_i32 use_mips32r2_instructions +#define TCG_TARGET_HAS_bswap32_i32 use_mips32r2_instructions +#define TCG_TARGET_HAS_deposit_i32 use_mips32r2_instructions +#define TCG_TARGET_HAS_ext8s_i32 use_mips32r2_instructions +#define TCG_TARGET_HAS_ext16s_i32 use_mips32r2_instructions +#define TCG_TARGET_HAS_rot_i32 use_mips32r2_instructions /* optional instructions automatically implemented */ #define TCG_TARGET_HAS_neg_i32 0 /* sub rd, zero, rt */ @@ -125,8 +135,7 @@ typedef enum { #include <sys/cachectl.h> #endif -static inline void flush_icache_range(tcg_target_ulong start, - tcg_target_ulong stop) +static inline void flush_icache_range(uintptr_t start, uintptr_t stop) { cacheflush ((void *)start, stop-start, ICACHE); } diff --git a/tcg/optimize.c b/tcg/optimize.c index b35868afbc..b29bf25b67 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -198,6 +198,8 @@ static TCGOpcode op_to_mov(TCGOpcode op) static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y) { + uint64_t l64, h64; + switch (op) { CASE_OP_32_64(add): return x + y; @@ -290,6 +292,37 @@ static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y) case INDEX_op_ext32u_i64: return (uint32_t)x; + case INDEX_op_muluh_i32: + return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32; + case INDEX_op_mulsh_i32: + return ((int64_t)(int32_t)x * (int32_t)y) >> 32; + + case INDEX_op_muluh_i64: + mulu64(&l64, &h64, x, y); + return h64; + case INDEX_op_mulsh_i64: + muls64(&l64, &h64, x, y); + return h64; + + case INDEX_op_div_i32: + /* Avoid crashing on divide by zero, otherwise undefined. */ + return (int32_t)x / ((int32_t)y ? : 1); + case INDEX_op_divu_i32: + return (uint32_t)x / ((uint32_t)y ? : 1); + case INDEX_op_div_i64: + return (int64_t)x / ((int64_t)y ? : 1); + case INDEX_op_divu_i64: + return (uint64_t)x / ((uint64_t)y ? : 1); + + case INDEX_op_rem_i32: + return (int32_t)x % ((int32_t)y ? : 1); + case INDEX_op_remu_i32: + return (uint32_t)x % ((uint32_t)y ? : 1); + case INDEX_op_rem_i64: + return (int64_t)x % ((int64_t)y ? : 1); + case INDEX_op_remu_i64: + return (uint64_t)x % ((uint64_t)y ? : 1); + default: fprintf(stderr, "Unrecognized operation %d in do_constant_folding.\n", op); @@ -531,6 +564,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, CASE_OP_32_64(eqv): CASE_OP_32_64(nand): CASE_OP_32_64(nor): + CASE_OP_32_64(muluh): + CASE_OP_32_64(mulsh): swap_commutative(args[0], &args[1], &args[2]); break; CASE_OP_32_64(brcond): @@ -771,6 +806,8 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, switch (op) { CASE_OP_32_64(and): CASE_OP_32_64(mul): + CASE_OP_32_64(muluh): + CASE_OP_32_64(mulsh): if ((temps[args[2]].state == TCG_TEMP_CONST && temps[args[2]].val == 0)) { s->gen_opc_buf[op_index] = op_to_movi(op); @@ -882,6 +919,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, CASE_OP_32_64(eqv): CASE_OP_32_64(nand): CASE_OP_32_64(nor): + CASE_OP_32_64(muluh): + CASE_OP_32_64(mulsh): + CASE_OP_32_64(div): + CASE_OP_32_64(divu): + CASE_OP_32_64(rem): + CASE_OP_32_64(remu): if (temps[args[1]].state == TCG_TEMP_CONST && temps[args[2]].state == TCG_TEMP_CONST) { s->gen_opc_buf[op_index] = op_to_movi(op); diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 453ab6b580..25955563b8 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -204,7 +204,7 @@ static void reloc_pc14 (void *pc, tcg_target_long target) } static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) + intptr_t value, intptr_t addend) { value += addend; switch (type) { @@ -549,8 +549,6 @@ static void add_qemu_ldst_label (TCGContext *s, label->label_ptr[0] = label_ptr; } -#include "exec/softmmu_defs.h" - /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -1062,14 +1060,14 @@ static void tcg_target_qemu_prologue (TCGContext *s) #endif } -static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, - tcg_target_long arg2) +static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, + intptr_t arg2) { tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX); } -static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, - tcg_target_long arg2) +static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, + intptr_t arg2) { tcg_out_ldst (s, arg, arg1, arg2, STW, STWX); } diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index b42d97cc24..c9f8ff5206 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -96,11 +96,13 @@ typedef enum { #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_AREG0 TCG_REG_R27 #define tcg_qemu_tb_exec(env, tb_ptr) \ - ((long __attribute__ ((longcall)) \ + ((uintptr_t __attribute__ ((longcall)) \ (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, tb_ptr) #endif diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 0678de2045..0bd1e0ce8c 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -208,7 +208,7 @@ static void reloc_pc14 (void *pc, tcg_target_long target) } static void patch_reloc (uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) + intptr_t value, intptr_t addend) { value += addend; switch (type) { @@ -750,9 +750,6 @@ static void tcg_out_ldsta(TCGContext *s, TCGReg ret, TCGReg addr, } #if defined (CONFIG_SOFTMMU) - -#include "exec/softmmu_defs.h" - /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -1072,8 +1069,8 @@ static void tcg_target_qemu_prologue (TCGContext *s) tcg_out32(s, BCLR | BO_ALWAYS); } -static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, - tcg_target_long arg2) +static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, + intptr_t arg2) { if (type == TCG_TYPE_I32) tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX); @@ -1081,8 +1078,8 @@ static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX); } -static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, - tcg_target_long arg2) +static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, + intptr_t arg2) { if (type == TCG_TYPE_I32) tcg_out_ldst (s, arg, arg1, arg2, STW, STWX); @@ -1975,29 +1972,11 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args, } break; - case INDEX_op_mulu2_i64: - case INDEX_op_muls2_i64: - { - int oph = (opc == INDEX_op_mulu2_i64 ? MULHDU : MULHD); - TCGReg outl = args[0], outh = args[1]; - a0 = args[2], a1 = args[3]; - - if (outl == a0 || outl == a1) { - if (outh == a0 || outh == a1) { - outl = TCG_REG_R0; - } else { - tcg_out32(s, oph | TAB(outh, a0, a1)); - oph = 0; - } - } - tcg_out32(s, MULLD | TAB(outl, a0, a1)); - if (oph != 0) { - tcg_out32(s, oph | TAB(outh, a0, a1)); - } - if (outl != args[0]) { - tcg_out_mov(s, TCG_TYPE_I64, args[0], outl); - } - } + case INDEX_op_muluh_i64: + tcg_out32(s, MULHDU | TAB(args[0], args[1], args[2])); + break; + case INDEX_op_mulsh_i64: + tcg_out32(s, MULHD | TAB(args[0], args[1], args[2])); break; default: @@ -2124,8 +2103,8 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_add2_i64, { "r", "r", "r", "r", "rI", "rZM" } }, { INDEX_op_sub2_i64, { "r", "r", "rI", "r", "rZM", "r" } }, - { INDEX_op_muls2_i64, { "r", "r", "r", "r" } }, - { INDEX_op_mulu2_i64, { "r", "r", "r", "r" } }, + { INDEX_op_mulsh_i64, { "r", "r", "r" } }, + { INDEX_op_muluh_i64, { "r", "r", "r" } }, { -1 }, }; diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h index 48fc6e2e54..fa4b9da093 100644 --- a/tcg/ppc64/tcg-target.h +++ b/tcg/ppc64/tcg-target.h @@ -95,6 +95,8 @@ typedef enum { #define TCG_TARGET_HAS_sub2_i32 0 #define TCG_TARGET_HAS_mulu2_i32 0 #define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_rem_i64 0 @@ -116,8 +118,10 @@ typedef enum { #define TCG_TARGET_HAS_movcond_i64 1 #define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1 -#define TCG_TARGET_HAS_mulu2_i64 1 -#define TCG_TARGET_HAS_muls2_i64 1 +#define TCG_TARGET_HAS_mulu2_i64 0 +#define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 1 +#define TCG_TARGET_HAS_mulsh_i64 1 #define TCG_AREG0 TCG_REG_R27 diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index f229f1c346..1b44aeee96 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -315,9 +315,6 @@ static const uint8_t tcg_cond_to_ltr_cond[] = { }; #ifdef CONFIG_SOFTMMU - -#include "exec/softmmu_defs.h" - /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { @@ -351,10 +348,10 @@ static uint8_t *tb_ret_addr; static uint64_t facilities; static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) + intptr_t value, intptr_t addend) { - tcg_target_long code_ptr_tl = (tcg_target_long)code_ptr; - tcg_target_long pcrel2; + intptr_t code_ptr_tl = (intptr_t)code_ptr; + intptr_t pcrel2; /* ??? Not the usual definition of "addend". */ pcrel2 = (value - (code_ptr_tl + addend)) >> 1; @@ -771,7 +768,7 @@ static void tcg_out_mem(TCGContext *s, S390Opcode opc_rx, S390Opcode opc_rxy, /* load data without address translation or endianness conversion */ static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg data, - TCGReg base, tcg_target_long ofs) + TCGReg base, intptr_t ofs) { if (type == TCG_TYPE_I32) { tcg_out_mem(s, RX_L, RXY_LY, data, base, TCG_REG_NONE, ofs); @@ -781,7 +778,7 @@ static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg data, } static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg data, - TCGReg base, tcg_target_long ofs) + TCGReg base, intptr_t ofs) { if (type == TCG_TYPE_I32) { tcg_out_mem(s, RX_ST, RXY_STY, data, base, TCG_REG_NONE, ofs); diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index 42ca36c0e9..6142fb26a2 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -69,6 +69,8 @@ typedef enum TCGReg { #define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_mulu2_i32 0 #define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 #define TCG_TARGET_HAS_div2_i64 1 #define TCG_TARGET_HAS_rot_i64 1 @@ -94,6 +96,8 @@ typedef enum TCGReg { #define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_mulu2_i64 1 #define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 extern bool tcg_target_deposit_valid(int ofs, int len); #define TCG_TARGET_deposit_i32_valid tcg_target_deposit_valid @@ -110,8 +114,7 @@ enum { TCG_AREG0 = TCG_REG_R10, }; -static inline void flush_icache_range(tcg_target_ulong start, - tcg_target_ulong stop) +static inline void flush_icache_range(uintptr_t start, uintptr_t stop) { } diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 5bfd29c3b4..9574954ac4 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -252,7 +252,7 @@ static inline int check_fit_i32(uint32_t val, unsigned int bits) } static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) + intptr_t value, intptr_t addend) { uint32_t insn; value += addend; @@ -264,7 +264,7 @@ static void patch_reloc(uint8_t *code_ptr, int type, *(uint32_t *)code_ptr = value; break; case R_SPARC_WDISP16: - value -= (long)code_ptr; + value -= (intptr_t)code_ptr; if (!check_fit_tl(value >> 2, 16)) { tcg_abort(); } @@ -274,7 +274,7 @@ static void patch_reloc(uint8_t *code_ptr, int type, *(uint32_t *)code_ptr = insn; break; case R_SPARC_WDISP19: - value -= (long)code_ptr; + value -= (intptr_t)code_ptr; if (!check_fit_tl(value >> 2, 19)) { tcg_abort(); } @@ -436,13 +436,13 @@ static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, } static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { tcg_out_ldst(s, ret, arg1, arg2, (type == TCG_TYPE_I32 ? LDUW : LDX)); } static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, - TCGReg arg1, tcg_target_long arg2) + TCGReg arg1, intptr_t arg2) { tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX)); } @@ -831,8 +831,6 @@ static void tcg_target_qemu_prologue(TCGContext *s) #if defined(CONFIG_SOFTMMU) -#include "exec/softmmu_defs.h" - /* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr, int mmu_idx) */ static const void * const qemu_ld_helpers[4] = { diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index dab52d7176..2edf858733 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -24,6 +24,14 @@ #ifndef TCG_TARGET_SPARC #define TCG_TARGET_SPARC 1 +#if UINTPTR_MAX == UINT32_MAX +# define TCG_TARGET_REG_BITS 32 +#elif UINTPTR_MAX == UINT64_MAX +# define TCG_TARGET_REG_BITS 64 +#else +# error Unknown pointer size for tcg target +#endif + #define TCG_TARGET_WORDS_BIGENDIAN #define TCG_TARGET_NB_REGS 32 @@ -107,6 +115,8 @@ typedef enum { #define TCG_TARGET_HAS_sub2_i32 1 #define TCG_TARGET_HAS_mulu2_i32 1 #define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div_i64 1 @@ -134,20 +144,18 @@ typedef enum { #define TCG_TARGET_HAS_sub2_i64 0 #define TCG_TARGET_HAS_mulu2_i64 0 #define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 #endif #define TCG_AREG0 TCG_REG_I0 -static inline void flush_icache_range(tcg_target_ulong start, - tcg_target_ulong stop) +static inline void flush_icache_range(uintptr_t start, uintptr_t stop) { - unsigned long p; - - p = start & ~(8UL - 1UL); - stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL); - - for (; p < stop; p += 8) + uintptr_t p; + for (p = start & -8; p < (stop + 7) & -8; p += 8) { __asm__ __volatile__("flush\t%0" : : "r" (p)); + } } #endif diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 364964d8d4..bb30a7cf39 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -1039,10 +1039,18 @@ static inline void tcg_gen_mul_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) t0 = tcg_temp_new_i64(); t1 = tcg_temp_new_i32(); - tcg_gen_op4_i32(INDEX_op_mulu2_i32, TCGV_LOW(t0), TCGV_HIGH(t0), - TCGV_LOW(arg1), TCGV_LOW(arg2)); - /* Allow the optimizer room to replace mulu2 with two moves. */ - tcg_gen_op0(INDEX_op_nop); + if (TCG_TARGET_HAS_mulu2_i32) { + tcg_gen_op4_i32(INDEX_op_mulu2_i32, TCGV_LOW(t0), TCGV_HIGH(t0), + TCGV_LOW(arg1), TCGV_LOW(arg2)); + /* Allow the optimizer room to replace mulu2 with two moves. */ + tcg_gen_op0(INDEX_op_nop); + } else { + tcg_debug_assert(TCG_TARGET_HAS_muluh_i32); + tcg_gen_op3_i32(INDEX_op_mul_i32, TCGV_LOW(t0), + TCGV_LOW(arg1), TCGV_LOW(arg2)); + tcg_gen_op3_i32(INDEX_op_muluh_i32, TCGV_HIGH(t0), + TCGV_LOW(arg1), TCGV_LOW(arg2)); + } tcg_gen_mul_i32(t1, TCGV_LOW(arg1), TCGV_HIGH(arg2)); tcg_gen_add_i32(TCGV_HIGH(t0), TCGV_HIGH(t0), t1); @@ -2401,6 +2409,12 @@ static inline void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, tcg_gen_op4_i32(INDEX_op_mulu2_i32, rl, rh, arg1, arg2); /* Allow the optimizer room to replace mulu2 with two moves. */ tcg_gen_op0(INDEX_op_nop); + } else if (TCG_TARGET_HAS_muluh_i32) { + TCGv_i32 t = tcg_temp_new_i32(); + tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); + tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2); + tcg_gen_mov_i32(rl, t); + tcg_temp_free_i32(t); } else { TCGv_i64 t0 = tcg_temp_new_i64(); TCGv_i64 t1 = tcg_temp_new_i64(); @@ -2420,6 +2434,12 @@ static inline void tcg_gen_muls2_i32(TCGv_i32 rl, TCGv_i32 rh, tcg_gen_op4_i32(INDEX_op_muls2_i32, rl, rh, arg1, arg2); /* Allow the optimizer room to replace muls2 with two moves. */ tcg_gen_op0(INDEX_op_nop); + } else if (TCG_TARGET_HAS_mulsh_i32) { + TCGv_i32 t = tcg_temp_new_i32(); + tcg_gen_op3_i32(INDEX_op_mul_i32, t, arg1, arg2); + tcg_gen_op3_i32(INDEX_op_mulsh_i32, rh, arg1, arg2); + tcg_gen_mov_i32(rl, t); + tcg_temp_free_i32(t); } else if (TCG_TARGET_REG_BITS == 32 && TCG_TARGET_HAS_mulu2_i32) { TCGv_i32 t0 = tcg_temp_new_i32(); TCGv_i32 t1 = tcg_temp_new_i32(); @@ -2499,6 +2519,12 @@ static inline void tcg_gen_mulu2_i64(TCGv_i64 rl, TCGv_i64 rh, tcg_gen_op4_i64(INDEX_op_mulu2_i64, rl, rh, arg1, arg2); /* Allow the optimizer room to replace mulu2 with two moves. */ tcg_gen_op0(INDEX_op_nop); + } else if (TCG_TARGET_HAS_muluh_i64) { + TCGv_i64 t = tcg_temp_new_i64(); + tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); + tcg_gen_op3_i64(INDEX_op_muluh_i64, rh, arg1, arg2); + tcg_gen_mov_i64(rl, t); + tcg_temp_free_i64(t); } else if (TCG_TARGET_HAS_mulu2_i64) { TCGv_i64 t0 = tcg_temp_new_i64(); TCGv_i64 t1 = tcg_temp_new_i64(); @@ -2540,6 +2566,12 @@ static inline void tcg_gen_muls2_i64(TCGv_i64 rl, TCGv_i64 rh, tcg_gen_op4_i64(INDEX_op_muls2_i64, rl, rh, arg1, arg2); /* Allow the optimizer room to replace muls2 with two moves. */ tcg_gen_op0(INDEX_op_nop); + } else if (TCG_TARGET_HAS_mulsh_i64) { + TCGv_i64 t = tcg_temp_new_i64(); + tcg_gen_op3_i64(INDEX_op_mul_i64, t, arg1, arg2); + tcg_gen_op3_i64(INDEX_op_mulsh_i64, rh, arg1, arg2); + tcg_gen_mov_i64(rl, t); + tcg_temp_free_i64(t); } else { TCGv_i64 t0 = tcg_temp_new_i64(); int sizemask = 0; @@ -2599,7 +2631,7 @@ static inline void tcg_gen_debug_insn_start(uint64_t pc) #endif } -static inline void tcg_gen_exit_tb(tcg_target_long val) +static inline void tcg_gen_exit_tb(uintptr_t val) { tcg_gen_op1i(INDEX_op_exit_tb, val); } diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index a8af5b96a4..a75c29d518 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -91,6 +91,8 @@ DEF(add2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_add2_i32)) DEF(sub2_i32, 2, 4, 0, IMPL(TCG_TARGET_HAS_sub2_i32)) DEF(mulu2_i32, 2, 2, 0, IMPL(TCG_TARGET_HAS_mulu2_i32)) DEF(muls2_i32, 2, 2, 0, IMPL(TCG_TARGET_HAS_muls2_i32)) +DEF(muluh_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_muluh_i32)) +DEF(mulsh_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_mulsh_i32)) DEF(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | IMPL(TCG_TARGET_REG_BITS == 32)) DEF(setcond2_i32, 1, 4, 1, IMPL(TCG_TARGET_REG_BITS == 32)) @@ -167,6 +169,8 @@ DEF(add2_i64, 2, 4, 0, IMPL64 | IMPL(TCG_TARGET_HAS_add2_i64)) DEF(sub2_i64, 2, 4, 0, IMPL64 | IMPL(TCG_TARGET_HAS_sub2_i64)) DEF(mulu2_i64, 2, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_mulu2_i64)) DEF(muls2_i64, 2, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_muls2_i64)) +DEF(muluh_i64, 1, 2, 0, IMPL(TCG_TARGET_HAS_muluh_i64)) +DEF(mulsh_i64, 1, 2, 0, IMPL(TCG_TARGET_HAS_mulsh_i64)) /* QEMU specific */ #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS @@ -49,10 +49,10 @@ #include "tcg-op.h" -#if TCG_TARGET_REG_BITS == 64 -# define ELF_CLASS ELFCLASS64 -#else +#if UINTPTR_MAX == UINT32_MAX # define ELF_CLASS ELFCLASS32 +#else +# define ELF_CLASS ELFCLASS64 #endif #ifdef HOST_WORDS_BIGENDIAN # define ELF_DATA ELFDATA2MSB @@ -66,7 +66,7 @@ static void tcg_target_init(TCGContext *s); static void tcg_target_qemu_prologue(TCGContext *s); static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend); + intptr_t value, intptr_t addend); /* The CIE and FDE header definitions will be common to all hosts. */ typedef struct { @@ -82,8 +82,8 @@ typedef struct { typedef struct QEMU_PACKED { uint32_t len __attribute__((aligned((sizeof(void *))))); uint32_t cie_offset; - tcg_target_long func_start; - tcg_target_long func_len; + uintptr_t func_start; + uintptr_t func_len; } DebugFrameFDEHeader; static void tcg_register_jit_int(void *buf, size_t size, @@ -93,14 +93,14 @@ static void tcg_register_jit_int(void *buf, size_t size, /* Forward declarations for functions declared and used in tcg-target.c. */ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str); static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, - tcg_target_long arg2); + intptr_t arg2); static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg); static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret, tcg_target_long arg); static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, const int *const_args); static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, - tcg_target_long arg2); + intptr_t arg2); static int tcg_target_const_match(tcg_target_long val, const TCGArgConstraint *arg_ct); @@ -121,20 +121,29 @@ static inline void tcg_out8(TCGContext *s, uint8_t v) 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 */ static void tcg_out_reloc(TCGContext *s, uint8_t *code_ptr, int type, - int label_index, long addend) + int label_index, intptr_t addend) { TCGLabel *l; TCGRelocation *r; @@ -160,11 +169,12 @@ static void tcg_out_label(TCGContext *s, int label_index, void *ptr) { TCGLabel *l; TCGRelocation *r; - tcg_target_long value = (tcg_target_long)ptr; + intptr_t value = (intptr_t)ptr; l = &s->labels[label_index]; - if (l->has_value) + if (l->has_value) { tcg_abort(); + } r = l->u.first_reloc; while (r != NULL) { patch_reloc(r->ptr, r->type, value, r->addend); @@ -284,8 +294,7 @@ void tcg_prologue_init(TCGContext *s) s->code_buf = s->code_gen_prologue; s->code_ptr = s->code_buf; tcg_target_qemu_prologue(s); - flush_icache_range((tcg_target_ulong)s->code_buf, - (tcg_target_ulong)s->code_ptr); + flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr); #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) { @@ -298,8 +307,7 @@ void tcg_prologue_init(TCGContext *s) #endif } -void tcg_set_frame(TCGContext *s, int reg, - tcg_target_long start, tcg_target_long size) +void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size) { s->frame_start = start; s->frame_end = start + size; @@ -382,7 +390,7 @@ TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name) } static inline int tcg_global_mem_new_internal(TCGType type, int reg, - tcg_target_long offset, + intptr_t offset, const char *name) { TCGContext *s = &tcg_ctx; @@ -442,21 +450,15 @@ static inline int tcg_global_mem_new_internal(TCGType type, int reg, return idx; } -TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset, - const char *name) +TCGv_i32 tcg_global_mem_new_i32(int reg, intptr_t offset, const char *name) { - int idx; - - idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name); + int idx = tcg_global_mem_new_internal(TCG_TYPE_I32, reg, offset, name); return MAKE_TCGV_I32(idx); } -TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset, - const char *name) +TCGv_i64 tcg_global_mem_new_i64(int reg, intptr_t offset, const char *name) { - int idx; - - idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name); + int idx = tcg_global_mem_new_internal(TCG_TYPE_I64, reg, offset, name); return MAKE_TCGV_I64(idx); } @@ -632,7 +634,7 @@ void tcg_register_helper(void *func, const char *name) s->helpers = realloc(s->helpers, n * sizeof(TCGHelperInfo)); s->allocated_helpers = n; } - s->helpers[s->nb_helpers].func = (tcg_target_ulong)func; + s->helpers[s->nb_helpers].func = (uintptr_t)func; s->helpers[s->nb_helpers].name = name; s->nb_helpers++; } @@ -862,11 +864,11 @@ static int helper_cmp(const void *p1, const void *p2) } /* find helper definition (Note: A hash table would be better) */ -static TCGHelperInfo *tcg_find_helper(TCGContext *s, tcg_target_ulong val) +static TCGHelperInfo *tcg_find_helper(TCGContext *s, uintptr_t val) { int m, m_min, m_max; TCGHelperInfo *th; - tcg_target_ulong v; + uintptr_t v; if (unlikely(!s->helpers_sorted)) { qsort(s->helpers, s->nb_helpers, sizeof(TCGHelperInfo), @@ -1243,12 +1245,13 @@ static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps, static void tcg_liveness_analysis(TCGContext *s) { int i, op_index, nb_args, nb_iargs, nb_oargs, arg, nb_ops; - TCGOpcode op, op_new; + TCGOpcode op, op_new, op_new2; TCGArg *args; const TCGOpDef *def; uint8_t *dead_temps, *mem_temps; uint16_t dead_args; uint8_t sync_args; + bool have_op_new2; s->gen_opc_ptr++; /* skip end */ @@ -1385,29 +1388,52 @@ static void tcg_liveness_analysis(TCGContext *s) goto do_not_remove; case INDEX_op_mulu2_i32: + op_new = INDEX_op_mul_i32; + op_new2 = INDEX_op_muluh_i32; + have_op_new2 = TCG_TARGET_HAS_muluh_i32; + goto do_mul2; case INDEX_op_muls2_i32: op_new = INDEX_op_mul_i32; + op_new2 = INDEX_op_mulsh_i32; + have_op_new2 = TCG_TARGET_HAS_mulsh_i32; goto do_mul2; case INDEX_op_mulu2_i64: + op_new = INDEX_op_mul_i64; + op_new2 = INDEX_op_muluh_i64; + have_op_new2 = TCG_TARGET_HAS_muluh_i64; + goto do_mul2; case INDEX_op_muls2_i64: op_new = INDEX_op_mul_i64; + op_new2 = INDEX_op_mulsh_i64; + have_op_new2 = TCG_TARGET_HAS_mulsh_i64; + goto do_mul2; do_mul2: args -= 4; nb_iargs = 2; nb_oargs = 2; - /* Likewise, test for the high part of the operation dead. */ if (dead_temps[args[1]] && !mem_temps[args[1]]) { if (dead_temps[args[0]] && !mem_temps[args[0]]) { + /* Both parts of the operation are dead. */ goto do_remove; } + /* The high part of the operation is dead; generate the low. */ s->gen_opc_buf[op_index] = op = op_new; args[1] = args[2]; args[2] = args[3]; - assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop); - tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 1); - /* Fall through and mark the single-word operation live. */ - nb_oargs = 1; + } else if (have_op_new2 && dead_temps[args[0]] + && !mem_temps[args[0]]) { + /* The low part of the operation is dead; generate the high. */ + s->gen_opc_buf[op_index] = op = op_new2; + args[0] = args[1]; + args[1] = args[2]; + args[2] = args[3]; + } else { + goto do_not_remove; } + assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop); + tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 1); + /* Mark the single-word operation live. */ + nb_oargs = 1; goto do_not_remove; default: @@ -1581,7 +1607,7 @@ static void temp_allocate_frame(TCGContext *s, int temp) ts->mem_offset = s->current_frame_offset; ts->mem_reg = s->frame_reg; ts->mem_allocated = 1; - s->current_frame_offset += (tcg_target_long)sizeof(tcg_target_long); + s->current_frame_offset += sizeof(tcg_target_long); } /* sync register 'reg' by saving it to the corresponding temporary */ @@ -2044,7 +2070,9 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params; TCGArg arg, func_arg; TCGTemp *ts; - tcg_target_long stack_offset, call_stack_size, func_addr; + intptr_t stack_offset; + size_t call_stack_size; + uintptr_t func_addr; int const_func_arg, allocate_args; TCGRegSet allocated_regs; const TCGArgConstraint *arg_ct; @@ -2382,8 +2410,7 @@ int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf) tcg_gen_code_common(s, gen_code_buf, -1); /* flush instruction cache */ - flush_icache_range((tcg_target_ulong)gen_code_buf, - (tcg_target_ulong)s->code_ptr); + flush_icache_range((uintptr_t)gen_code_buf, (uintptr_t)s->code_ptr); return s->code_ptr - gen_code_buf; } @@ -21,15 +21,23 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + +#ifndef TCG_H +#define TCG_H + #include "qemu-common.h" -/* Target word size (must be identical to pointer size). */ -#if UINTPTR_MAX == UINT32_MAX -# define TCG_TARGET_REG_BITS 32 -#elif UINTPTR_MAX == UINT64_MAX -# define TCG_TARGET_REG_BITS 64 -#else -# error Unknown pointer size for tcg target +#include "tcg-target.h" + +/* Default target word size to pointer size. */ +#ifndef TCG_TARGET_REG_BITS +# if UINTPTR_MAX == UINT32_MAX +# define TCG_TARGET_REG_BITS 32 +# elif UINTPTR_MAX == UINT64_MAX +# define TCG_TARGET_REG_BITS 64 +# else +# error Unknown pointer size for tcg target +# endif #endif #if TCG_TARGET_REG_BITS == 32 @@ -46,7 +54,6 @@ typedef uint64_t tcg_target_ulong; #error unsupported #endif -#include "tcg-target.h" #include "tcg-runtime.h" #if TCG_TARGET_NB_REGS <= 32 @@ -85,6 +92,8 @@ typedef uint64_t TCGRegSet; #define TCG_TARGET_HAS_sub2_i64 0 #define TCG_TARGET_HAS_mulu2_i64 0 #define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 /* Turn some undef macros into true macros. */ #define TCG_TARGET_HAS_add2_i32 1 #define TCG_TARGET_HAS_sub2_i32 1 @@ -134,13 +143,13 @@ typedef struct TCGRelocation { struct TCGRelocation *next; int type; uint8_t *ptr; - tcg_target_long addend; + intptr_t addend; } TCGRelocation; typedef struct TCGLabel { int has_value; union { - tcg_target_ulong value; + uintptr_t value; TCGRelocation *first_reloc; } u; } TCGLabel; @@ -173,9 +182,12 @@ typedef enum TCGType { TCG_TYPE_REG = TCG_TYPE_I64, #endif - /* An alias for the size of the native pointer. We don't currently - support any hosts with 64-bit registers and 32-bit pointers. */ - TCG_TYPE_PTR = TCG_TYPE_REG, + /* An alias for the size of the native pointer. */ +#if UINTPTR_MAX == UINT32_MAX + TCG_TYPE_PTR = TCG_TYPE_I32, +#else + TCG_TYPE_PTR = TCG_TYPE_I64, +#endif /* An alias for the size of the target "long", aka register. */ #if TARGET_LONG_BITS == 64 @@ -380,7 +392,7 @@ typedef struct TCGTemp { int reg; tcg_target_long val; int mem_reg; - tcg_target_long mem_offset; + intptr_t mem_offset; unsigned int fixed_reg:1; unsigned int mem_coherent:1; unsigned int mem_allocated:1; @@ -394,7 +406,7 @@ typedef struct TCGTemp { } TCGTemp; typedef struct TCGHelperInfo { - tcg_target_ulong func; + uintptr_t func; const char *name; } TCGHelperInfo; @@ -427,9 +439,9 @@ struct TCGContext { into account fixed registers */ int reg_to_temp[TCG_TARGET_NB_REGS]; TCGRegSet reserved_regs; - tcg_target_long current_frame_offset; - tcg_target_long frame_start; - tcg_target_long frame_end; + intptr_t current_frame_offset; + intptr_t frame_start; + intptr_t frame_end; int frame_reg; uint8_t *code_ptr; @@ -522,12 +534,10 @@ void tcg_func_start(TCGContext *s); int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf); int tcg_gen_code_search_pc(TCGContext *s, uint8_t *gen_code_buf, long offset); -void tcg_set_frame(TCGContext *s, int reg, - tcg_target_long start, tcg_target_long size); +void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size); TCGv_i32 tcg_global_reg_new_i32(int reg, const char *name); -TCGv_i32 tcg_global_mem_new_i32(int reg, tcg_target_long offset, - const char *name); +TCGv_i32 tcg_global_mem_new_i32(int reg, intptr_t offset, const char *name); TCGv_i32 tcg_temp_new_internal_i32(int temp_local); static inline TCGv_i32 tcg_temp_new_i32(void) { @@ -541,8 +551,7 @@ void tcg_temp_free_i32(TCGv_i32 arg); char *tcg_get_arg_str_i32(TCGContext *s, char *buf, int buf_size, TCGv_i32 arg); TCGv_i64 tcg_global_reg_new_i64(int reg, const char *name); -TCGv_i64 tcg_global_mem_new_i64(int reg, tcg_target_long offset, - const char *name); +TCGv_i64 tcg_global_mem_new_i64(int reg, intptr_t offset, const char *name); TCGv_i64 tcg_temp_new_internal_i64(int temp_local); static inline TCGv_i64 tcg_temp_new_i64(void) { @@ -637,11 +646,11 @@ do {\ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs); -#if TCG_TARGET_REG_BITS == 32 +#if UINTPTR_MAX == UINT32_MAX #define TCGV_NAT_TO_PTR(n) MAKE_TCGV_PTR(GET_TCGV_I32(n)) #define TCGV_PTR_TO_NAT(n) MAKE_TCGV_I32(GET_TCGV_PTR(n)) -#define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i32((tcg_target_long)(V))) +#define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i32((intptr_t)(V))) #define tcg_global_reg_new_ptr(R, N) \ TCGV_NAT_TO_PTR(tcg_global_reg_new_i32((R), (N))) #define tcg_global_mem_new_ptr(R, O, N) \ @@ -652,7 +661,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs); #define TCGV_NAT_TO_PTR(n) MAKE_TCGV_PTR(GET_TCGV_I64(n)) #define TCGV_PTR_TO_NAT(n) MAKE_TCGV_I64(GET_TCGV_PTR(n)) -#define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i64((tcg_target_long)(V))) +#define tcg_const_ptr(V) TCGV_NAT_TO_PTR(tcg_const_i64((intptr_t)(V))) #define tcg_global_reg_new_ptr(R, N) \ TCGV_NAT_TO_PTR(tcg_global_reg_new_i64((R), (N))) #define tcg_global_mem_new_ptr(R, O, N) \ @@ -731,8 +740,7 @@ TCGv_i64 tcg_const_local_i64(int64_t val); #if !defined(tcg_qemu_tb_exec) # define tcg_qemu_tb_exec(env, tb_ptr) \ - ((tcg_target_ulong (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, \ - tb_ptr) + ((uintptr_t (*)(void *, void *))tcg_ctx.code_gen_prologue)(env, tb_ptr) #endif void tcg_register_jit(void *buf, size_t buf_size); @@ -741,3 +749,51 @@ void tcg_register_jit(void *buf, size_t buf_size); /* Generate TB finalization at the end of block */ void tcg_out_tb_finalize(TCGContext *s); #endif + +/* + * Memory helpers that will be used by TCG generated code. + */ +#ifdef CONFIG_SOFTMMU +/* Value zero-extended to tcg register size. */ +tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr, + int mmu_idx, uintptr_t retaddr); +tcg_target_ulong helper_ret_lduw_mmu(CPUArchState *env, target_ulong addr, + int mmu_idx, uintptr_t retaddr); +tcg_target_ulong helper_ret_ldul_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); + +/* Value sign-extended to tcg register size. */ +tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr, + int mmu_idx, uintptr_t retaddr); +tcg_target_ulong helper_ret_ldsw_mmu(CPUArchState *env, target_ulong addr, + int mmu_idx, uintptr_t retaddr); +tcg_target_ulong helper_ret_ldsl_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); +uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx); +uint32_t helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx); +uint64_t helper_ldq_mmu(CPUArchState *env, target_ulong addr, 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); +#endif /* CONFIG_SOFTMMU */ + +#endif /* TCG_H */ diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c index e118bc7179..281d7d50f3 100644 --- a/tcg/tci/tcg-target.c +++ b/tcg/tci/tcg-target.c @@ -370,7 +370,7 @@ static const char *const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { #endif static void patch_reloc(uint8_t *code_ptr, int type, - tcg_target_long value, tcg_target_long addend) + intptr_t value, intptr_t addend) { /* tcg_out_reloc always uses the same type, addend. */ assert(type == sizeof(tcg_target_long)); @@ -488,7 +488,7 @@ static void tci_out_label(TCGContext *s, TCGArg arg) } static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, - tcg_target_long arg2) + intptr_t arg2) { uint8_t *old_code_ptr = s->code_ptr; if (type == TCG_TYPE_I32) { @@ -842,7 +842,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, } static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, - tcg_target_long arg2) + intptr_t arg2) { uint8_t *old_code_ptr = s->code_ptr; if (type == TCG_TYPE_I32) { diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index d7fc14eb17..c2ecfbe047 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -44,6 +44,14 @@ #define TCG_TARGET_INTERPRETER 1 +#if UINTPTR_MAX == UINT32_MAX +# define TCG_TARGET_REG_BITS 32 +#elif UINTPTR_MAX == UINT64_MAX +# define TCG_TARGET_REG_BITS 64 +#else +# error Unknown pointer size for tci target +#endif + #ifdef CONFIG_DEBUG_TCG /* Enable debug output. */ #define CONFIG_DEBUG_TCG_INTERPRETER @@ -76,6 +84,8 @@ #define TCG_TARGET_HAS_rot_i32 1 #define TCG_TARGET_HAS_movcond_i32 0 #define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_bswap16_i64 1 @@ -100,13 +110,14 @@ #define TCG_TARGET_HAS_rot_i64 1 #define TCG_TARGET_HAS_movcond_i64 0 #define TCG_TARGET_HAS_muls2_i64 0 - #define TCG_TARGET_HAS_add2_i32 0 #define TCG_TARGET_HAS_sub2_i32 0 #define TCG_TARGET_HAS_mulu2_i32 0 #define TCG_TARGET_HAS_add2_i64 0 #define TCG_TARGET_HAS_sub2_i64 0 #define TCG_TARGET_HAS_mulu2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 #endif /* TCG_TARGET_REG_BITS == 64 */ /* Number of registers available. @@ -166,11 +177,10 @@ typedef enum { void tci_disas(uint8_t opc); -tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr); +uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr); #define tcg_qemu_tb_exec tcg_qemu_tb_exec -static inline void flush_icache_range(tcg_target_ulong start, - tcg_target_ulong stop) +static inline void flush_icache_range(uintptr_t start, uintptr_t stop) { } @@ -434,11 +434,11 @@ static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition) } /* Interpret pseudo code in tb. */ -tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) +uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) { long tcg_temps[CPU_TEMP_BUF_NLONGS]; uintptr_t sp_value = (uintptr_t)(tcg_temps + CPU_TEMP_BUF_NLONGS); - tcg_target_ulong next_tb = 0; + uintptr_t next_tb = 0; tci_reg[TCG_AREG0] = (tcg_target_ulong)env; tci_reg[TCG_REG_CALL_STACK] = sp_value; diff --git a/tests/Makefile b/tests/Makefile index b0200fd60f..baba9e95ad 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -23,6 +23,8 @@ check-unit-y += tests/test-string-input-visitor$(EXESUF) 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) @@ -100,7 +102,8 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \ 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 @@ -148,6 +151,7 @@ tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qap 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 diff --git a/tests/libqtest.h b/tests/libqtest.h index 0f6aade092..a6e99bd023 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -258,9 +258,9 @@ void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size) * 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 @@ int64_t qtest_clock_step_next(QTestState *s); * @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 @@ int64_t qtest_clock_step(QTestState *s, int64_t step); * @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 @@ static inline void memwrite(uint64_t addr, const void *data, size_t size) /** * 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 @@ static inline int64_t clock_step_next(void) * 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 @@ static inline int64_t clock_step(int64_t step) * 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/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index 4434fa3961..fe5af756c5 100644 --- a/tests/qapi-schema/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 index fb00344894..3851880de3 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -9,11 +9,13 @@ 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([('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', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]), + OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])] diff --git a/tests/test-aio.c b/tests/test-aio.c index 1ab5637d95..07a1f61f87 100644 --- a/tests/test-aio.c +++ b/tests/test-aio.c @@ -12,6 +12,7 @@ #include <glib.h> #include "block/aio.h" +#include "qemu/timer.h" AioContext *ctx; @@ -46,6 +47,15 @@ typedef struct { 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; @@ -54,6 +64,19 @@ static void bh_test_cb(void *opaque) } } +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; @@ -342,6 +365,64 @@ static void test_wait_event_notifier_noflush(void) 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: @@ -624,12 +705,61 @@ static void test_source_wait_event_notifier_noflush(void) 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); @@ -650,6 +780,7 @@ int main(int argc, char **argv) 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); @@ -664,5 +795,6 @@ int main(int argc, char **argv) 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 0000000000..9f902b597e --- /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-thread-pool.c b/tests/test-thread-pool.c index 8188d1a69d..c1f8e13a9f 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; @@ -205,6 +206,8 @@ int main(int argc, char **argv) { int ret; + init_clocks(); + ctx = aio_context_new(); pool = aio_get_thread_pool(ctx); diff --git a/thread-pool.c b/thread-pool.c index 5025567817..3735fd34bc 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); diff --git a/trace-events b/trace-events index 9d1d1df89d..3e988669a3 100644 --- a/trace-events +++ b/trace-events @@ -1133,6 +1133,11 @@ xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_ xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]" xics_ics_eoi(int nr) "ics_eoi: irq %#x" +# hw/ppc/spapr_iommu.c +spapr_iommu_put(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tce=0x%"PRIx64" ret=%"PRId64 +spapr_iommu_xlate(uint64_t liobn, uint64_t ioba, uint64_t tce, unsigned perm, unsigned pgsize) "liobn=%"PRIx64" 0x%"PRIx64" -> 0x%"PRIx64" perm=%u mask=%x" +spapr_iommu_new_table(uint64_t liobn, void *tcet, void *table, int fd) "liobn=%"PRIx64" tcet=%p table=%p fd=%d" + # util/hbitmap.c hbitmap_iter_skip_words(const void *hb, void *hbi, uint64_t pos, unsigned long cur) "hb %p hbi %p pos %"PRId64" cur 0x%lx" hbitmap_reset(void *hb, uint64_t start, uint64_t count, uint64_t sbit, uint64_t ebit) "hb %p items %"PRIu64",%"PRIu64" bits %"PRIu64"..%"PRIu64 diff --git a/ui/console.c b/ui/console.c index e3e82979d8..aad4fc9a57 100644 --- a/ui/console.c +++ b/ui/console.c @@ -208,8 +208,8 @@ static void gui_update(void *opaque) } 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 @@ static void gui_setup_refresh(DisplayState *ds) } 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 @@ void console_select(unsigned int index) 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 @@ void console_select(unsigned int index) 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 @@ static void kbd_send_chars(void *opaque) /* 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 @@ void update_displaychangelistener(DisplayChangeListener *dcl, 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 @@ static void text_console_update_cursor(void *opaque) 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 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds) 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 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds) } 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; @@ -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 92c44ca810..10d8c056f1 100644 --- a/ui/input.c +++ b/ui/input.c @@ -277,11 +277,11 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time, 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 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time, } /* 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 bd7a248f91..3a2cd7e0c6 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -63,25 +63,25 @@ static SpiceTimer *timer_add(SpiceTimerFunc func, void *opaque) 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); } diff --git a/ui/vnc-auth-sasl.h b/ui/vnc-auth-sasl.h index 8091d689cb..3f59da67eb 100644 --- a/ui/vnc-auth-sasl.h +++ b/ui/vnc-auth-sasl.h @@ -33,6 +33,7 @@ typedef struct VncStateSASL VncStateSASL; 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 c59b188602..bc7032e695 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 df89315733..e304bafeb0 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/version.rc b/version.rc index 82e10ecf26..a50d62fa0c 100644 --- a/version.rc +++ b/version.rc @@ -26,3 +26,5 @@ FILESUBTYPE VFT2_UNKNOWN VALUE "Translation", 0x0409, 1252 } } + +IDI_ICON1 ICON "pc-bios/qemu-nsis.ico" @@ -196,7 +196,7 @@ NICInfo nd_table[MAX_NICS]; 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 @@ static void configure_rtc(QemuOpts *opts) 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 @@ static int chardev_init_func(QemuOpts *opts, void *opaque) 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 @@ int main(int argc, char **argv, char **envp) runstate_init(); init_clocks(); - rtc_clock = host_clock; + rtc_clock = QEMU_CLOCK_HOST; qemu_cache_utils_init(envp); @@ -3714,7 +3714,9 @@ int main(int argc, char **argv, char **envp) 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 @@ int main(int argc, char **argv, char **envp) 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); } @@ -4419,7 +4421,8 @@ int main(int argc, char **argv, char **envp) 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); } @@ -606,8 +606,8 @@ static ioreq_t *cpu_get_ioreq(XenIOState *state) 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 @@ static void handle_buffered_io(void *opaque) 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 @@ static void xen_main_loop_prepare(XenIOState *state) 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) { |