qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, lersek@redhat.com, kwolf@redhat.com,
	mreitz@redhat.com, qemu-block@nongnu.org, pkrempa@redhat.com,
	mst@redhat.com, marcel.apfelbaum@gmail.com,
	marcandre.lureau@redhat.com, philmd@redhat.com
Subject: [Qemu-devel] [PATCH v2 01/12] qdev: Fix latent bug with compat_props and onboard devices
Date: Thu,  7 Mar 2019 18:23:50 +0100	[thread overview]
Message-ID: <20190307172401.29451-2-armbru@redhat.com> (raw)
In-Reply-To: <20190307172401.29451-1-armbru@redhat.com>

Compatibility properties started life as a qdev property thing: we
supported them only for qdev properties, and implemented them with the
machinery backing command line option -global.

Recent commit fa0cb34d221 put them to use (tacitly) with memory
backend objects (subtypes of TYPE_MEMORY_BACKEND).  To make that
possible, we first moved the work of applying them from the -global
machinery into TYPE_DEVICE's .instance_post_init() method
device_post_init(), in commits ea9ce8934c5 and b66bbee39f6, then made
it available to TYPE_MEMORY_BACKEND's .instance_post_init() method
host_memory_backend_post_init() as object_apply_compat_props(), in
commit 1c3994f6d2a.

Note the code smell: we now have function name starting with object_
in hw/core/qdev.c.  It has to be there rather than in qom/, because it
calls qdev_get_machine() to find the current accelerator's and
machine's compat_props.

Turns out calling qdev_get_machine() there is problematic.  If we
qdev_create() from a machine's .instance_init() method, we call
device_post_init() and thus qdev_get_machine() before main() can
create "/machine" in QOM.  qdev_get_machine() tries to get it with
container_get(), which "helpfully" creates it as "container" object,
and returns that.  object_apply_compat_props() tries to paper over the
problem by doing nothing when the value of qdev_get_machine() isn't a
TYPE_MACHINE.  But the damage is done already: when main() later
attempts to create the real "/machine", it fails with "attempt to add
duplicate property 'machine' to object (type 'container')", and
aborts.

Since no machine .instance_init() calls qdev_create() so far, the bug
is latent.  But since I want to do that, I get to fix the bug first.

Observe that object_apply_compat_props() doesn't actually need the
MachineState, only its the compat_props member of its MachineClass and
AccelClass.  This permits a simple fix: register MachineClass and
AccelClass compat_props with the object_apply_compat_props() machinery
right after these classes get selected.

This is actually similar to how things worked before commits
ea9ce8934c5 and b66bbee39f6, except we now register much earlier.  The
old code registered them only after the machine's .instance_init()
ran, which would've broken compatibility properties for any devices
created there.

Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 accel/accel.c          |  1 +
 hw/core/qdev.c         | 48 ++++++++++++++++++++++++++++++++----------
 include/hw/qdev-core.h |  2 ++
 vl.c                   |  1 +
 4 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/accel/accel.c b/accel/accel.c
index 68b6d56323..4a1670e404 100644
--- a/accel/accel.c
+++ b/accel/accel.c
@@ -66,6 +66,7 @@ static int accel_init_machine(AccelClass *acc, MachineState *ms)
         *(acc->allowed) = false;
         object_unref(OBJECT(accel));
     }
+    object_set_accelerator_compat_props(acc->compat_props);
     return ret;
 }
 
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index d59071b8ed..1a86c7990a 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -970,25 +970,51 @@ static void device_initfn(Object *obj)
     QLIST_INIT(&dev->gpios);
 }
 
+/*
+ * Global property defaults
+ * Slot 0: accelerator's global property defaults
+ * Slot 1: machine's global property defaults
+ * Each is a GPtrArray of of GlobalProperty.
+ * Applied in order, later entries override earlier ones.
+ */
+static GPtrArray *object_compat_props[2];
+
+/*
+ * Set machine's global property defaults to @compat_props.
+ * May be called at most once.
+ */
+void object_set_machine_compat_props(GPtrArray *compat_props)
+{
+    assert(!object_compat_props[1]);
+    object_compat_props[1] = compat_props;
+}
+
+/*
+ * Set accelerator's global property defaults to @compat_props.
+ * May be called at most once.
+ */
+void object_set_accelerator_compat_props(GPtrArray *compat_props)
+{
+    assert(!object_compat_props[0]);
+    object_compat_props[0] = compat_props;
+}
+
 void object_apply_compat_props(Object *obj)
 {
-    if (object_dynamic_cast(qdev_get_machine(), TYPE_MACHINE)) {
-        MachineState *m = MACHINE(qdev_get_machine());
-        MachineClass *mc = MACHINE_GET_CLASS(m);
+    int i;
 
-        if (m->accelerator) {
-            AccelClass *ac = ACCEL_GET_CLASS(m->accelerator);
-
-            if (ac->compat_props) {
-                object_apply_global_props(obj, ac->compat_props, &error_abort);
-            }
-        }
-        object_apply_global_props(obj, mc->compat_props, &error_abort);
+    for (i = 0; i < ARRAY_SIZE(object_compat_props); i++) {
+        object_apply_global_props(obj, object_compat_props[i],
+                                  &error_abort);
     }
 }
 
 static void device_post_init(Object *obj)
 {
+    /*
+     * Note: ordered so that the user's global properties take
+     * precedence.
+     */
     object_apply_compat_props(obj);
     qdev_prop_set_globals(DEVICE(obj));
 }
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index e70a4bfa49..c1dc06e9bb 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -418,6 +418,8 @@ const char *qdev_fw_name(DeviceState *dev);
 
 Object *qdev_get_machine(void);
 
+void object_set_machine_compat_props(GPtrArray *compat_props);
+void object_set_accelerator_compat_props(GPtrArray *compat_props);
 void object_apply_compat_props(Object *obj);
 
 /* FIXME: make this a link<> */
diff --git a/vl.c b/vl.c
index fd0d51320d..ea58a16a4a 100644
--- a/vl.c
+++ b/vl.c
@@ -3954,6 +3954,7 @@ int main(int argc, char **argv, char **envp)
     configure_rtc(qemu_find_opts_singleton("rtc"));
 
     machine_class = select_machine();
+    object_set_machine_compat_props(machine_class->compat_props);
 
     set_memory_options(&ram_slots, &maxram_size, machine_class);
 
-- 
2.17.2

  reply	other threads:[~2019-03-07 17:24 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-07 17:23 [Qemu-devel] [PATCH v2 00/12] pc: Support firmware configuration with -blockdev Markus Armbruster
2019-03-07 17:23 ` Markus Armbruster [this message]
2019-03-07 17:23 ` [Qemu-devel] [PATCH v2 02/12] qom: Move compat_props machinery from qdev to QOM Markus Armbruster
2019-03-07 17:23 ` [Qemu-devel] [PATCH v2 03/12] vl: Fix latent bug with -global and onboard devices Markus Armbruster
2019-03-07 17:23 ` [Qemu-devel] [PATCH v2 04/12] sysbus: Fix latent bug with " Markus Armbruster
2019-03-07 17:23 ` [Qemu-devel] [PATCH v2 05/12] vl: Improve legibility of BlockdevOptions queue Markus Armbruster
2019-03-07 17:23 ` [Qemu-devel] [PATCH v2 06/12] vl: Factor configure_blockdev() out of main() Markus Armbruster
2019-03-07 17:46   ` Philippe Mathieu-Daudé
2019-03-07 17:59   ` Eric Blake
2019-03-07 19:08     ` Markus Armbruster
2019-03-08  8:31       ` Laszlo Ersek
2019-03-07 17:23 ` [Qemu-devel] [PATCH v2 07/12] vl: Create block backends before setting machine properties Markus Armbruster
2019-03-07 17:46   ` Philippe Mathieu-Daudé
2019-03-07 17:23 ` [Qemu-devel] [PATCH v2 08/12] pflash_cfi01: Add pflash_cfi01_get_blk() helper Markus Armbruster
2019-03-07 17:23 ` [Qemu-devel] [PATCH v2 09/12] pc_sysfw: Remove unused PcSysFwDevice Markus Armbruster
2019-03-07 17:23 ` [Qemu-devel] [PATCH v2 10/12] pc_sysfw: Pass PCMachineState to pc_system_firmware_init() Markus Armbruster
2019-03-08  8:11   ` Laszlo Ersek
2019-03-07 17:24 ` [Qemu-devel] [PATCH v2 11/12] pc: Support firmware configuration with -blockdev Markus Armbruster
2019-03-07 17:48   ` Philippe Mathieu-Daudé
2019-03-08  8:22   ` Laszlo Ersek
2019-03-07 17:24 ` [Qemu-devel] [PATCH v2 12/12] docs/interop/firmware.json: Prefer -machine to if=pflash Markus Armbruster
2019-03-08  8:44   ` Laszlo Ersek
2019-03-08 12:01     ` Markus Armbruster
2019-03-07 17:49 ` [Qemu-devel] [PATCH v2 00/12] pc: Support firmware configuration with -blockdev no-reply
2019-03-07 18:29 ` no-reply
2019-03-07 18:46 ` no-reply
2019-03-08  8:17 ` no-reply
2019-03-08  8:26 ` no-reply
2019-03-09  0:56 ` no-reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190307172401.29451-2-armbru@redhat.com \
    --to=armbru@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=lersek@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=marcel.apfelbaum@gmail.com \
    --cc=mreitz@redhat.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=philmd@redhat.com \
    --cc=pkrempa@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).