diff options
41 files changed, 410 insertions, 250 deletions
diff --git a/block/iscsi.c b/block/iscsi.c index 5daa201181..b5f7a228b9 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1732,6 +1732,10 @@ static QemuOptsList runtime_opts = { .name = "timeout", .type = QEMU_OPT_NUMBER, }, + { + .name = "filename", + .type = QEMU_OPT_STRING, + }, { /* end of list */ } }, }; @@ -1747,12 +1751,27 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, char *initiator_name = NULL; QemuOpts *opts; Error *local_err = NULL; - const char *transport_name, *portal, *target; + const char *transport_name, *portal, *target, *filename; #if LIBISCSI_API_VERSION >= (20160603) enum iscsi_transport_type transport; #endif int i, ret = 0, timeout = 0, lun; + /* If we are given a filename, parse the filename, with precedence given to + * filename encoded options */ + filename = qdict_get_try_str(options, "filename"); + if (filename) { + error_report("Warning: 'filename' option specified. " + "This is an unsupported option, and may be deprecated " + "in the future"); + iscsi_parse_filename(filename, options, &local_err); + if (local_err) { + ret = -EINVAL; + error_propagate(errp, local_err); + goto exit; + } + } + opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); if (local_err) { @@ -1967,6 +1986,7 @@ out: } memset(iscsilun, 0, sizeof(IscsiLun)); } +exit: return ret; } diff --git a/block/rbd.c b/block/rbd.c index e551639e47..ff44e5f437 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -340,6 +340,10 @@ static QemuOptsList runtime_opts = { .type = QEMU_OPT_STRING, .help = "Legacy rados key/value option parameters", }, + { + .name = "filename", + .type = QEMU_OPT_STRING, + }, { /* end of list */ } }, }; @@ -541,12 +545,27 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, { BDRVRBDState *s = bs->opaque; const char *pool, *snap, *conf, *user, *image_name, *keypairs; - const char *secretid; + const char *secretid, *filename; QemuOpts *opts; Error *local_err = NULL; char *mon_host = NULL; int r; + /* If we are given a filename, parse the filename, with precedence given to + * filename encoded options */ + filename = qdict_get_try_str(options, "filename"); + if (filename) { + error_report("Warning: 'filename' option specified. " + "This is an unsupported option, and may be deprecated " + "in the future"); + qemu_rbd_parse_filename(filename, options, &local_err); + if (local_err) { + r = -EINVAL; + error_propagate(errp, local_err); + goto exit; + } + } + opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); if (local_err) { @@ -665,6 +684,7 @@ failed_shutdown: failed_opts: qemu_opts_del(opts); g_free(mon_host); +exit: return r; } @@ -2301,14 +2301,14 @@ fi # GTK probe if test "$gtkabi" = ""; then - # The GTK ABI was not specified explicitly, so try whether 2.0 is available. - # Use 3.0 as a fallback if that is available. - if $pkg_config --exists "gtk+-2.0 >= 2.18.0"; then - gtkabi=2.0 - elif $pkg_config --exists "gtk+-3.0 >= 3.0.0"; then + # The GTK ABI was not specified explicitly, so try whether 3.0 is available. + # Use 2.0 as a fallback if that is available. + if $pkg_config --exists "gtk+-3.0 >= 3.0.0"; then gtkabi=3.0 - else + elif $pkg_config --exists "gtk+-2.0 >= 2.18.0"; then gtkabi=2.0 + else + gtkabi=3.0 fi fi @@ -2331,7 +2331,7 @@ if test "$gtk" != "no"; then libs_softmmu="$gtk_libs $libs_softmmu" gtk="yes" elif test "$gtk" = "yes"; then - feature_not_found "gtk" "Install gtk2 or gtk3 devel" + feature_not_found "gtk" "Install gtk3-devel" else gtk="no" fi @@ -2598,12 +2598,12 @@ fi # sdl-config even without cross prefix, and favour pkg-config over sdl-config. if test "$sdlabi" = ""; then - if $pkg_config --exists "sdl"; then - sdlabi=1.2 - elif $pkg_config --exists "sdl2"; then + if $pkg_config --exists "sdl2"; then sdlabi=2.0 - else + elif $pkg_config --exists "sdl"; then sdlabi=1.2 + else + sdlabi=2.0 fi fi @@ -2630,7 +2630,7 @@ elif has ${sdl_config}; then sdlversion=$($sdlconfig --version) else if test "$sdl" = "yes" ; then - feature_not_found "sdl" "Install SDL devel" + feature_not_found "sdl" "Install SDL2-devel" fi sdl=no fi diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index 100c8a98bf..de2c5d5702 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -111,7 +111,7 @@ float16 float16_default_nan(float_status *status) *----------------------------------------------------------------------------*/ float32 float32_default_nan(float_status *status) { -#if defined(TARGET_SPARC) +#if defined(TARGET_SPARC) || defined(TARGET_M68K) return const_float32(0x7FFFFFFF); #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \ defined(TARGET_XTENSA) || defined(TARGET_S390X) || defined(TARGET_TRICORE) @@ -136,7 +136,7 @@ float32 float32_default_nan(float_status *status) *----------------------------------------------------------------------------*/ float64 float64_default_nan(float_status *status) { -#if defined(TARGET_SPARC) +#if defined(TARGET_SPARC) || defined(TARGET_M68K) return const_float64(LIT64(0x7FFFFFFFFFFFFFFF)); #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \ defined(TARGET_S390X) @@ -162,7 +162,10 @@ float64 float64_default_nan(float_status *status) floatx80 floatx80_default_nan(float_status *status) { floatx80 r; - +#if defined(TARGET_M68K) + r.low = LIT64(0xFFFFFFFFFFFFFFFF); + r.high = 0x7FFF; +#else if (status->snan_bit_is_one) { r.low = LIT64(0xBFFFFFFFFFFFFFFF); r.high = 0x7FFF; @@ -170,6 +173,7 @@ floatx80 floatx80_default_nan(float_status *status) r.low = LIT64(0xC000000000000000); r.high = 0xFFFF; } +#endif return r; } @@ -502,6 +506,30 @@ static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, return 1; } } +#elif defined(TARGET_M68K) +static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, + flag aIsLargerSignificand) +{ + /* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL + * 3.4 FLOATING-POINT INSTRUCTION DETAILS + * If either operand, but not both operands, of an operation is a + * nonsignaling NaN, then that NaN is returned as the result. If both + * operands are nonsignaling NaNs, then the destination operand + * nonsignaling NaN is returned as the result. + * If either operand to an operation is a signaling NaN (SNaN), then the + * SNaN bit is set in the FPSR EXC byte. If the SNaN exception enable bit + * is set in the FPCR ENABLE byte, then the exception is taken and the + * destination is not modified. If the SNaN exception enable bit is not + * set, setting the SNaN bit in the operand to a one converts the SNaN to + * a nonsignaling NaN. The operation then continues as described in the + * preceding paragraph for nonsignaling NaNs. + */ + if (aIsQNaN || aIsSNaN) { /* a is the destination operand */ + return 0; /* return the destination operand */ + } else { + return 1; /* return b */ + } +} #else static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN, flag aIsLargerSignificand) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 17c572c55f..73090e01ad 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -2241,6 +2241,11 @@ static void ehci_work_bh(void *opaque) uint64_t uframes, skipped_uframes; int i; + if (ehci->working) { + return; + } + ehci->working = true; + t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); ns_elapsed = t_now - ehci->last_run_ns; uframes = ns_elapsed / UFRAME_TIMER_NS; @@ -2322,6 +2327,8 @@ static void ehci_work_bh(void *opaque) } timer_mod(ehci->frame_timer, expire_time); } + + ehci->working = false; } static void ehci_work_timer(void *opaque) diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h index 938d8aa284..821f1ded43 100644 --- a/hw/usb/hcd-ehci.h +++ b/hw/usb/hcd-ehci.h @@ -297,6 +297,7 @@ struct EHCIState { */ QEMUTimer *frame_timer; QEMUBH *async_bh; + bool working; uint32_t astate; /* Current state in asynchronous schedule */ uint32_t pstate; /* Current state in periodic schedule */ USBPort ports[NB_PORTS]; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index a0c7960a7b..760135c0d2 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1912,6 +1912,8 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) } assert(!xfer->running_retry); if (xfer->complete) { + /* update ring dequeue ptr */ + xhci_set_ep_state(xhci, epctx, stctx, epctx->state); xhci_ep_free_xfer(epctx->retry); } epctx->retry = NULL; @@ -1962,6 +1964,8 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) xhci_fire_transfer(xhci, xfer, epctx); } if (xfer->complete) { + /* update ring dequeue ptr */ + xhci_set_ep_state(xhci, epctx, stctx, epctx->state); xhci_ep_free_xfer(xfer); xfer = NULL; } @@ -1979,8 +1983,6 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) break; } } - /* update ring dequeue ptr */ - xhci_set_ep_state(xhci, epctx, stctx, epctx->state); epctx->kick_active--; ep = xhci_epid_to_usbep(epctx); diff --git a/include/migration/colo.h b/include/migration/colo.h index ba0bb6e6d5..be6beba301 100644 --- a/include/migration/colo.h +++ b/include/migration/colo.h @@ -14,9 +14,6 @@ #define QEMU_COLO_H #include "qemu-common.h" -#include "qemu/coroutine_int.h" -#include "qemu/thread.h" -#include "qemu/main-loop.h" bool colo_supported(void); void colo_info_init(void); diff --git a/include/migration/misc.h b/include/migration/misc.h index d5a433afdb..65c7070262 100644 --- a/include/migration/misc.h +++ b/include/migration/misc.h @@ -14,6 +14,8 @@ #ifndef MIGRATION_MISC_H #define MIGRATION_MISC_H +#include "qemu/notify.h" + /* migration/ram.c */ void ram_mig_init(void); diff --git a/include/migration/register.h b/include/migration/register.h index 717c6175b5..d9498d95eb 100644 --- a/include/migration/register.h +++ b/include/migration/register.h @@ -14,9 +14,6 @@ #ifndef MIGRATION_REGISTER_H #define MIGRATION_REGISTER_H -typedef void SaveStateHandler(QEMUFile *f, void *opaque); -typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); - typedef struct SaveVMHandlers { /* This runs inside the iothread lock. */ SaveStateHandler *save_state; diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index f3f3c2af4d..e85fbd81fc 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -29,7 +29,6 @@ #include "migration/qjson.h" -typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); typedef struct VMStateInfo VMStateInfo; typedef struct VMStateDescription VMStateDescription; typedef struct VMStateField VMStateField; diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 51958bf7d3..f745d5faf7 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -96,5 +96,7 @@ typedef struct uWireSlave uWireSlave; typedef struct VirtIODevice VirtIODevice; typedef struct Visitor Visitor; typedef struct node_info NodeInfo; +typedef void SaveStateHandler(QEMUFile *f, void *opaque); +typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); #endif /* QEMU_TYPEDEFS_H */ diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index 184d4c373a..4ba9444dba 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -140,6 +140,8 @@ struct SimpleSpiceCursor { QXLCursor cursor; }; +extern bool spice_opengl; + int qemu_spice_rect_is_empty(const QXLRect* r); void qemu_spice_rect_union(QXLRect *dest, const QXLRect *r); diff --git a/migration/block.c b/migration/block.c index ae06975199..3aae5a375e 100644 --- a/migration/block.c +++ b/migration/block.c @@ -15,19 +15,13 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "qemu-common.h" -#include "block/block.h" #include "qemu/error-report.h" -#include "qemu/main-loop.h" -#include "hw/hw.h" #include "qemu/cutils.h" #include "qemu/queue.h" -#include "qemu/timer.h" #include "block.h" #include "migration/misc.h" #include "migration.h" #include "migration/register.h" -#include "sysemu/blockdev.h" #include "qemu-file.h" #include "migration/vmstate.h" #include "sysemu/block-backend.h" diff --git a/migration/colo-failover.c b/migration/colo-failover.c index cc229f5ab1..f9914869c5 100644 --- a/migration/colo-failover.c +++ b/migration/colo-failover.c @@ -13,6 +13,8 @@ #include "qemu/osdep.h" #include "migration/colo.h" #include "migration/failover.h" +#include "qemu/main-loop.h" +#include "migration.h" #include "qmp-commands.h" #include "qapi/qmp/qerror.h" #include "qemu/error-report.h" diff --git a/migration/colo.c b/migration/colo.c index 45e9b46289..c4ba4c328b 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -11,7 +11,6 @@ */ #include "qemu/osdep.h" -#include "qemu/timer.h" #include "sysemu/sysemu.h" #include "qemu-file-channel.h" #include "migration.h" @@ -22,7 +21,6 @@ #include "io/channel-buffer.h" #include "trace.h" #include "qemu/error-report.h" -#include "qapi/error.h" #include "migration/failover.h" #include "replication.h" #include "qmp-commands.h" @@ -354,7 +352,7 @@ static int colo_do_checkpoint_transaction(MigrationState *s, qemu_savevm_state_header(fb); qemu_savevm_state_begin(fb); qemu_mutex_lock_iothread(); - qemu_savevm_state_complete_precopy(fb, false); + qemu_savevm_state_complete_precopy(fb, false, false); qemu_mutex_unlock_iothread(); qemu_fflush(fb); diff --git a/migration/exec.c b/migration/exec.c index b1de44543a..08b599e0e2 100644 --- a/migration/exec.c +++ b/migration/exec.c @@ -19,10 +19,8 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "qemu-common.h" #include "channel.h" #include "exec.h" -#include "migration.h" #include "io/channel-command.h" #include "trace.h" diff --git a/migration/fd.c b/migration/fd.c index b2384bf133..30f5258a6a 100644 --- a/migration/fd.c +++ b/migration/fd.c @@ -16,10 +16,8 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "qemu-common.h" #include "channel.h" #include "fd.h" -#include "migration.h" #include "monitor/monitor.h" #include "io/channel-util.h" #include "trace.h" diff --git a/migration/global_state.c b/migration/global_state.c index 16ac63fb92..f792cf5242 100644 --- a/migration/global_state.c +++ b/migration/global_state.c @@ -17,7 +17,6 @@ #include "qapi/util.h" #include "migration/global_state.h" #include "migration/vmstate.h" -#include "sysemu/sysemu.h" #include "trace.h" typedef struct { diff --git a/migration/migration.c b/migration/migration.c index 8ef6d6c412..f588329f4c 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -16,7 +16,6 @@ #include "qemu/osdep.h" #include "qemu/cutils.h" #include "qemu/error-report.h" -#include "qemu/main-loop.h" #include "migration/blocker.h" #include "exec.h" #include "fd.h" @@ -30,11 +29,9 @@ #include "qemu-file-channel.h" #include "qemu-file.h" #include "migration/vmstate.h" -#include "sysemu/sysemu.h" #include "block/block.h" #include "qapi/qmp/qerror.h" #include "qapi/util.h" -#include "qemu/sockets.h" #include "qemu/rcu.h" #include "block.h" #include "postcopy-ram.h" @@ -42,9 +39,6 @@ #include "qmp-commands.h" #include "trace.h" #include "qapi-event.h" -#include "qom/cpu.h" -#include "exec/memory.h" -#include "exec/address-spaces.h" #include "exec/target_page.h" #include "io/channel-buffer.h" #include "migration/colo.h" @@ -1559,7 +1553,7 @@ static int postcopy_start(MigrationState *ms, bool *old_vm_running) * Cause any non-postcopiable, but iterative devices to * send out their final data. */ - qemu_savevm_state_complete_precopy(ms->to_dst_file, true); + qemu_savevm_state_complete_precopy(ms->to_dst_file, true, false); /* * in Finish migrate and with the io-lock held everything should @@ -1603,7 +1597,7 @@ static int postcopy_start(MigrationState *ms, bool *old_vm_running) */ qemu_savevm_send_postcopy_listen(fb); - qemu_savevm_state_complete_precopy(fb, false); + qemu_savevm_state_complete_precopy(fb, false, false); qemu_savevm_send_ping(fb, 3); qemu_savevm_send_postcopy_run(fb); @@ -1701,20 +1695,15 @@ static void migration_completion(MigrationState *s, int current_active_state, ret = global_state_store(); if (!ret) { + bool inactivate = !migrate_colo_enabled(); ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); if (ret >= 0) { qemu_file_set_rate_limit(s->to_dst_file, INT64_MAX); - qemu_savevm_state_complete_precopy(s->to_dst_file, false); + ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false, + inactivate); } - /* - * Don't mark the image with BDRV_O_INACTIVE flag if - * we will go into COLO stage later. - */ - if (ret >= 0 && !migrate_colo_enabled()) { - ret = bdrv_inactivate_all(); - if (ret >= 0) { - s->block_inactive = true; - } + if (inactivate && ret >= 0) { + s->block_inactive = true; } } qemu_mutex_unlock_iothread(); @@ -1814,7 +1803,11 @@ static void *migration_thread(void *opaque) qemu_savevm_state_header(s->to_dst_file); - if (s->to_dst_file) { + /* + * If we opened the return path, we need to make sure dst has it + * opened as well. + */ + if (s->rp_state.from_dst_file) { /* Now tell the dest that it should open its end so it can reply */ qemu_savevm_send_open_return_path(s->to_dst_file); diff --git a/migration/migration.h b/migration/migration.h index 601e4ab354..d9a268a3af 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -14,10 +14,8 @@ #ifndef QEMU_MIGRATION_H #define QEMU_MIGRATION_H -#include "qapi/qmp/qdict.h" #include "qemu-common.h" #include "qemu/thread.h" -#include "qemu/notify.h" #include "qapi-types.h" #include "exec/cpu-common.h" #include "qemu/coroutine_int.h" diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index c8c4500cc4..7e21e6fd36 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -17,8 +17,6 @@ */ #include "qemu/osdep.h" - -#include "qemu-common.h" #include "exec/target_page.h" #include "migration.h" #include "qemu-file.h" diff --git a/migration/qemu-file.c b/migration/qemu-file.c index e65c373341..2ab2bf362d 100644 --- a/migration/qemu-file.c +++ b/migration/qemu-file.c @@ -26,8 +26,6 @@ #include "qemu-common.h" #include "qemu/error-report.h" #include "qemu/iov.h" -#include "qemu/sockets.h" -#include "qemu/coroutine.h" #include "migration.h" #include "qemu-file.h" #include "trace.h" diff --git a/migration/ram.c b/migration/ram.c index c1b4f4abf3..0baa1e0d56 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -26,14 +26,12 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" -#include "qemu-common.h" #include "cpu.h" #include <zlib.h> #include "qapi-event.h" #include "qemu/cutils.h" #include "qemu/bitops.h" #include "qemu/bitmap.h" -#include "qemu/timer.h" #include "qemu/main-loop.h" #include "xbzrle.h" #include "ram.h" @@ -41,9 +39,7 @@ #include "migration/register.h" #include "migration/misc.h" #include "qemu-file.h" -#include "migration/vmstate.h" #include "postcopy-ram.h" -#include "exec/address-spaces.h" #include "migration/page_cache.h" #include "qemu/error-report.h" #include "trace.h" @@ -2238,6 +2234,9 @@ void migrate_decompress_threads_create(void) { int i, thread_count; + if (!migrate_use_compression()) { + return; + } thread_count = migrate_decompress_threads(); decompress_threads = g_new0(QemuThread, thread_count); decomp_param = g_new0(DecompressParam, thread_count); @@ -2259,6 +2258,9 @@ void migrate_decompress_threads_join(void) { int i, thread_count; + if (!migrate_use_compression()) { + return; + } thread_count = migrate_decompress_threads(); for (i = 0; i < thread_count; i++) { qemu_mutex_lock(&decomp_param[i].mutex); @@ -2459,7 +2461,7 @@ static int ram_load_postcopy(QEMUFile *f) static int ram_load(QEMUFile *f, void *opaque, int version_id) { - int flags = 0, ret = 0; + int flags = 0, ret = 0, invalid_flags = 0; static uint64_t seq_iter; int len = 0; /* @@ -2476,6 +2478,9 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) ret = -EINVAL; } + if (!migrate_use_compression()) { + invalid_flags |= RAM_SAVE_FLAG_COMPRESS_PAGE; + } /* This RCU critical section can be very long running. * When RCU reclaims in the code start to become numerous, * it will be necessary to reduce the granularity of this @@ -2496,6 +2501,15 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) flags = addr & ~TARGET_PAGE_MASK; addr &= TARGET_PAGE_MASK; + if (flags & invalid_flags) { + if (flags & invalid_flags & RAM_SAVE_FLAG_COMPRESS_PAGE) { + error_report("Received an unexpected compressed page"); + } + + ret = -EINVAL; + break; + } + if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE | RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE)) { RAMBlock *block = ram_block_from_stream(f, flags); diff --git a/migration/savevm.c b/migration/savevm.c index 30cda2cb46..6bfd4893e0 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -28,12 +28,8 @@ #include "qemu/osdep.h" #include "hw/boards.h" -#include "hw/hw.h" -#include "hw/qdev.h" #include "hw/xen/xen.h" #include "net/net.h" -#include "sysemu/sysemu.h" -#include "qemu/timer.h" #include "migration.h" #include "migration/snapshot.h" #include "migration/misc.h" @@ -46,13 +42,11 @@ #include "postcopy-ram.h" #include "qapi/qmp/qerror.h" #include "qemu/error-report.h" -#include "qemu/queue.h" #include "sysemu/cpus.h" #include "exec/memory.h" #include "exec/target_page.h" #include "qmp-commands.h" #include "trace.h" -#include "qemu/bitops.h" #include "qemu/iov.h" #include "block/snapshot.h" #include "qemu/cutils.h" @@ -1110,7 +1104,8 @@ void qemu_savevm_state_complete_postcopy(QEMUFile *f) qemu_fflush(f); } -void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only) +int qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only, + bool inactivate_disks) { QJSON *vmdesc; int vmdesc_len; @@ -1144,12 +1139,12 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only) save_section_footer(f, se); if (ret < 0) { qemu_file_set_error(f, ret); - return; + return -1; } } if (iterable_only) { - return; + return 0; } vmdesc = qjson_new(); @@ -1179,6 +1174,15 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only) json_end_object(vmdesc); } + if (inactivate_disks) { + /* Inactivate before sending QEMU_VM_EOF so that the + * bdrv_invalidate_cache_all() on the other end won't fail. */ + ret = bdrv_inactivate_all(); + if (ret) { + qemu_file_set_error(f, ret); + return ret; + } + } if (!in_postcopy) { /* Postcopy stream will still be going */ qemu_put_byte(f, QEMU_VM_EOF); @@ -1196,6 +1200,7 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only) qjson_destroy(vmdesc); qemu_fflush(f); + return 0; } /* Give an estimate of the amount left to be transferred, @@ -1269,7 +1274,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) ret = qemu_file_get_error(f); if (ret == 0) { - qemu_savevm_state_complete_precopy(f, false); + qemu_savevm_state_complete_precopy(f, false, false); ret = qemu_file_get_error(f); } qemu_savevm_state_cleanup(); diff --git a/migration/savevm.h b/migration/savevm.h index 45b59c19bc..5a2ed1161d 100644 --- a/migration/savevm.h +++ b/migration/savevm.h @@ -35,7 +35,8 @@ void qemu_savevm_state_header(QEMUFile *f); int qemu_savevm_state_iterate(QEMUFile *f, bool postcopy); void qemu_savevm_state_cleanup(void); void qemu_savevm_state_complete_postcopy(QEMUFile *f); -void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only); +int qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only, + bool inactivate_disks); void qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size, uint64_t *res_non_postcopiable, uint64_t *res_postcopiable); diff --git a/target/m68k/Makefile.objs b/target/m68k/Makefile.objs index 02cf616a78..39141ab93d 100644 --- a/target/m68k/Makefile.objs +++ b/target/m68k/Makefile.objs @@ -1,3 +1,3 @@ obj-y += m68k-semi.o -obj-y += translate.o op_helper.o helper.o cpu.o +obj-y += translate.o op_helper.o helper.o cpu.o fpu_helper.o obj-y += gdbstub.o diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c new file mode 100644 index 0000000000..5bf2576c2b --- /dev/null +++ b/target/m68k/fpu_helper.c @@ -0,0 +1,112 @@ +/* + * m68k FPU helpers + * + * Copyright (c) 2006-2007 CodeSourcery + * Written by Paul Brook + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/helper-proto.h" + +uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val) +{ + return float64_to_int32(val, &env->fp_status); +} + +float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val) +{ + return float64_to_float32(val, &env->fp_status); +} + +float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val) +{ + return int32_to_float64(val, &env->fp_status); +} + +float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val) +{ + return float32_to_float64(val, &env->fp_status); +} + +float64 HELPER(iround_f64)(CPUM68KState *env, float64 val) +{ + return float64_round_to_int(val, &env->fp_status); +} + +float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val) +{ + return float64_trunc_to_int(val, &env->fp_status); +} + +float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val) +{ + return float64_sqrt(val, &env->fp_status); +} + +float64 HELPER(abs_f64)(float64 val) +{ + return float64_abs(val); +} + +float64 HELPER(chs_f64)(float64 val) +{ + return float64_chs(val); +} + +float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b) +{ + return float64_add(a, b, &env->fp_status); +} + +float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b) +{ + return float64_sub(a, b, &env->fp_status); +} + +float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b) +{ + return float64_mul(a, b, &env->fp_status); +} + +float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b) +{ + return float64_div(a, b, &env->fp_status); +} + +float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b) +{ + /* ??? This may incorrectly raise exceptions. */ + /* ??? Should flush denormals to zero. */ + float64 res; + res = float64_sub(a, b, &env->fp_status); + if (float64_is_quiet_nan(res, &env->fp_status)) { + /* +/-inf compares equal against itself, but sub returns nan. */ + if (!float64_is_quiet_nan(a, &env->fp_status) + && !float64_is_quiet_nan(b, &env->fp_status)) { + res = float64_zero; + if (float64_lt_quiet(a, res, &env->fp_status)) { + res = float64_chs(res); + } + } + } + return res; +} + +uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val) +{ + return float64_compare_quiet(val, float64_zero, &env->fp_status); +} diff --git a/target/m68k/helper.c b/target/m68k/helper.c index f750d3dbaa..5ca9911657 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -284,94 +284,6 @@ void HELPER(set_sr)(CPUM68KState *env, uint32_t val) m68k_switch_sp(env); } -/* FPU helpers. */ -uint32_t HELPER(f64_to_i32)(CPUM68KState *env, float64 val) -{ - return float64_to_int32(val, &env->fp_status); -} - -float32 HELPER(f64_to_f32)(CPUM68KState *env, float64 val) -{ - return float64_to_float32(val, &env->fp_status); -} - -float64 HELPER(i32_to_f64)(CPUM68KState *env, uint32_t val) -{ - return int32_to_float64(val, &env->fp_status); -} - -float64 HELPER(f32_to_f64)(CPUM68KState *env, float32 val) -{ - return float32_to_float64(val, &env->fp_status); -} - -float64 HELPER(iround_f64)(CPUM68KState *env, float64 val) -{ - return float64_round_to_int(val, &env->fp_status); -} - -float64 HELPER(itrunc_f64)(CPUM68KState *env, float64 val) -{ - return float64_trunc_to_int(val, &env->fp_status); -} - -float64 HELPER(sqrt_f64)(CPUM68KState *env, float64 val) -{ - return float64_sqrt(val, &env->fp_status); -} - -float64 HELPER(abs_f64)(float64 val) -{ - return float64_abs(val); -} - -float64 HELPER(chs_f64)(float64 val) -{ - return float64_chs(val); -} - -float64 HELPER(add_f64)(CPUM68KState *env, float64 a, float64 b) -{ - return float64_add(a, b, &env->fp_status); -} - -float64 HELPER(sub_f64)(CPUM68KState *env, float64 a, float64 b) -{ - return float64_sub(a, b, &env->fp_status); -} - -float64 HELPER(mul_f64)(CPUM68KState *env, float64 a, float64 b) -{ - return float64_mul(a, b, &env->fp_status); -} - -float64 HELPER(div_f64)(CPUM68KState *env, float64 a, float64 b) -{ - return float64_div(a, b, &env->fp_status); -} - -float64 HELPER(sub_cmp_f64)(CPUM68KState *env, float64 a, float64 b) -{ - /* ??? This may incorrectly raise exceptions. */ - /* ??? Should flush denormals to zero. */ - float64 res; - res = float64_sub(a, b, &env->fp_status); - if (float64_is_quiet_nan(res, &env->fp_status)) { - /* +/-inf compares equal against itself, but sub returns nan. */ - if (!float64_is_quiet_nan(a, &env->fp_status) - && !float64_is_quiet_nan(b, &env->fp_status)) { - res = float64_zero; - if (float64_lt_quiet(a, res, &env->fp_status)) - res = float64_chs(res); - } - } - return res; -} - -uint32_t HELPER(compare_f64)(CPUM68KState *env, float64 val) -{ - return float64_compare_quiet(val, float64_zero, &env->fp_status); -} /* MAC unit. */ /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers diff --git a/target/m68k/translate.c b/target/m68k/translate.c index ad4d4efb8d..dfecfb6e5f 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -565,7 +565,7 @@ static void gen_flush_flags(DisasContext *s) t1 = tcg_temp_new(); tcg_gen_add_i32(t0, QREG_CC_N, QREG_CC_V); gen_ext(t0, t0, s->cc_op - CC_OP_SUBB, 1); - tcg_gen_xor_i32(t1, QREG_CC_N, QREG_CC_V); + tcg_gen_xor_i32(t1, QREG_CC_N, t0); tcg_gen_xor_i32(QREG_CC_V, QREG_CC_V, t0); tcg_temp_free(t0); tcg_gen_and_i32(QREG_CC_V, QREG_CC_V, t1); @@ -669,6 +669,21 @@ static inline int insn_opsize(int insn) } } +static inline int ext_opsize(int ext, int pos) +{ + switch ((ext >> pos) & 7) { + case 0: return OS_LONG; + case 1: return OS_SINGLE; + case 2: return OS_EXTENDED; + case 3: return OS_PACKED; + case 4: return OS_WORD; + case 5: return OS_DOUBLE; + case 6: return OS_BYTE; + default: + g_assert_not_reached(); + } +} + /* Assign value to a register. If the width is less than the register width only the low part of the register is set. */ static void gen_partset_reg(int opsize, TCGv reg, TCGv val) @@ -4111,20 +4126,19 @@ DISAS_INSN(fpu) tmp32 = tcg_temp_new_i32(); /* fmove */ /* ??? TODO: Proper behavior on overflow. */ - switch ((ext >> 10) & 7) { - case 0: - opsize = OS_LONG; + + opsize = ext_opsize(ext, 10); + switch (opsize) { + case OS_LONG: gen_helper_f64_to_i32(tmp32, cpu_env, src); break; - case 1: - opsize = OS_SINGLE; + case OS_SINGLE: gen_helper_f64_to_f32(tmp32, cpu_env, src); break; - case 4: - opsize = OS_WORD; + case OS_WORD: gen_helper_f64_to_i32(tmp32, cpu_env, src); break; - case 5: /* OS_DOUBLE */ + case OS_DOUBLE: tcg_gen_mov_i32(tmp32, AREG(insn, 0)); switch ((insn >> 3) & 7) { case 2: @@ -4153,8 +4167,7 @@ DISAS_INSN(fpu) } tcg_temp_free_i32(tmp32); return; - case 6: - opsize = OS_BYTE; + case OS_BYTE: gen_helper_f64_to_i32(tmp32, cpu_env, src); break; default: @@ -4227,15 +4240,7 @@ DISAS_INSN(fpu) } if (ext & (1 << 14)) { /* Source effective address. */ - switch ((ext >> 10) & 7) { - case 0: opsize = OS_LONG; break; - case 1: opsize = OS_SINGLE; break; - case 4: opsize = OS_WORD; break; - case 5: opsize = OS_DOUBLE; break; - case 6: opsize = OS_BYTE; break; - default: - goto undef; - } + opsize = ext_opsize(ext, 10); if (opsize == OS_DOUBLE) { tmp32 = tcg_temp_new_i32(); tcg_gen_mov_i32(tmp32, AREG(insn, 0)); diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index a4d31df2b5..a4028fb315 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -149,7 +149,7 @@ typedef struct CPUS390XState { CPU_COMMON uint32_t cpu_num; - uint32_t machine_type; + uint64_t cpuid; uint64_t tod_offset; uint64_t tod_basetime; @@ -460,11 +460,6 @@ static inline bool get_per_in_range(CPUS390XState *env, uint64_t addr) } #ifndef CONFIG_USER_ONLY -/* In several cases of runtime exceptions, we havn't recorded the true - instruction length. Use these codes when raising exceptions in order - to re-compute the length by examining the insn in memory. */ -#define ILEN_LATER 0x20 -#define ILEN_LATER_INC 0x21 void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen); #endif @@ -1133,6 +1128,8 @@ uint32_t set_cc_nz_f128(float128 v); int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3); void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3); #endif +/* automatically detect the instruction length */ +#define ILEN_AUTO 0xff void program_interrupt(CPUS390XState *env, uint32_t code, int ilen); void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, uintptr_t retaddr); diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index b34318f1e3..478bcc604e 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -737,8 +737,6 @@ static inline void apply_cpu_model(const S390CPUModel *model, Error **errp) if (kvm_enabled()) { kvm_s390_apply_cpu_model(model, errp); - } else if (model) { - /* FIXME TCG - use data for stdip/stfl */ } if (!*errp) { @@ -786,6 +784,12 @@ void s390_realize_cpu_model(CPUState *cs, Error **errp) } apply_cpu_model(cpu->model, errp); + + cpu->env.cpuid = s390_cpuid_from_cpu_model(cpu->model); + if (tcg_enabled()) { + /* basic mode, write the cpu address into the first 4 bit of the ID */ + cpu->env.cpuid = deposit64(cpu->env.cpuid, 54, 4, cpu->env.cpu_num); + } } static void get_feature(Object *obj, Visitor *v, const char *name, diff --git a/target/s390x/helper.c b/target/s390x/helper.c index a8d20c51fa..aef09e1234 100644 --- a/target/s390x/helper.c +++ b/target/s390x/helper.c @@ -204,7 +204,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, if (raddr > ram_size) { DPRINTF("%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__, (uint64_t)raddr, (uint64_t)ram_size); - trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER_INC); + trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_AUTO); return 1; } @@ -331,16 +331,42 @@ static void do_program_interrupt(CPUS390XState *env) LowCore *lowcore; int ilen = env->int_pgm_ilen; - switch (ilen) { - case ILEN_LATER: - ilen = get_ilen(cpu_ldub_code(env, env->psw.addr)); - break; - case ILEN_LATER_INC: + if (ilen == ILEN_AUTO) { ilen = get_ilen(cpu_ldub_code(env, env->psw.addr)); + } + assert(ilen == 2 || ilen == 4 || ilen == 6); + + switch (env->int_pgm_code) { + case PGM_PER: + if (env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION) { + break; + } + /* FALL THROUGH */ + case PGM_OPERATION: + case PGM_PRIVILEGED: + case PGM_EXECUTE: + case PGM_PROTECTION: + case PGM_ADDRESSING: + case PGM_SPECIFICATION: + case PGM_DATA: + case PGM_FIXPT_OVERFLOW: + case PGM_FIXPT_DIVIDE: + case PGM_DEC_OVERFLOW: + case PGM_DEC_DIVIDE: + case PGM_HFP_EXP_OVERFLOW: + case PGM_HFP_EXP_UNDERFLOW: + case PGM_HFP_SIGNIFICANCE: + case PGM_HFP_DIVIDE: + case PGM_TRANS_SPEC: + case PGM_SPECIAL_OP: + case PGM_OPERAND: + case PGM_HFP_SQRT: + case PGM_PC_TRANS_SPEC: + case PGM_ALET_SPEC: + case PGM_MONITOR: + /* advance the PSW if our exception is not nullifying */ env->psw.addr += ilen; break; - default: - assert(ilen == 2 || ilen == 4 || ilen == 6); } qemu_log_mask(CPU_LOG_INT, "%s: code=0x%x ilen=%d\n", @@ -737,6 +763,6 @@ void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr, if (retaddr) { cpu_restore_state(cs, retaddr); } - program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER); + program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); } #endif /* CONFIG_USER_ONLY */ diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def index 73dd05daf0..d089707073 100644 --- a/target/s390x/insn-data.def +++ b/target/s390x/insn-data.def @@ -960,7 +960,7 @@ /* STORE CPU ADDRESS */ C(0xb212, STAP, S, Z, la2, 0, new, m1_16, stap, 0) /* STORE CPU ID */ - C(0xb202, STIDP, S, Z, la2, 0, new, m1_64, stidp, 0) + C(0xb202, STIDP, S, Z, la2, 0, new, 0, stidp, 0) /* STORE CPU TIMER */ C(0xb209, STPT, S, Z, la2, 0, new, m1_64, stpt, 0) /* STORE FACILITY LIST */ diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c index edcdf17db6..b5081019c5 100644 --- a/target/s390x/misc_helper.c +++ b/target/s390x/misc_helper.c @@ -54,19 +54,14 @@ void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp, uintptr_t retaddr) { CPUState *cs = CPU(s390_env_get_cpu(env)); - int t; cs->exception_index = EXCP_PGM; env->int_pgm_code = excp; + env->int_pgm_ilen = ILEN_AUTO; /* Use the (ultimate) callers address to find the insn that trapped. */ cpu_restore_state(cs, retaddr); - /* Advance past the insn. */ - t = cpu_ldub_code(env, env->psw.addr); - env->int_pgm_ilen = t = get_ilen(t); - env->psw.addr += t; - cpu_loop_exit(cs); } @@ -199,12 +194,12 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) IplParameterBlock *iplb; if (env->psw.mask & PSW_MASK_PSTATE) { - program_interrupt(env, PGM_PRIVILEGED, ILEN_LATER_INC); + program_interrupt(env, PGM_PRIVILEGED, ILEN_AUTO); return; } if ((subcode & ~0x0ffffULL) || (subcode > 6)) { - program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); + program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); return; } @@ -229,12 +224,12 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3) break; case 5: if ((r1 & 1) || (addr & 0x0fffULL)) { - program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); + program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); return; } if (!address_space_access_valid(&address_space_memory, addr, sizeof(IplParameterBlock), false)) { - program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC); + program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO); return; } iplb = g_malloc0(sizeof(IplParameterBlock)); @@ -258,12 +253,12 @@ out: return; case 6: if ((r1 & 1) || (addr & 0x0fffULL)) { - program_interrupt(env, PGM_SPECIFICATION, ILEN_LATER_INC); + program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO); return; } if (!address_space_access_valid(&address_space_memory, addr, sizeof(IplParameterBlock), true)) { - program_interrupt(env, PGM_ADDRESSING, ILEN_LATER_INC); + program_interrupt(env, PGM_ADDRESSING, ILEN_AUTO); return; } iplb = s390_ipl_get_iplb(); @@ -307,7 +302,7 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num) } if (r) { - program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC); + program_interrupt(env, PGM_OPERATION, ILEN_AUTO); } } @@ -383,6 +378,7 @@ uint64_t HELPER(stpt)(CPUS390XState *env) uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, uint64_t r0, uint64_t r1) { + S390CPU *cpu = s390_env_get_cpu(env); int cc = 0; int sel1, sel2; @@ -402,12 +398,14 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, if ((sel1 == 1) && (sel2 == 1)) { /* Basic Machine Configuration */ struct sysib_111 sysib; + char type[5] = {}; memset(&sysib, 0, sizeof(sysib)); ebcdic_put(sysib.manuf, "QEMU ", 16); - /* same as machine type number in STORE CPU ID */ - ebcdic_put(sysib.type, "QEMU", 4); - /* same as model number in STORE CPU ID */ + /* same as machine type number in STORE CPU ID, but in EBCDIC */ + snprintf(type, ARRAY_SIZE(type), "%X", cpu->model->def->type); + ebcdic_put(sysib.type, type, 4); + /* model number (not stored in STORE CPU ID for z/Architecure) */ ebcdic_put(sysib.model, "QEMU ", 16); ebcdic_put(sysib.sequence, "QEMU ", 16); ebcdic_put(sysib.plant, "QEMU", 4); @@ -668,6 +666,7 @@ void HELPER(per_ifetch)(CPUS390XState *env, uint64_t addr) if (env->cregs[9] & PER_CR9_EVENT_NULLIFICATION) { CPUState *cs = CPU(s390_env_get_cpu(env)); + env->per_perc_atmid |= PER_CODE_EVENT_NULLIFICATION; env->int_pgm_code = PGM_PER; env->int_pgm_ilen = get_ilen(cpu_ldub_code(env, addr)); diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c index 501e39010d..a873dc48a0 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -79,13 +79,13 @@ static void trigger_prot_fault(CPUS390XState *env, target_ulong vaddr, return; } - trigger_access_exception(env, PGM_PROTECTION, ILEN_LATER_INC, tec); + trigger_access_exception(env, PGM_PROTECTION, ILEN_AUTO, tec); } static void trigger_page_fault(CPUS390XState *env, target_ulong vaddr, uint32_t type, uint64_t asc, int rw, bool exc) { - int ilen = ILEN_LATER; + int ilen = ILEN_AUTO; uint64_t tec; tec = vaddr | (rw == MMU_DATA_STORE ? FS_WRITE : FS_READ) | asc >> 46; @@ -431,7 +431,7 @@ static int translate_pages(S390CPU *cpu, vaddr addr, int nr_pages, for (i = 0; i < nr_pages; i++) { /* Low-address protection? */ if (lowprot && (addr < 512 || (addr >= 4096 && addr < 4096 + 512))) { - trigger_access_exception(env, PGM_PROTECTION, ILEN_LATER_INC, 0); + trigger_access_exception(env, PGM_PROTECTION, ILEN_AUTO, 0); return -EACCES; } ret = mmu_translate(env, addr, is_write, asc, &pages[i], &pflags, true); diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 95f91d4f08..8c055b7bb7 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -355,8 +355,7 @@ static void gen_program_exception(DisasContext *s, int code) tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUS390XState, int_pgm_ilen)); tcg_temp_free_i32(tmp); - /* Advance past instruction. */ - s->pc = s->next_pc; + /* update the psw */ update_psw_addr(s); /* Save off cc. */ @@ -3877,14 +3876,9 @@ static ExitStatus op_stctl(DisasContext *s, DisasOps *o) static ExitStatus op_stidp(DisasContext *s, DisasOps *o) { - TCGv_i64 t1 = tcg_temp_new_i64(); - check_privileged(s); - tcg_gen_ld32u_i64(o->out, cpu_env, offsetof(CPUS390XState, cpu_num)); - tcg_gen_ld32u_i64(t1, cpu_env, offsetof(CPUS390XState, machine_type)); - tcg_gen_deposit_i64(o->out, o->out, t1, 32, 32); - tcg_temp_free_i64(t1); - + tcg_gen_ld_i64(o->out, cpu_env, offsetof(CPUS390XState, cpuid)); + tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN); return NO_EXIT; } diff --git a/ui/cocoa.m b/ui/cocoa.m index 004ec2711c..1f010d3ae7 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -52,6 +52,8 @@ /* macOS 10.12 deprecated many constants, #define the new names for older SDKs */ #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 #define NSEventMaskAny NSAnyEventMask +#define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask +#define NSEventModifierFlagShift NSShiftKeyMask #define NSEventModifierFlagCommand NSCommandKeyMask #define NSEventModifierFlagControl NSControlKeyMask #define NSEventModifierFlagOption NSAlternateKeyMask @@ -268,7 +270,7 @@ static void handleAnyDeviceErrors(Error * err) NSWindow *fullScreenWindow; float cx,cy,cw,ch,cdx,cdy; CGDataProviderRef dataProviderRef; - int modifiers_state[256]; + BOOL modifiers_state[256]; BOOL isMouseGrabbed; BOOL isFullscreen; BOOL isAbsoluteEnabled; @@ -536,18 +538,59 @@ QemuCocoaView *cocoaView; } } +- (void) toggleModifier: (int)keycode { + // Toggle the stored state. + modifiers_state[keycode] = !modifiers_state[keycode]; + // Send a keyup or keydown depending on the state. + qemu_input_event_send_key_qcode(dcl->con, keycode, modifiers_state[keycode]); +} + +- (void) toggleStatefulModifier: (int)keycode { + // Toggle the stored state. + modifiers_state[keycode] = !modifiers_state[keycode]; + // Generate keydown and keyup. + qemu_input_event_send_key_qcode(dcl->con, keycode, true); + qemu_input_event_send_key_qcode(dcl->con, keycode, false); +} + - (void) handleEvent:(NSEvent *)event { COCOA_DEBUG("QemuCocoaView: handleEvent\n"); int buttons = 0; - int keycode; + int keycode = 0; bool mouse_event = false; NSPoint p = [event locationInWindow]; switch ([event type]) { case NSEventTypeFlagsChanged: - keycode = cocoa_keycode_to_qemu([event keyCode]); + if ([event keyCode] == 0) { + // When the Cocoa keyCode is zero that means keys should be + // synthesized based on the values in in the eventModifiers + // bitmask. + + if (qemu_console_is_graphic(NULL)) { + NSEventModifierFlags modifiers = [event modifierFlags]; + + if (!!(modifiers & NSEventModifierFlagCapsLock) != !!modifiers_state[Q_KEY_CODE_CAPS_LOCK]) { + [self toggleStatefulModifier:Q_KEY_CODE_CAPS_LOCK]; + } + if (!!(modifiers & NSEventModifierFlagShift) != !!modifiers_state[Q_KEY_CODE_SHIFT]) { + [self toggleModifier:Q_KEY_CODE_SHIFT]; + } + if (!!(modifiers & NSEventModifierFlagControl) != !!modifiers_state[Q_KEY_CODE_CTRL]) { + [self toggleModifier:Q_KEY_CODE_CTRL]; + } + if (!!(modifiers & NSEventModifierFlagOption) != !!modifiers_state[Q_KEY_CODE_ALT]) { + [self toggleModifier:Q_KEY_CODE_ALT]; + } + if (!!(modifiers & NSEventModifierFlagCommand) != !!modifiers_state[Q_KEY_CODE_META_L]) { + [self toggleModifier:Q_KEY_CODE_META_L]; + } + } + } else { + keycode = cocoa_keycode_to_qemu([event keyCode]); + } if ((keycode == Q_KEY_CODE_META_L || keycode == Q_KEY_CODE_META_R) && !isMouseGrabbed) { @@ -559,16 +602,9 @@ QemuCocoaView *cocoaView; // emulate caps lock and num lock keydown and keyup if (keycode == Q_KEY_CODE_CAPS_LOCK || keycode == Q_KEY_CODE_NUM_LOCK) { - qemu_input_event_send_key_qcode(dcl->con, keycode, true); - qemu_input_event_send_key_qcode(dcl->con, keycode, false); + [self toggleStatefulModifier:keycode]; } else if (qemu_console_is_graphic(NULL)) { - if (modifiers_state[keycode] == 0) { // keydown - qemu_input_event_send_key_qcode(dcl->con, keycode, true); - modifiers_state[keycode] = 1; - } else { // keyup - qemu_input_event_send_key_qcode(dcl->con, keycode, false); - modifiers_state[keycode] = 0; - } + [self toggleModifier:keycode]; } } diff --git a/ui/spice-core.c b/ui/spice-core.c index a087ad5da9..182f550f1f 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -847,6 +847,7 @@ void qemu_spice_init(void) exit(1); } display_opengl = 1; + spice_opengl = 1; } #endif } diff --git a/ui/spice-display.c b/ui/spice-display.c index b353445f58..042292cc90 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -27,6 +27,7 @@ #include "ui/spice-display.h" static int debug = 0; +bool spice_opengl; static void GCC_FMT_ATTR(2, 3) dprint(int level, const char *fmt, ...) { @@ -1013,7 +1014,7 @@ static void qemu_spice_display_init_one(QemuConsole *con) ssd->dcl.ops = &display_listener_ops; #ifdef HAVE_SPICE_GL - if (display_opengl) { + if (spice_opengl) { ssd->dcl.ops = &display_listener_gl_ops; ssd->gl_unblock_bh = qemu_bh_new(qemu_spice_gl_unblock_bh, ssd); ssd->gl_unblock_timer = timer_new_ms(QEMU_CLOCK_REALTIME, diff --git a/ui/spice-input.c b/ui/spice-input.c index 86293dd2ce..918580239d 100644 --- a/ui/spice-input.c +++ b/ui/spice-input.c @@ -87,7 +87,7 @@ static void kbd_leds(void *opaque, int ledstate) if (ledstate & QEMU_CAPS_LOCK_LED) { kbd->ledstate |= SPICE_KEYBOARD_MODIFIER_FLAGS_CAPS_LOCK; } - spice_server_kbd_leds(&kbd->sin, ledstate); + spice_server_kbd_leds(&kbd->sin, kbd->ledstate); } /* mouse bits */ |