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> --- hw/s390x/cpu-topology.c | 79 +++++++++++++++++++++++++++++++++ include/hw/s390x/cpu-topology.h | 1 + target/s390x/cpu-sysemu.c | 8 ++++ target/s390x/cpu.h | 1 + 4 files changed, 89 insertions(+) diff --git a/hw/s390x/cpu-topology.c b/hw/s390x/cpu-topology.c index 6098d6ea1f..b6bf839e40 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" S390Topology *s390_get_topology(void) { @@ -132,6 +133,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_feat(S390_FEAT_CONFIGURATION_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_feat(S390_FEAT_CONFIGURATION_TOPOLOGY)) { + return 0; + } + + /* We support CPU Topology, set the MTCR */ + 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_feat(S390_FEAT_CONFIGURATION_TOPOLOGY); + return 0; +} + +/** + * cpu_topology_needed: + * @opaque: The pointer to the S390Topology + * + * If we use the CPU Topology on the source it will be needed on the destination. + */ +static bool cpu_topology_needed(void *opaque) +{ + return s390_has_feat(S390_FEAT_CONFIGURATION_TOPOLOGY); +} + + +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 @@ -146,6 +224,7 @@ static void topology_class_init(ObjectClass *oc, void *data) dc->realize = s390_topology_realize; 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/include/hw/s390x/cpu-topology.h b/include/hw/s390x/cpu-topology.h index 4f8ac39ca0..a15567baca 100644 --- a/include/hw/s390x/cpu-topology.h +++ b/include/hw/s390x/cpu-topology.h @@ -29,6 +29,7 @@ typedef struct S390TopoTLE { struct S390Topology { SysBusDevice parent_obj; + bool topology_needed; int total_books; int total_sockets; int drawers; diff --git a/target/s390x/cpu-sysemu.c b/target/s390x/cpu-sysemu.c index 707c0b658c..78cb11c0f8 100644 --- a/target/s390x/cpu-sysemu.c +++ b/target/s390x/cpu-sysemu.c @@ -313,3 +313,11 @@ void s390_cpu_topology_reset(void) kvm_s390_topology_set_mtcr(0); } } + +int s390_cpu_topology_mtcr_set(void) +{ + if (kvm_enabled()) { + return kvm_s390_topology_set_mtcr(1); + } + return -ENOENT; +} diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index cff5cc0415..0eb2d219d3 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -827,6 +827,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 -- 2.31.1