The migration can only take place if both source and destination of the migration both use or both do not use the CPU topology facility. We indicate a change in topology during migration postload for the case the topology changed between source and destination. Signed-off-by: Pierre Morel <pmorel@xxxxxxxxxxxxx> --- target/s390x/cpu.h | 1 + hw/s390x/cpu-topology.c | 79 +++++++++++++++++++++++++++++++++++++++ target/s390x/cpu-sysemu.c | 8 ++++ 3 files changed, 88 insertions(+) diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index 70de251b07..53127c249c 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -857,6 +857,7 @@ void s390_do_cpu_set_diag318(CPUState *cs, run_on_cpu_data arg); int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id, int vq, bool assign); void s390_cpu_topology_reset(void); +int s390_cpu_topology_mtcr_set(void); #ifndef CONFIG_USER_ONLY unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu); #else diff --git a/hw/s390x/cpu-topology.c b/hw/s390x/cpu-topology.c index 21d2785b37..df4470d2b4 100644 --- a/hw/s390x/cpu-topology.c +++ b/hw/s390x/cpu-topology.c @@ -19,6 +19,7 @@ #include "target/s390x/cpu.h" #include "hw/s390x/s390-virtio-ccw.h" #include "hw/s390x/cpu-topology.h" +#include "migration/vmstate.h" /* * s390_topology_new_cpu: @@ -105,6 +106,83 @@ static void s390_topology_reset(DeviceState *dev) s390_cpu_topology_reset(); } +/** + * cpu_topology_postload + * @opaque: a pointer to the S390Topology + * @version_id: version identifier + * + * We check that the topology is used or is not used + * on both side identically. + * + * If the topology is in use we set the Modified Topology Change Report + * on the destination host. + */ +static int cpu_topology_postload(void *opaque, int version_id) +{ + S390Topology *topo = opaque; + int ret; + + if (topo->topology_needed != s390_has_topology()) { + if (topo->topology_needed) { + error_report("Topology facility is needed in destination"); + } else { + error_report("Topology facility can not be used in destination"); + } + return -EINVAL; + } + + /* We do not support CPU Topology, all is good */ + if (!s390_has_topology()) { + return 0; + } + + /* We support CPU Topology, set the MTCR unconditionally */ + ret = s390_cpu_topology_mtcr_set(); + if (ret) { + error_report("Failed to set MTCR: %s", strerror(-ret)); + } + return ret; +} + +/** + * cpu_topology_presave: + * @opaque: The pointer to the S390Topology + * + * Save the usage of the CPU Topology in the VM State. + */ +static int cpu_topology_presave(void *opaque) +{ + S390Topology *topo = opaque; + + topo->topology_needed = s390_has_topology(); + return 0; +} + +/** + * cpu_topology_needed: + * @opaque: The pointer to the S390Topology + * + * We always need to know if source and destination use the topology. + */ +static bool cpu_topology_needed(void *opaque) +{ + return true; +} + + +const VMStateDescription vmstate_cpu_topology = { + .name = "cpu_topology", + .version_id = 1, + .post_load = cpu_topology_postload, + .pre_save = cpu_topology_presave, + .minimum_version_id = 1, + .needed = cpu_topology_needed, + .fields = (VMStateField[]) { + VMSTATE_BOOL(topology_needed, S390Topology), + VMSTATE_END_OF_LIST() + } +}; + /** * topology_class_init: * @oc: Object class @@ -120,6 +198,7 @@ static void topology_class_init(ObjectClass *oc, void *data) device_class_set_props(dc, s390_topology_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); dc->reset = s390_topology_reset; + dc->vmsd = &vmstate_cpu_topology; } static const TypeInfo cpu_topology_info = { diff --git a/target/s390x/cpu-sysemu.c b/target/s390x/cpu-sysemu.c index e27864c5f5..a8e3e6219d 100644 --- a/target/s390x/cpu-sysemu.c +++ b/target/s390x/cpu-sysemu.c @@ -319,3 +319,11 @@ void s390_cpu_topology_reset(void) } } } + +int s390_cpu_topology_mtcr_set(void) +{ + if (kvm_enabled()) { + return kvm_s390_topology_set_mtcr(1); + } + return -ENOENT; +} -- 2.31.1