diff options
34 files changed, 199 insertions, 136 deletions
@@ -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/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 17c572c..73090e0 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 938d8aa..821f1de 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 a0c7960..760135c 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 ba0bb6e..be6beba 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 d5a433a..65c7070 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 717c617..d9498d9 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 f3f3c2a..e85fbd8 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 51958bf..f745d5f 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 184d4c3..4ba9444 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 ae06975..3aae5a3 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 cc229f5..f991486 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 45e9b46..c4ba4c3 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 b1de445..08b599e 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 b2384bf..30f5258 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 16ac63f..f792cf5 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 8ef6d6c..f588329 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 601e4ab..d9a268a 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 c8c4500..7e21e6f 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 e65c373..2ab2bf3 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 c1b4f4a..0baa1e0 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 30cda2c..6bfd489 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 45b59c1..5a2ed11 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/s390x/cpu.h b/target/s390x/cpu.h index a4d31df..a4028fb 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 b34318f..478bcc6 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 a8d20c5..aef09e1 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 73dd05d..d089707 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 edcdf17..b508101 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 501e390..a873dc4 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 95f91d4..8c055b7 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; } @@ -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 a087ad5..182f550 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 b353445..042292c 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 86293dd..9185802 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 */ |