diff mbox series

[PULL,4/9] hw/s390x: Fix crash that occurs when inspecting older versioned machines types

Message ID 20250121105613.1286672-5-thuth@redhat.com (mailing list archive)
State New
Headers show
Series [PULL,1/9] tests/functional: Convert the kvm_xen_guest avocado test | expand

Commit Message

Thomas Huth Jan. 21, 2025, 10:56 a.m. UTC
qemu-system-s390x currently crashes when trying to inspect older
machines types, for example:

 $ echo '{ "execute": "qmp_capabilities" }
         { "execute": "qom-list-properties","arguments":
           { "typename": "s390-ccw-virtio-3.0-machine"}}' \
   | ./qemu-system-s390x -qmp stdio -no-shutdown
 {"QMP": {"version": {"qemu": {"micro": 50, "minor": 2, "major": 9},
  "package": "v9.2.0-1071-g81e97df3e7"}, "capabilities": ["oob"]}}
 {"return": {}}
 **
 Bail out! ERROR:../target/s390x/cpu_models.c:832:s390_set_qemu_cpu_model:
  assertion failed: (QTAILQ_EMPTY_RCU(&cpus_queue))
 Aborted (core dumped)

The problem is that the versioned s390-ccw-virtio machine types
use instance_init() to set global state that should be initialized
before the CPUs get instantiated. But instance_init() is not called
only for the machine that is finally used, it is also called for
temporary instances of objects that are e.g. just created for
introspection. That means that those instance_init() functions can
also be called while a machine (and its CPUs) is already created,
which triggers the assertion in cpu_models.c.

So we must not use instance_init() for setting global state, but
use the machine->init() function instead, which is really only called
once when the machine comes to life.

Fixes: 3b00f702c2 ("s390x/cpumodel: add zpci, aen and ais facilities")
Message-ID: <20250120085059.239345-1-thuth@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 hw/s390x/s390-virtio-ccw.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 38aeba14ee..3af613d4e9 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -782,7 +782,6 @@  static void ccw_machine_class_init(ObjectClass *oc, void *data)
 
     s390mc->hpage_1m_allowed = true;
     s390mc->max_threads = 1;
-    mc->init = ccw_init;
     mc->reset = s390_machine_reset;
     mc->block_default_type = IF_VIRTIO;
     mc->no_cdrom = 1;
@@ -852,6 +851,12 @@  static const TypeInfo ccw_machine_info = {
 };
 
 #define DEFINE_CCW_MACHINE_IMPL(latest, ...)                                  \
+    static void MACHINE_VER_SYM(mach_init, ccw, __VA_ARGS__)(MachineState *mach) \
+    {                                                                         \
+        current_mc = S390_CCW_MACHINE_CLASS(MACHINE_GET_CLASS(mach));         \
+        MACHINE_VER_SYM(instance_options, ccw, __VA_ARGS__)(mach);            \
+        ccw_init(mach);                                                       \
+    }                                                                         \
     static void MACHINE_VER_SYM(class_init, ccw, __VA_ARGS__)(                \
         ObjectClass *oc,                                                      \
         void *data)                                                           \
@@ -859,24 +864,18 @@  static const TypeInfo ccw_machine_info = {
         MachineClass *mc = MACHINE_CLASS(oc);                                 \
         MACHINE_VER_SYM(class_options, ccw, __VA_ARGS__)(mc);                 \
         mc->desc = "Virtual s390x machine (version " MACHINE_VER_STR(__VA_ARGS__) ")"; \
+        mc->init = MACHINE_VER_SYM(mach_init, ccw, __VA_ARGS__);              \
         MACHINE_VER_DEPRECATION(__VA_ARGS__);                                 \
         if (latest) {                                                         \
             mc->alias = "s390-ccw-virtio";                                    \
             mc->is_default = true;                                            \
         }                                                                     \
     }                                                                         \
-    static void MACHINE_VER_SYM(instance_init, ccw, __VA_ARGS__)(Object *obj) \
-    {                                                                         \
-        MachineState *machine = MACHINE(obj);                                 \
-        current_mc = S390_CCW_MACHINE_CLASS(MACHINE_GET_CLASS(machine));      \
-        MACHINE_VER_SYM(instance_options, ccw, __VA_ARGS__)(machine);         \
-    }                                                                         \
     static const TypeInfo MACHINE_VER_SYM(info, ccw, __VA_ARGS__) =           \
     {                                                                         \
         .name = MACHINE_VER_TYPE_NAME("s390-ccw-virtio", __VA_ARGS__),        \
         .parent = TYPE_S390_CCW_MACHINE,                                      \
         .class_init = MACHINE_VER_SYM(class_init, ccw, __VA_ARGS__),          \
-        .instance_init = MACHINE_VER_SYM(instance_init, ccw, __VA_ARGS__),    \
     };                                                                        \
     static void MACHINE_VER_SYM(register, ccw, __VA_ARGS__)(void)             \
     {                                                                         \