diff options
| -rw-r--r-- | block/file-posix.c | 146 | ||||
| -rw-r--r-- | blockjob.c | 27 | ||||
| -rw-r--r-- | hw/s390x/ccw-device.c | 8 | ||||
| -rw-r--r-- | hw/s390x/css.c | 8 | ||||
| -rw-r--r-- | hw/s390x/ipl.c | 43 | ||||
| -rw-r--r-- | hw/s390x/ipl.h | 16 | ||||
| -rw-r--r-- | hw/s390x/s390-virtio-ccw.c | 51 | ||||
| -rw-r--r-- | hw/s390x/virtio-ccw.c | 20 | ||||
| -rw-r--r-- | hw/s390x/virtio-ccw.h | 1 | ||||
| -rw-r--r-- | include/block/blockjob_int.h | 14 | ||||
| -rw-r--r-- | include/hw/s390x/s390-virtio-ccw.h | 2 | ||||
| -rw-r--r-- | pc-bios/s390-ccw/cio.h | 2 | ||||
| -rw-r--r-- | qapi/block-core.json | 7 | ||||
| -rwxr-xr-x | scripts/checkpatch.pl | 56 | ||||
| -rw-r--r-- | target/s390x/cpu.h | 26 | ||||
| -rw-r--r-- | target/s390x/diag.c | 61 | ||||
| -rw-r--r-- | target/s390x/internal.h | 6 | ||||
| -rw-r--r-- | target/s390x/kvm.c | 2 | ||||
| -rw-r--r-- | target/s390x/misc_helper.c | 2 |
19 files changed, 354 insertions, 144 deletions
diff --git a/block/file-posix.c b/block/file-posix.c index 3794c0007a..5a602cfe37 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -161,6 +161,7 @@ typedef struct BDRVRawState { bool page_cache_inconsistent:1; bool has_fallocate; bool needs_alignment; + bool check_cache_dropped; PRManager *pr_mgr; } BDRVRawState; @@ -168,6 +169,7 @@ typedef struct BDRVRawState { typedef struct BDRVRawReopenState { int fd; int open_flags; + bool check_cache_dropped; } BDRVRawReopenState; static int fd_open(BlockDriverState *bs); @@ -415,6 +417,11 @@ static QemuOptsList raw_runtime_opts = { .type = QEMU_OPT_STRING, .help = "id of persistent reservation manager object (default: none)", }, + { + .name = "x-check-cache-dropped", + .type = QEMU_OPT_BOOL, + .help = "check that page cache was dropped on live migration (default: off)" + }, { /* end of list */ } }, }; @@ -500,6 +507,9 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, } } + s->check_cache_dropped = qemu_opt_get_bool(opts, "x-check-cache-dropped", + false); + s->open_flags = open_flags; raw_parse_flags(bdrv_flags, &s->open_flags); @@ -777,6 +787,7 @@ static int raw_reopen_prepare(BDRVReopenState *state, { BDRVRawState *s; BDRVRawReopenState *rs; + QemuOpts *opts; int ret = 0; Error *local_err = NULL; @@ -787,6 +798,19 @@ static int raw_reopen_prepare(BDRVReopenState *state, state->opaque = g_new0(BDRVRawReopenState, 1); rs = state->opaque; + rs->fd = -1; + + /* Handle options changes */ + opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort); + qemu_opts_absorb_qdict(opts, state->options, &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret = -EINVAL; + goto out; + } + + rs->check_cache_dropped = qemu_opt_get_bool(opts, "x-check-cache-dropped", + s->check_cache_dropped); if (s->type == FTYPE_CD) { rs->open_flags |= O_NONBLOCK; @@ -794,8 +818,6 @@ static int raw_reopen_prepare(BDRVReopenState *state, raw_parse_flags(state->flags, &rs->open_flags); - rs->fd = -1; - int fcntl_flags = O_APPEND | O_NONBLOCK; #ifdef O_NOATIME fcntl_flags |= O_NOATIME; @@ -850,6 +872,8 @@ static int raw_reopen_prepare(BDRVReopenState *state, } } +out: + qemu_opts_del(opts); return ret; } @@ -858,6 +882,7 @@ static void raw_reopen_commit(BDRVReopenState *state) BDRVRawReopenState *rs = state->opaque; BDRVRawState *s = state->bs->opaque; + s->check_cache_dropped = rs->check_cache_dropped; s->open_flags = rs->open_flags; qemu_close(s->fd); @@ -2236,6 +2261,120 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, return ret | BDRV_BLOCK_OFFSET_VALID; } +#if defined(__linux__) +/* Verify that the file is not in the page cache */ +static void check_cache_dropped(BlockDriverState *bs, Error **errp) +{ + const size_t window_size = 128 * 1024 * 1024; + BDRVRawState *s = bs->opaque; + void *window = NULL; + size_t length = 0; + unsigned char *vec; + size_t page_size; + off_t offset; + off_t end; + + /* mincore(2) page status information requires 1 byte per page */ + page_size = sysconf(_SC_PAGESIZE); + vec = g_malloc(DIV_ROUND_UP(window_size, page_size)); + + end = raw_getlength(bs); + + for (offset = 0; offset < end; offset += window_size) { + void *new_window; + size_t new_length; + size_t vec_end; + size_t i; + int ret; + + /* Unmap previous window if size has changed */ + new_length = MIN(end - offset, window_size); + if (new_length != length) { + munmap(window, length); + window = NULL; + length = 0; + } + + new_window = mmap(window, new_length, PROT_NONE, MAP_PRIVATE, + s->fd, offset); + if (new_window == MAP_FAILED) { + error_setg_errno(errp, errno, "mmap failed"); + break; + } + + window = new_window; + length = new_length; + + ret = mincore(window, length, vec); + if (ret < 0) { + error_setg_errno(errp, errno, "mincore failed"); + break; + } + + vec_end = DIV_ROUND_UP(length, page_size); + for (i = 0; i < vec_end; i++) { + if (vec[i] & 0x1) { + error_setg(errp, "page cache still in use!"); + break; + } + } + } + + if (window) { + munmap(window, length); + } + + g_free(vec); +} +#endif /* __linux__ */ + +static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs, + Error **errp) +{ + BDRVRawState *s = bs->opaque; + int ret; + + ret = fd_open(bs); + if (ret < 0) { + error_setg_errno(errp, -ret, "The file descriptor is not open"); + return; + } + + if (s->open_flags & O_DIRECT) { + return; /* No host kernel page cache */ + } + +#if defined(__linux__) + /* This sets the scene for the next syscall... */ + ret = bdrv_co_flush(bs); + if (ret < 0) { + error_setg_errno(errp, -ret, "flush failed"); + return; + } + + /* Linux does not invalidate pages that are dirty, locked, or mmapped by a + * process. These limitations are okay because we just fsynced the file, + * we don't use mmap, and the file should not be in use by other processes. + */ + ret = posix_fadvise(s->fd, 0, 0, POSIX_FADV_DONTNEED); + if (ret != 0) { /* the return value is a positive errno */ + error_setg_errno(errp, ret, "fadvise failed"); + return; + } + + if (s->check_cache_dropped) { + check_cache_dropped(bs, errp); + } +#else /* __linux__ */ + /* Do nothing. Live migration to a remote host with cache.direct=off is + * unsupported on other host operating systems. Cache consistency issues + * may occur but no error is reported here, partly because that's the + * historical behavior and partly because it's hard to differentiate valid + * configurations that should not cause errors. + */ +#endif /* !__linux__ */ +} + static coroutine_fn BlockAIOCB *raw_aio_pdiscard(BlockDriverState *bs, int64_t offset, int bytes, BlockCompletionFunc *cb, void *opaque) @@ -2328,6 +2467,7 @@ BlockDriver bdrv_file = { .bdrv_co_create_opts = raw_co_create_opts, .bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_co_block_status = raw_co_block_status, + .bdrv_co_invalidate_cache = raw_co_invalidate_cache, .bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes, .bdrv_co_preadv = raw_co_preadv, @@ -2805,6 +2945,7 @@ static BlockDriver bdrv_host_device = { .bdrv_reopen_abort = raw_reopen_abort, .bdrv_co_create_opts = hdev_co_create_opts, .create_opts = &raw_create_opts, + .bdrv_co_invalidate_cache = raw_co_invalidate_cache, .bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes, .bdrv_co_preadv = raw_co_preadv, @@ -2927,6 +3068,7 @@ static BlockDriver bdrv_host_cdrom = { .bdrv_reopen_abort = raw_reopen_abort, .bdrv_co_create_opts = hdev_co_create_opts, .create_opts = &raw_create_opts, + .bdrv_co_invalidate_cache = raw_co_invalidate_cache, .bdrv_co_preadv = raw_co_preadv, diff --git a/blockjob.c b/blockjob.c index 27f957e571..dfffad921a 100644 --- a/blockjob.c +++ b/blockjob.c @@ -988,19 +988,6 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, return job; } -void block_job_pause_all(void) -{ - BlockJob *job = NULL; - while ((job = block_job_next(job))) { - AioContext *aio_context = blk_get_aio_context(job->blk); - - aio_context_acquire(aio_context); - block_job_ref(job); - block_job_pause(job); - aio_context_release(aio_context); - } -} - void block_job_early_fail(BlockJob *job) { assert(job->status == BLOCK_JOB_STATUS_CREATED); @@ -1078,20 +1065,6 @@ void coroutine_fn block_job_pause_point(BlockJob *job) } } -void block_job_resume_all(void) -{ - BlockJob *job, *next; - - QLIST_FOREACH_SAFE(job, &block_jobs, job_list, next) { - AioContext *aio_context = blk_get_aio_context(job->blk); - - aio_context_acquire(aio_context); - block_job_resume(job); - block_job_unref(job); - aio_context_release(aio_context); - } -} - /* * Conditionally enter a block_job pending a call to fn() while * under the block_job_lock critical section. diff --git a/hw/s390x/ccw-device.c b/hw/s390x/ccw-device.c index f9bfa154d6..7cd73df4aa 100644 --- a/hw/s390x/ccw-device.c +++ b/hw/s390x/ccw-device.c @@ -40,6 +40,13 @@ static Property ccw_device_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static void ccw_device_reset(DeviceState *d) +{ + CcwDevice *ccw_dev = CCW_DEVICE(d); + + css_reset_sch(ccw_dev->sch); +} + static void ccw_device_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -48,6 +55,7 @@ static void ccw_device_class_init(ObjectClass *klass, void *data) k->realize = ccw_device_realize; k->refill_ids = ccw_device_refill_ids; dc->props = ccw_device_properties; + dc->reset = ccw_device_reset; } const VMStateDescription vmstate_ccw_dev = { diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 301bf1772f..56c3fa8c89 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -617,6 +617,14 @@ void css_inject_io_interrupt(SubchDev *sch) void css_conditional_io_interrupt(SubchDev *sch) { /* + * If the subchannel is not enabled, it is not made status pending + * (see PoP p. 16-17, "Status Control"). + */ + if (!(sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA)) { + return; + } + + /* * If the subchannel is not currently status pending, make it pending * with alert status. */ diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 150f6c0582..04245b5258 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -26,6 +26,7 @@ #include "qemu/config-file.h" #include "qemu/cutils.h" #include "qemu/option.h" +#include "exec/exec-all.h" #define KERN_IMAGE_START 0x010000UL #define KERN_PARM_AREA 0x010480UL @@ -488,12 +489,20 @@ IplParameterBlock *s390_ipl_get_iplb(void) return &ipl->iplb; } -void s390_reipl_request(void) +void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type) { S390IPLState *ipl = get_ipl_device(); - ipl->reipl_requested = true; - if (ipl->iplb_valid && + if (reset_type == S390_RESET_EXTERNAL || reset_type == S390_RESET_REIPL) { + /* use CPU 0 for full resets */ + ipl->reset_cpu_index = 0; + } else { + ipl->reset_cpu_index = cs->cpu_index; + } + ipl->reset_type = reset_type; + + if (reset_type == S390_RESET_REIPL && + ipl->iplb_valid && !ipl->netboot && ipl->iplb.pbt == S390_IPL_TYPE_CCW && is_virtio_scsi_device(&ipl->iplb)) { @@ -510,6 +519,31 @@ void s390_reipl_request(void) } } qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + /* as this is triggered by a CPU, make sure to exit the loop */ + if (tcg_enabled()) { + cpu_loop_exit(cs); + } +} + +void s390_ipl_get_reset_request(CPUState **cs, enum s390_reset *reset_type) +{ + S390IPLState *ipl = get_ipl_device(); + + *cs = qemu_get_cpu(ipl->reset_cpu_index); + if (!*cs) { + /* use any CPU */ + *cs = first_cpu; + } + *reset_type = ipl->reset_type; +} + +void s390_ipl_clear_reset_request(void) +{ + S390IPLState *ipl = get_ipl_device(); + + ipl->reset_type = S390_RESET_EXTERNAL; + /* use CPU 0 for full resets */ + ipl->reset_cpu_index = 0; } static void s390_ipl_prepare_qipl(S390CPU *cpu) @@ -556,11 +590,10 @@ static void s390_ipl_reset(DeviceState *dev) { S390IPLState *ipl = S390_IPL(dev); - if (!ipl->reipl_requested) { + if (ipl->reset_type != S390_RESET_REIPL) { ipl->iplb_valid = false; memset(&ipl->iplb, 0, sizeof(IplParameterBlock)); } - ipl->reipl_requested = false; } static void s390_ipl_class_init(ObjectClass *klass, void *data) diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h index 0570d0ad75..4e87b89418 100644 --- a/hw/s390x/ipl.h +++ b/hw/s390x/ipl.h @@ -87,7 +87,17 @@ int s390_ipl_set_loadparm(uint8_t *loadparm); void s390_ipl_update_diag308(IplParameterBlock *iplb); void s390_ipl_prepare_cpu(S390CPU *cpu); IplParameterBlock *s390_ipl_get_iplb(void); -void s390_reipl_request(void); + +enum s390_reset { + /* default is a reset not triggered by a CPU e.g. issued by QMP */ + S390_RESET_EXTERNAL = 0, + S390_RESET_REIPL, + S390_RESET_MODIFIED_CLEAR, + S390_RESET_LOAD_NORMAL, +}; +void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type); +void s390_ipl_get_reset_request(CPUState **cs, enum s390_reset *reset_type); +void s390_ipl_clear_reset_request(void); #define QIPL_ADDRESS 0xcc @@ -129,9 +139,11 @@ struct S390IPLState { bool enforce_bios; IplParameterBlock iplb; bool iplb_valid; - bool reipl_requested; bool netboot; QemuIplParameters qipl; + /* reset related properties don't have to be migrated or reset */ + enum s390_reset reset_type; + int reset_cpu_index; /*< public >*/ char *kernel; diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 5796e24bd8..e548d341a0 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -93,7 +93,7 @@ static const char *const reset_dev_types[] = { "diag288", }; -void subsystem_reset(void) +static void subsystem_reset(void) { DeviceState *dev; int i; @@ -381,17 +381,54 @@ static void s390_cpu_plug(HotplugHandler *hotplug_dev, } } +static inline void s390_do_cpu_ipl(CPUState *cs, run_on_cpu_data arg) +{ + S390CPU *cpu = S390_CPU(cs); + + s390_ipl_prepare_cpu(cpu); + s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); +} + static void s390_machine_reset(void) { - S390CPU *ipl_cpu = S390_CPU(qemu_get_cpu(0)); + enum s390_reset reset_type; + CPUState *cs, *t; + /* get the reset parameters, reset them once done */ + s390_ipl_get_reset_request(&cs, &reset_type); + + /* all CPUs are paused and synchronized at this point */ s390_cmma_reset(); - qemu_devices_reset(); - s390_crypto_reset(); - /* all cpus are stopped - configure and start the ipl cpu only */ - s390_ipl_prepare_cpu(ipl_cpu); - s390_cpu_set_state(S390_CPU_STATE_OPERATING, ipl_cpu); + switch (reset_type) { + case S390_RESET_EXTERNAL: + case S390_RESET_REIPL: + qemu_devices_reset(); + s390_crypto_reset(); + + /* configure and start the ipl CPU only */ + run_on_cpu(cs, s390_do_cpu_ipl, RUN_ON_CPU_NULL); + break; + case S390_RESET_MODIFIED_CLEAR: + CPU_FOREACH(t) { + run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); + } + subsystem_reset(); + s390_crypto_reset(); + run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL); + break; + case S390_RESET_LOAD_NORMAL: + CPU_FOREACH(t) { + run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); + } + subsystem_reset(); + run_on_cpu(cs, s390_do_cpu_initial_reset, RUN_ON_CPU_NULL); + run_on_cpu(cs, s390_do_cpu_load_normal, RUN_ON_CPU_NULL); + break; + default: + g_assert_not_reached(); + } + s390_ipl_clear_reset_request(); } static void s390_machine_device_plug(HotplugHandler *hotplug_dev, diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index e51fbefd23..22df33b509 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1058,10 +1058,12 @@ static void virtio_ccw_reset(DeviceState *d) { VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); - CcwDevice *ccw_dev = CCW_DEVICE(d); + VirtIOCCWDeviceClass *vdc = VIRTIO_CCW_DEVICE_GET_CLASS(dev); virtio_ccw_reset_virtio(dev, vdev); - css_reset_sch(ccw_dev->sch); + if (vdc->parent_reset) { + vdc->parent_reset(d); + } } static void virtio_ccw_vmstate_change(DeviceState *d, bool running) @@ -1345,7 +1347,6 @@ static void virtio_ccw_net_class_init(ObjectClass *klass, void *data) k->realize = virtio_ccw_net_realize; k->unrealize = virtio_ccw_unrealize; - dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_net_properties; set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); } @@ -1373,7 +1374,6 @@ static void virtio_ccw_blk_class_init(ObjectClass *klass, void *data) k->realize = virtio_ccw_blk_realize; k->unrealize = virtio_ccw_unrealize; - dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_blk_properties; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } @@ -1401,7 +1401,6 @@ static void virtio_ccw_serial_class_init(ObjectClass *klass, void *data) k->realize = virtio_ccw_serial_realize; k->unrealize = virtio_ccw_unrealize; - dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_serial_properties; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } @@ -1429,7 +1428,6 @@ static void virtio_ccw_balloon_class_init(ObjectClass *klass, void *data) k->realize = virtio_ccw_balloon_realize; k->unrealize = virtio_ccw_unrealize; - dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_balloon_properties; set_bit(DEVICE_CATEGORY_MISC, dc->categories); } @@ -1457,7 +1455,6 @@ static void virtio_ccw_scsi_class_init(ObjectClass *klass, void *data) k->realize = virtio_ccw_scsi_realize; k->unrealize = virtio_ccw_unrealize; - dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_scsi_properties; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } @@ -1484,7 +1481,6 @@ static void vhost_ccw_scsi_class_init(ObjectClass *klass, void *data) k->realize = vhost_ccw_scsi_realize; k->unrealize = virtio_ccw_unrealize; - dc->reset = virtio_ccw_reset; dc->props = vhost_ccw_scsi_properties; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } @@ -1521,7 +1517,6 @@ static void virtio_ccw_rng_class_init(ObjectClass *klass, void *data) k->realize = virtio_ccw_rng_realize; k->unrealize = virtio_ccw_unrealize; - dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_rng_properties; set_bit(DEVICE_CATEGORY_MISC, dc->categories); } @@ -1559,7 +1554,6 @@ static void virtio_ccw_crypto_class_init(ObjectClass *klass, void *data) k->realize = virtio_ccw_crypto_realize; k->unrealize = virtio_ccw_unrealize; - dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_crypto_properties; set_bit(DEVICE_CATEGORY_MISC, dc->categories); } @@ -1597,7 +1591,6 @@ static void virtio_ccw_gpu_class_init(ObjectClass *klass, void *data) k->realize = virtio_ccw_gpu_realize; k->unrealize = virtio_ccw_unrealize; - dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_gpu_properties; dc->hotpluggable = false; set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); @@ -1626,7 +1619,6 @@ static void virtio_ccw_input_class_init(ObjectClass *klass, void *data) k->realize = virtio_ccw_input_realize; k->unrealize = virtio_ccw_unrealize; - dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_input_properties; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } @@ -1725,11 +1717,13 @@ static void virtio_ccw_device_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); CCWDeviceClass *k = CCW_DEVICE_CLASS(dc); + VirtIOCCWDeviceClass *vdc = VIRTIO_CCW_DEVICE_CLASS(klass); k->unplug = virtio_ccw_busdev_unplug; dc->realize = virtio_ccw_busdev_realize; dc->unrealize = virtio_ccw_busdev_unrealize; dc->bus_type = TYPE_VIRTUAL_CSS_BUS; + device_class_set_parent_reset(dc, virtio_ccw_reset, &vdc->parent_reset); } static const TypeInfo virtio_ccw_device_info = { @@ -1806,7 +1800,6 @@ static void virtio_ccw_9p_class_init(ObjectClass *klass, void *data) k->unrealize = virtio_ccw_unrealize; k->realize = virtio_ccw_9p_realize; - dc->reset = virtio_ccw_reset; dc->props = virtio_ccw_9p_properties; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } @@ -1856,7 +1849,6 @@ static void vhost_vsock_ccw_class_init(ObjectClass *klass, void *data) k->unrealize = virtio_ccw_unrealize; set_bit(DEVICE_CATEGORY_MISC, dc->categories); dc->props = vhost_vsock_ccw_properties; - dc->reset = virtio_ccw_reset; } static void vhost_vsock_ccw_instance_init(Object *obj) diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index 2fc513001e..3453aa1f98 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -77,6 +77,7 @@ typedef struct VirtIOCCWDeviceClass { CCWDeviceClass parent_class; void (*realize)(VirtioCcwDevice *dev, Error **errp); void (*unrealize)(VirtioCcwDevice *dev, Error **errp); + void (*parent_reset)(DeviceState *dev); } VirtIOCCWDeviceClass; /* Performance improves when virtqueue kick processing is decoupled from the diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h index 642adce68b..d5a515de9b 100644 --- a/include/block/blockjob_int.h +++ b/include/block/blockjob_int.h @@ -169,20 +169,6 @@ void block_job_sleep_ns(BlockJob *job, int64_t ns); void block_job_yield(BlockJob *job); /** - * block_job_pause_all: - * - * Asynchronously pause all jobs. - */ -void block_job_pause_all(void); - -/** - * block_job_resume_all: - * - * Resume all block jobs. Must be paired with a preceding block_job_pause_all. - */ -void block_job_resume_all(void); - -/** * block_job_early_fail: * @bs: The block device. * diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h index ac896e31ea..ab88d49d10 100644 --- a/include/hw/s390x/s390-virtio-ccw.h +++ b/include/hw/s390x/s390-virtio-ccw.h @@ -53,6 +53,4 @@ bool cpu_model_allowed(void); */ bool css_migration_enabled(void); -void subsystem_reset(void); - #endif diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h index 55eaeee4b6..1a0795f645 100644 --- a/pc-bios/s390-ccw/cio.h +++ b/pc-bios/s390-ccw/cio.h @@ -125,7 +125,7 @@ struct tpi_info { __u32 reserved3 : 12; __u32 int_type : 3; __u32 reserved4 : 12; -} __attribute__ ((packed)); +} __attribute__ ((packed, aligned(4))); /* channel command word (type 1) */ struct ccw1 { diff --git a/qapi/block-core.json b/qapi/block-core.json index c50517bff3..21c3470234 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -2530,6 +2530,10 @@ # @locking: whether to enable file locking. If set to 'auto', only enable # when Open File Descriptor (OFD) locking API is available # (default: auto, since 2.10) +# @x-check-cache-dropped: whether to check that page cache was dropped on live +# migration. May cause noticeable delays if the image +# file is large, do not use in production. +# (default: off) (since: 2.13) # # Since: 2.9 ## @@ -2537,7 +2541,8 @@ 'data': { 'filename': 'str', '*pr-manager': 'str', '*locking': 'OnOffAuto', - '*aio': 'BlockdevAioOptions' } } + '*aio': 'BlockdevAioOptions', + '*x-check-cache-dropped': 'bool' } } ## # @BlockdevOptionsNull: diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index e73b4efcfb..cb1b652388 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -224,9 +224,8 @@ our $NonptrType; our $Type; our $Declare; -our $UTF8 = qr { - [\x09\x0A\x0D\x20-\x7E] # ASCII - | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte +our $NON_ASCII_UTF8 = qr{ + [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates @@ -235,6 +234,11 @@ our $UTF8 = qr { | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 }x; +our $UTF8 = qr{ + [\x09\x0A\x0D\x20-\x7E] # ASCII + | $NON_ASCII_UTF8 +}x; + # There are still some false positives, but this catches most # common cases. our $typeTypedefs = qr{(?x: @@ -1207,6 +1211,11 @@ sub process { my $signoff = 0; my $is_patch = 0; + my $in_header_lines = $file ? 0 : 1; + my $in_commit_log = 0; #Scanning lines before patch + my $reported_maintainer_file = 0; + my $non_utf8_charset = 0; + our @report = (); our $cnt_lines = 0; our $cnt_error = 0; @@ -1359,7 +1368,6 @@ sub process { if ($line =~ /^diff --git.*?(\S+)$/) { $realfile = $1; $realfile =~ s@^([^/]*)/@@; - } elsif ($line =~ /^\+\+\+\s+(\S+)/) { $realfile = $1; $realfile =~ s@^([^/]*)/@@; @@ -1398,6 +1406,8 @@ sub process { if ($line =~ /^\s*signed-off-by:/i) { # This is a signoff, if ugly, so do not double report. $signoff++; + $in_commit_log = 0; + if (!($line =~ /^\s*Signed-off-by:/)) { ERROR("The correct form is \"Signed-off-by\"\n" . $herecurr); @@ -1408,6 +1418,22 @@ sub process { } } +# Check if MAINTAINERS is being updated. If so, there's probably no need to +# emit the "does MAINTAINERS need updating?" message on file add/move/delete + if ($line =~ /^\s*MAINTAINERS\s*\|/) { + $reported_maintainer_file = 1; + } + +# Check for added, moved or deleted files + if (!$reported_maintainer_file && !$in_commit_log && + ($line =~ /^(?:new|deleted) file mode\s*\d+\s*$/ || + $line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ || + ($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ && + (defined($1) || defined($2))))) { + $reported_maintainer_file = 1; + WARN("added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr); + } + # Check for wrappage within a valid hunk of the file if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) { ERROR("patch seems to be corrupt (line wrapped?)\n" . @@ -1426,6 +1452,28 @@ sub process { ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); } +# Check if it's the start of a commit log +# (not a header line and we haven't seen the patch filename) + if ($in_header_lines && $realfile =~ /^$/ && + !($rawline =~ /^\s+\S/ || + $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) { + $in_header_lines = 0; + $in_commit_log = 1; + } + +# Check if there is UTF-8 in a commit log when a mail header has explicitly +# declined it, i.e defined some charset where it is missing. + if ($in_header_lines && + $rawline =~ /^Content-Type:.+charset="(.+)".*$/ && + $1 !~ /utf-8/i) { + $non_utf8_charset = 1; + } + + if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ && + $rawline =~ /$NON_ASCII_UTF8/) { + WARN("8-bit UTF-8 used in possible commit log\n" . $herecurr); + } + # ignore non-hunk lines and lines being removed next if (!$hunk_line || $line =~ /^-/); diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index 3ee40f08b7..6629a533f3 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -686,6 +686,32 @@ static inline uint64_t s390_build_validity_mcic(void) return mcic; } +static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg) +{ + cpu_reset(cs); +} + +static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg) +{ + S390CPUClass *scc = S390_CPU_GET_CLASS(cs); + + scc->cpu_reset(cs); +} + +static inline void s390_do_cpu_initial_reset(CPUState *cs, run_on_cpu_data arg) +{ + S390CPUClass *scc = S390_CPU_GET_CLASS(cs); + + scc->initial_cpu_reset(cs); +} + +static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg) +{ + S390CPUClass *scc = S390_CPU_GET_CLASS(cs); + + scc->load_normal(cs); +} + /* cpu.c */ int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low); diff --git a/target/s390x/diag.c b/target/s390x/diag.c index a755837ad5..ac2c40f363 100644 --- a/target/s390x/diag.c +++ b/target/s390x/diag.c @@ -22,51 +22,6 @@ #include "hw/s390x/ipl.h" #include "hw/s390x/s390-virtio-ccw.h" -static int modified_clear_reset(S390CPU *cpu) -{ - S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); - CPUState *t; - - pause_all_vcpus(); - cpu_synchronize_all_states(); - CPU_FOREACH(t) { - run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); - } - s390_cmma_reset(); - subsystem_reset(); - s390_crypto_reset(); - scc->load_normal(CPU(cpu)); - cpu_synchronize_all_post_reset(); - resume_all_vcpus(); - return 0; -} - -static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg) -{ - S390CPUClass *scc = S390_CPU_GET_CLASS(cs); - - scc->cpu_reset(cs); -} - -static int load_normal_reset(S390CPU *cpu) -{ - S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); - CPUState *t; - - pause_all_vcpus(); - cpu_synchronize_all_states(); - CPU_FOREACH(t) { - run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); - } - s390_cmma_reset(); - subsystem_reset(); - scc->initial_cpu_reset(CPU(cpu)); - scc->load_normal(CPU(cpu)); - cpu_synchronize_all_post_reset(); - resume_all_vcpus(); - return 0; -} - int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) { uint64_t func = env->regs[r1]; @@ -101,6 +56,7 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) { + CPUState *cs = CPU(s390_env_get_cpu(env)); uint64_t addr = env->regs[r1]; uint64_t subcode = env->regs[r3]; IplParameterBlock *iplb; @@ -117,22 +73,13 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) switch (subcode) { case 0: - modified_clear_reset(s390_env_get_cpu(env)); - if (tcg_enabled()) { - cpu_loop_exit(CPU(s390_env_get_cpu(env))); - } + s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR); break; case 1: - load_normal_reset(s390_env_get_cpu(env)); - if (tcg_enabled()) { - cpu_loop_exit(CPU(s390_env_get_cpu(env))); - } + s390_ipl_reset_request(cs, S390_RESET_LOAD_NORMAL); break; case 3: - s390_reipl_request(); - if (tcg_enabled()) { - cpu_loop_exit(CPU(s390_env_get_cpu(env))); - } + s390_ipl_reset_request(cs, S390_RESET_REIPL); break; case 5: if ((r1 & 1) || (addr & 0x0fffULL)) { diff --git a/target/s390x/internal.h b/target/s390x/internal.h index d911e84958..e392a02d12 100644 --- a/target/s390x/internal.h +++ b/target/s390x/internal.h @@ -273,12 +273,6 @@ static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb, /* Base/displacement are at the same locations. */ #define decode_basedisp_rs decode_basedisp_s -static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg) -{ - cpu_reset(cs); -} - - /* arch_dump.c */ int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, int cpuid, void *opaque); diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 12b90cf5c5..58e4380ae3 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -1767,7 +1767,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) ret = handle_intercept(cpu); break; case KVM_EXIT_S390_RESET: - s390_reipl_request(); + s390_ipl_reset_request(cs, S390_RESET_REIPL); break; case KVM_EXIT_S390_TSCH: ret = handle_tsch(cpu); diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c index e0b23c1fd1..1f834f35ef 100644 --- a/target/s390x/misc_helper.c +++ b/target/s390x/misc_helper.c @@ -206,7 +206,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, uint64_t r0, uint64_t r1) const MachineState *ms = MACHINE(qdev_get_machine()); uint16_t total_cpus = 0, conf_cpus = 0, reserved_cpus = 0; S390CPU *cpu = s390_env_get_cpu(env); - SysIB sysib = { 0 }; + SysIB sysib = { }; int i, cc = 0; if ((r0 & STSI_R0_FC_MASK) > STSI_R0_FC_LEVEL_3) { |