[Qemu-devel] [RFC] hw/core/bus.c: Only the main system bus can have no parent

Peter Maydell posted 1 patch 6 days ago
Test docker-clang@ubuntu passed
Test checkpatch passed
Test asan passed
Test docker-mingw@fedora passed
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20190514171545.24961-1-peter.maydell@linaro.org
hw/core/bus.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)

[Qemu-devel] [RFC] hw/core/bus.c: Only the main system bus can have no parent

Posted by Peter Maydell 6 days ago
In commit 80376c3fc2c38fdd453 in 2010 we added a workaround for
some qbus buses not being connected to qdev devices -- if the
bus has no parent object then we register a reset function which
resets the bus on system reset.

Nearly a decade later, we have now no buses in the tree which
are created with non-NULL parents, so we can remove the
workaround and instead just assert that if the bus has a NULL
parent then it is the main system bus.

(The absence of other parentless buses was confirmed by
code inspection of all the callsites of qbus_create() and
qbus_create_inplace() and cross-checked by 'make check'.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
While I was reviewing Damian's reset patchset I noticed this
code which meant that we theoretically had multiple 'roots' to
the set of things being reset, so I wondered what was actually
using it. It turns out nothing was :-)

Commit 80376c3fc2c38fdd453 also added a TODO in vl.c suggesting
that there is the wrong place to register the reset function
which effectively resets the whole system starting at the
root which is the main system bus:
   qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
I don't understand why vl.c is a bad place to put that, and I'd
rather not move it to qdev.c (where in qdev.c?) because that
would reshuffle reset ordering which seems liable to cause
regressions. So maybe we should just delete that TODO comment?

---
 hw/core/bus.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/hw/core/bus.c b/hw/core/bus.c
index e09843f6abe..e50287c2b35 100644
--- a/hw/core/bus.c
+++ b/hw/core/bus.c
@@ -96,10 +96,9 @@ static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
         bus->parent->num_child_bus++;
         object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
         object_unref(OBJECT(bus));
-    } else if (bus != sysbus_get_default()) {
-        /* TODO: once all bus devices are qdevified,
-           only reset handler for main_system_bus should be registered here. */
-        qemu_register_reset(qbus_reset_all_fn, bus);
+    } else {
+        /* The only bus without a parent is the main system bus */
+        assert(bus == sysbus_get_default());
     }
 }
 
-- 
2.20.1


Re: [Qemu-devel] [RFC] hw/core/bus.c: Only the main system bus can have no parent

Posted by Markus Armbruster 5 days ago
Peter Maydell <peter.maydell@linaro.org> writes:

> In commit 80376c3fc2c38fdd453 in 2010 we added a workaround for
> some qbus buses not being connected to qdev devices -- if the
> bus has no parent object then we register a reset function which
> resets the bus on system reset.
>
> Nearly a decade later, we have now no buses in the tree which
> are created with non-NULL parents, so we can remove the
> workaround and instead just assert that if the bus has a NULL
> parent then it is the main system bus.
>
> (The absence of other parentless buses was confirmed by
> code inspection of all the callsites of qbus_create() and
> qbus_create_inplace() and cross-checked by 'make check'.)

Could we assert(parent || bus == main_system_bus) in qbus_realize()?

Aside: I hate sysbus_get_default().  It creates main_system_bus on first
call, wherever that call may be hiding.  I feel we should create it
explicitly.  I'd then make main_system_bus public, and delete
sysbus_get_default().

> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> While I was reviewing Damian's reset patchset I noticed this
> code which meant that we theoretically had multiple 'roots' to
> the set of things being reset, so I wondered what was actually
> using it. It turns out nothing was :-)
>
> Commit 80376c3fc2c38fdd453 also added a TODO in vl.c suggesting
> that there is the wrong place to register the reset function
> which effectively resets the whole system starting at the
> root which is the main system bus:
>    qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
> I don't understand why vl.c is a bad place to put that, and I'd
> rather not move it to qdev.c (where in qdev.c?) because that
> would reshuffle reset ordering which seems liable to cause
> regressions. So maybe we should just delete that TODO comment?

Hmm.

The one in vl.c arranges to run qbus_reset_all(main_system_bus), which
walks the tree rooted at main_system_bus, resetting its buses and
devices in post-order.

A registry of callbacks to run on certain events is a fine technique.
Relying on registration order, however, is in bad taste.  We should
model dependencies between reset functions explicitly.

That said, we can't ignore dependencies just because we've coded them
badly.

I count more than 100 qemu_register_reset(), and most of them look like
they reset hardware.  Why do devices use qemu_register_reset() instead
of DeviceClass method reset?

Registered handlers run in (implicitly defined) registration order,
reset methods in (explicit) qdev tree post order.  Much better as long
as that's the order we want.

Say we managed to clean up this mess somehow, so reset handler
registration order doesn't matter anymore.  Then moving the
qemu_register_reset() for main_system_bus from main() to wherever we
create main_system_bus would make sense, wouldn't it?

If it does make sense, we should keep the TODO in main(), because it
asks for exactly that.  Perhaps delete "by qdev.c".

> ---
>  hw/core/bus.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/hw/core/bus.c b/hw/core/bus.c
> index e09843f6abe..e50287c2b35 100644
> --- a/hw/core/bus.c
> +++ b/hw/core/bus.c
> @@ -96,10 +96,9 @@ static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
>          bus->parent->num_child_bus++;
>          object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
>          object_unref(OBJECT(bus));
> -    } else if (bus != sysbus_get_default()) {
> -        /* TODO: once all bus devices are qdevified,
> -           only reset handler for main_system_bus should be registered here. */
> -        qemu_register_reset(qbus_reset_all_fn, bus);
> +    } else {
> +        /* The only bus without a parent is the main system bus */
> +        assert(bus == sysbus_get_default());
>      }
>  }

You delete a qemu_register_reset() because it's unreachable.  The commit
that added it also added a qemu_unregister_reset().  It's now in
bus_unparent().  Why is it still needed?

Re: [Qemu-devel] [RFC] hw/core/bus.c: Only the main system bus can have no parent

Posted by Peter Maydell 5 days ago
On Thu, 16 May 2019 at 06:37, Markus Armbruster <armbru@redhat.com> wrote:
>
> Peter Maydell <peter.maydell@linaro.org> writes:
>
> > In commit 80376c3fc2c38fdd453 in 2010 we added a workaround for
> > some qbus buses not being connected to qdev devices -- if the
> > bus has no parent object then we register a reset function which
> > resets the bus on system reset.
> >
> > Nearly a decade later, we have now no buses in the tree which
> > are created with non-NULL parents, so we can remove the
> > workaround and instead just assert that if the bus has a NULL
> > parent then it is the main system bus.
> >
> > (The absence of other parentless buses was confirmed by
> > code inspection of all the callsites of qbus_create() and
> > qbus_create_inplace() and cross-checked by 'make check'.)
>
> Could we assert(parent || bus == main_system_bus) in qbus_realize()?

Er, that's what this patch is doing.

> Aside: I hate sysbus_get_default().  It creates main_system_bus on first
> call, wherever that call may be hiding.  I feel we should create it
> explicitly.  I'd then make main_system_bus public, and delete
> sysbus_get_default().

Yes, I think that would be a reasonable thing to do.
The implicit creation is weird since we effectively
rely on a main system bus existing anyway (it is the root
of the reset tree).

> > Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> > ---
> > While I was reviewing Damian's reset patchset I noticed this
> > code which meant that we theoretically had multiple 'roots' to
> > the set of things being reset, so I wondered what was actually
> > using it. It turns out nothing was :-)
> >
> > Commit 80376c3fc2c38fdd453 also added a TODO in vl.c suggesting
> > that there is the wrong place to register the reset function
> > which effectively resets the whole system starting at the
> > root which is the main system bus:
> >    qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
> > I don't understand why vl.c is a bad place to put that, and I'd
> > rather not move it to qdev.c (where in qdev.c?) because that
> > would reshuffle reset ordering which seems liable to cause
> > regressions. So maybe we should just delete that TODO comment?
>
> Hmm.
>
> The one in vl.c arranges to run qbus_reset_all(main_system_bus), which
> walks the tree rooted at main_system_bus, resetting its buses and
> devices in post-order.
>
> A registry of callbacks to run on certain events is a fine technique.
> Relying on registration order, however, is in bad taste.  We should
> model dependencies between reset functions explicitly.

That might be nice, but in practice we have no such model at
all, and I don't think I've seen anybody propose one. I hope we
don't have too many accidental ordering dependencies, but I'm
not confident that we have none at all, and would prefer not to
prod that sleeping dragon...

The multi-phase-reset patches Damien has on list at the moment
would allow some of the reset ordering issues to be sidestepped
because "phase 1" for all devices happens before "phase 2" so
you have "before" and "after" places to put the logic in different
devices.

> That said, we can't ignore dependencies just because we've coded them
> badly.
>
> I count more than 100 qemu_register_reset(), and most of them look like
> they reset hardware.  Why do devices use qemu_register_reset() instead
> of DeviceClass method reset?

Most of the ones for hardware are "this device hasn't been
converted to be a QOM Device" (eg hw/arm/omap1.c, hw/input/pckbd.c,
lots of the stuff in hw/ppc).

The other reason for having to have a qemu_register_reset() handler
to reset something that's a Device is if that Device is not on
a qbus. The most common example of this is CPUs -- since those
don't have a bus to live on they don't get reset by the "reset
everything that's on a QOM bus reachable from the main system
bus" logic. I'm not sure what the nicest way to address this is:
transitioning away from "reset of devices is based on the qdev tree"
to something else seems between difficult and impossible, even
though logically speaking the QOM tree is in many cases closer
to the actual hardware hierarchy of reset.

> Registered handlers run in (implicitly defined) registration order,
> reset methods in (explicit) qdev tree post order.  Much better as long
> as that's the order we want.
>
> Say we managed to clean up this mess somehow, so reset handler
> registration order doesn't matter anymore.  Then moving the
> qemu_register_reset() for main_system_bus from main() to wherever we
> create main_system_bus would make sense, wouldn't it?

I guess so... (There's an argument that the main system bus
should be a child bus of the Machine object, logically speaking,
but Machines aren't subtypes of Device so that doesn't work.)

> If it does make sense, we should keep the TODO in main(), because it
> asks for exactly that.  Perhaps delete "by qdev.c".
>
> > ---
> >  hw/core/bus.c | 7 +++----
> >  1 file changed, 3 insertions(+), 4 deletions(-)
> >
> > diff --git a/hw/core/bus.c b/hw/core/bus.c
> > index e09843f6abe..e50287c2b35 100644
> > --- a/hw/core/bus.c
> > +++ b/hw/core/bus.c
> > @@ -96,10 +96,9 @@ static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
> >          bus->parent->num_child_bus++;
> >          object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
> >          object_unref(OBJECT(bus));
> > -    } else if (bus != sysbus_get_default()) {
> > -        /* TODO: once all bus devices are qdevified,
> > -           only reset handler for main_system_bus should be registered here. */
> > -        qemu_register_reset(qbus_reset_all_fn, bus);
> > +    } else {
> > +        /* The only bus without a parent is the main system bus */
> > +        assert(bus == sysbus_get_default());
> >      }
> >  }
>
> You delete a qemu_register_reset() because it's unreachable.  The commit
> that added it also added a qemu_unregister_reset().  It's now in
> bus_unparent().  Why is it still needed?

You're right, the bus_unparent() logic should also be cleaned up.

thanks
-- PMM

Re: [Qemu-devel] [RFC] hw/core/bus.c: Only the main system bus can have no parent

Posted by Damien Hedde 1 day ago

On 5/16/19 11:19 AM, Peter Maydell wrote:
> On Thu, 16 May 2019 at 06:37, Markus Armbruster <armbru@redhat.com> wrote:
>>
>> Peter Maydell <peter.maydell@linaro.org> writes:
>>
>>> In commit 80376c3fc2c38fdd453 in 2010 we added a workaround for
>>> some qbus buses not being connected to qdev devices -- if the
>>> bus has no parent object then we register a reset function which
>>> resets the bus on system reset.
>>>
>>> Nearly a decade later, we have now no buses in the tree which
>>> are created with non-NULL parents, so we can remove the
>>> workaround and instead just assert that if the bus has a NULL
>>> parent then it is the main system bus.
>>>
>>> (The absence of other parentless buses was confirmed by
>>> code inspection of all the callsites of qbus_create() and
>>> qbus_create_inplace() and cross-checked by 'make check'.)
>>
>> Could we assert(parent || bus == main_system_bus) in qbus_realize()?
> 
> Er, that's what this patch is doing.
> 
>> Aside: I hate sysbus_get_default().  It creates main_system_bus on first
>> call, wherever that call may be hiding.  I feel we should create it
>> explicitly.  I'd then make main_system_bus public, and delete
>> sysbus_get_default().
> 
> Yes, I think that would be a reasonable thing to do.
> The implicit creation is weird since we effectively
> rely on a main system bus existing anyway (it is the root
> of the reset tree).
> 
>>> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
>>> ---
>>> While I was reviewing Damian's reset patchset I noticed this
>>> code which meant that we theoretically had multiple 'roots' to
>>> the set of things being reset, so I wondered what was actually
>>> using it. It turns out nothing was :-)
>>>
>>> Commit 80376c3fc2c38fdd453 also added a TODO in vl.c suggesting
>>> that there is the wrong place to register the reset function
>>> which effectively resets the whole system starting at the
>>> root which is the main system bus:
>>>    qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
>>> I don't understand why vl.c is a bad place to put that, and I'd
>>> rather not move it to qdev.c (where in qdev.c?) because that
>>> would reshuffle reset ordering which seems liable to cause
>>> regressions. So maybe we should just delete that TODO comment?
>>
>> Hmm.
>>
>> The one in vl.c arranges to run qbus_reset_all(main_system_bus), which
>> walks the tree rooted at main_system_bus, resetting its buses and
>> devices in post-order.
>>
>> A registry of callbacks to run on certain events is a fine technique.
>> Relying on registration order, however, is in bad taste.  We should
>> model dependencies between reset functions explicitly.
> 
> That might be nice, but in practice we have no such model at
> all, and I don't think I've seen anybody propose one. I hope we
> don't have too many accidental ordering dependencies, but I'm
> not confident that we have none at all, and would prefer not to
> prod that sleeping dragon...
> 
> The multi-phase-reset patches Damien has on list at the moment
> would allow some of the reset ordering issues to be sidestepped
> because "phase 1" for all devices happens before "phase 2" so
> you have "before" and "after" places to put the logic in different
> devices.
> 
>> That said, we can't ignore dependencies just because we've coded them
>> badly.
>>
>> I count more than 100 qemu_register_reset(), and most of them look like
>> they reset hardware.  Why do devices use qemu_register_reset() instead
>> of DeviceClass method reset?
> 
> Most of the ones for hardware are "this device hasn't been
> converted to be a QOM Device" (eg hw/arm/omap1.c, hw/input/pckbd.c,
> lots of the stuff in hw/ppc).
> 
> The other reason for having to have a qemu_register_reset() handler
> to reset something that's a Device is if that Device is not on
> a qbus. The most common example of this is CPUs -- since those
> don't have a bus to live on they don't get reset by the "reset
> everything that's on a QOM bus reachable from the main system
> bus" logic. I'm not sure what the nicest way to address this is:
> transitioning away from "reset of devices is based on the qdev tree"
> to something else seems between difficult and impossible, even
> though logically speaking the QOM tree is in many cases closer
> to the actual hardware hierarchy of reset.

One "solution" to reduce the qemu_register_reset usage would be to do
handle in the Device base class (at creation or realize) if it has no
parent bus like it is done for buses. But this would probably have an
impact on reset ordering.

> 
>> Registered handlers run in (implicitly defined) registration order,
>> reset methods in (explicit) qdev tree post order.  Much better as long
>> as that's the order we want.
>>
>> Say we managed to clean up this mess somehow, so reset handler
>> registration order doesn't matter anymore.  Then moving the
>> qemu_register_reset() for main_system_bus from main() to wherever we
>> create main_system_bus would make sense, wouldn't it?
> 
> I guess so... (There's an argument that the main system bus
> should be a child bus of the Machine object, logically speaking,
> but Machines aren't subtypes of Device so that doesn't work.)
> 
>> If it does make sense, we should keep the TODO in main(), because it
>> asks for exactly that.  Perhaps delete "by qdev.c".
>>
>>> ---
>>>  hw/core/bus.c | 7 +++----
>>>  1 file changed, 3 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/hw/core/bus.c b/hw/core/bus.c
>>> index e09843f6abe..e50287c2b35 100644
>>> --- a/hw/core/bus.c
>>> +++ b/hw/core/bus.c
>>> @@ -96,10 +96,9 @@ static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
>>>          bus->parent->num_child_bus++;
>>>          object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
>>>          object_unref(OBJECT(bus));
>>> -    } else if (bus != sysbus_get_default()) {
>>> -        /* TODO: once all bus devices are qdevified,
>>> -           only reset handler for main_system_bus should be registered here. */
>>> -        qemu_register_reset(qbus_reset_all_fn, bus);
>>> +    } else {
>>> +        /* The only bus without a parent is the main system bus */
>>> +        assert(bus == sysbus_get_default());
>>>      }
>>>  }
>>
>> You delete a qemu_register_reset() because it's unreachable.  The commit
>> that added it also added a qemu_unregister_reset().  It's now in
>> bus_unparent().  Why is it still needed?
> 
> You're right, the bus_unparent() logic should also be cleaned up.
> 
> thanks
> -- PMM
> 

Re: [Qemu-devel] [RFC] hw/core/bus.c: Only the main system bus can have no parent

Posted by Markus Armbruster 2 hours ago
Damien Hedde <damien.hedde@greensocs.com> writes:

> On 5/16/19 11:19 AM, Peter Maydell wrote:
>> On Thu, 16 May 2019 at 06:37, Markus Armbruster <armbru@redhat.com> wrote:
>>>
>>> Peter Maydell <peter.maydell@linaro.org> writes:
>>>
>>>> In commit 80376c3fc2c38fdd453 in 2010 we added a workaround for
>>>> some qbus buses not being connected to qdev devices -- if the
>>>> bus has no parent object then we register a reset function which
>>>> resets the bus on system reset.
>>>>
>>>> Nearly a decade later, we have now no buses in the tree which
>>>> are created with non-NULL parents, so we can remove the
>>>> workaround and instead just assert that if the bus has a NULL
>>>> parent then it is the main system bus.
>>>>
>>>> (The absence of other parentless buses was confirmed by
>>>> code inspection of all the callsites of qbus_create() and
>>>> qbus_create_inplace() and cross-checked by 'make check'.)
>>>
>>> Could we assert(parent || bus == main_system_bus) in qbus_realize()?
>> 
>> Er, that's what this patch is doing.

You're right; I got confused.

>>> Aside: I hate sysbus_get_default().  It creates main_system_bus on first
>>> call, wherever that call may be hiding.  I feel we should create it
>>> explicitly.  I'd then make main_system_bus public, and delete
>>> sysbus_get_default().
>> 
>> Yes, I think that would be a reasonable thing to do.
>> The implicit creation is weird since we effectively
>> rely on a main system bus existing anyway (it is the root
>> of the reset tree).
>> 
>>>> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
>>>> ---
>>>> While I was reviewing Damian's reset patchset I noticed this
>>>> code which meant that we theoretically had multiple 'roots' to
>>>> the set of things being reset, so I wondered what was actually
>>>> using it. It turns out nothing was :-)
>>>>
>>>> Commit 80376c3fc2c38fdd453 also added a TODO in vl.c suggesting
>>>> that there is the wrong place to register the reset function
>>>> which effectively resets the whole system starting at the
>>>> root which is the main system bus:
>>>>    qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
>>>> I don't understand why vl.c is a bad place to put that, and I'd
>>>> rather not move it to qdev.c (where in qdev.c?) because that
>>>> would reshuffle reset ordering which seems liable to cause
>>>> regressions. So maybe we should just delete that TODO comment?
>>>
>>> Hmm.
>>>
>>> The one in vl.c arranges to run qbus_reset_all(main_system_bus), which
>>> walks the tree rooted at main_system_bus, resetting its buses and
>>> devices in post-order.
>>>
>>> A registry of callbacks to run on certain events is a fine technique.
>>> Relying on registration order, however, is in bad taste.  We should
>>> model dependencies between reset functions explicitly.
>> 
>> That might be nice, but in practice we have no such model at
>> all, and I don't think I've seen anybody propose one.

Well, we do have qbus_reset_all() & friends reset buses and devices in
post order.  That's a model, isn't it?  I guess it can't model *all*
dependencies.  Still, shouldn't we use it wherever it actually suffices?

>>                                                       I hope we
>> don't have too many accidental ordering dependencies, but I'm
>> not confident that we have none at all, and would prefer not to
>> prod that sleeping dragon...
>> 
>> The multi-phase-reset patches Damien has on list at the moment
>> would allow some of the reset ordering issues to be sidestepped
>> because "phase 1" for all devices happens before "phase 2" so
>> you have "before" and "after" places to put the logic in different
>> devices.
>> 
>>> That said, we can't ignore dependencies just because we've coded them
>>> badly.
>>>
>>> I count more than 100 qemu_register_reset(), and most of them look like
>>> they reset hardware.  Why do devices use qemu_register_reset() instead
>>> of DeviceClass method reset?
>> 
>> Most of the ones for hardware are "this device hasn't been
>> converted to be a QOM Device" (eg hw/arm/omap1.c, hw/input/pckbd.c,
>> lots of the stuff in hw/ppc).

hw/input/pckbd.c is instructive.  The qemu_register_reset() in
i8042_mm_init() is inded for a non-qdevified device.  The one in
i8042_realizefn() has no such excuse.

Does not contradict what you wrote, of course.  Still, shouldn't we at
least get rid of the latter kind?

>> The other reason for having to have a qemu_register_reset() handler
>> to reset something that's a Device is if that Device is not on
>> a qbus. The most common example of this is CPUs -- since those
>> don't have a bus to live on they don't get reset by the "reset
>> everything that's on a QOM bus reachable from the main system
>> bus" logic. I'm not sure what the nicest way to address this is:
>> transitioning away from "reset of devices is based on the qdev tree"
>> to something else seems between difficult and impossible, even
>> though logically speaking the QOM tree is in many cases closer
>> to the actual hardware hierarchy of reset.
>
> One "solution" to reduce the qemu_register_reset usage would be to do
> handle in the Device base class (at creation or realize) if it has no
> parent bus like it is done for buses. But this would probably have an
> impact on reset ordering.

I'm afraid *any* improvement will have an impact on reset ordering.
Most reorderings will be just fine.  How terrible could the
less-than-fine ones be?

>>> Registered handlers run in (implicitly defined) registration order,
>>> reset methods in (explicit) qdev tree post order.  Much better as long
>>> as that's the order we want.
>>>
>>> Say we managed to clean up this mess somehow, so reset handler
>>> registration order doesn't matter anymore.  Then moving the
>>> qemu_register_reset() for main_system_bus from main() to wherever we
>>> create main_system_bus would make sense, wouldn't it?
>> 
>> I guess so... (There's an argument that the main system bus
>> should be a child bus of the Machine object, logically speaking,
>> but Machines aren't subtypes of Device so that doesn't work.)

We could replace the special case "bus's parent is null" by the special
case "bus's parent is a machine instead of a device", but I'm not sure
what exactly it would buy us.

>>> If it does make sense, we should keep the TODO in main(), because it
>>> asks for exactly that.  Perhaps delete "by qdev.c".
[...]

Re: [Qemu-devel] [RFC] hw/core/bus.c: Only the main system bus can have no parent

Posted by Peter Maydell 2 hours ago
On Tue, 21 May 2019 at 15:34, Markus Armbruster <armbru@redhat.com> wrote:
>
> Damien Hedde <damien.hedde@greensocs.com> writes:
>
> > On 5/16/19 11:19 AM, Peter Maydell wrote:
> >> On Thu, 16 May 2019 at 06:37, Markus Armbruster <armbru@redhat.com> wrote:
> >>>
> >>> A registry of callbacks to run on certain events is a fine technique.
> >>> Relying on registration order, however, is in bad taste.  We should
> >>> model dependencies between reset functions explicitly.
> >>
> >> That might be nice, but in practice we have no such model at
> >> all, and I don't think I've seen anybody propose one.
>
> Well, we do have qbus_reset_all() & friends reset buses and devices in
> post order.  That's a model, isn't it?  I guess it can't model *all*
> dependencies.  Still, shouldn't we use it wherever it actually suffices?

It's a well-defined order, but it doesn't actually help in a
lot of cases, because often the thing you care about ordering
on is not a device or is not in the same tree as the thing
it depends on. (For instance, there's an annoying ordering
issue between the rom-loader's "reset" function which copies rom
blob contents into RAM, and the Arm M-profile CPU reset method,
which needs to read the starting PC and SP out of RAM. [*])
It's also still an implicit ordering, in the sense that if
there's a dependency between device A (in subtree A') and device
B (in subtree B') then this will all work fine up until somebody
at the top level innocently reorders A' and B' in the list of
children of their mutual parent for some reason and then finds
they've broken an implicit dependency.

[*] aside: this one would actually be fixed by the multi-phase reset
proposal, since the definition of the reset phases is such that
the rom-loader should write to memory in phase 2 ('hold') and
the CPU should read from it in phase 3 ('exit').

> hw/input/pckbd.c is instructive.  The qemu_register_reset() in
> i8042_mm_init() is inded for a non-qdevified device.  The one in
> i8042_realizefn() has no such excuse.
>
> Does not contradict what you wrote, of course.  Still, shouldn't we at
> least get rid of the latter kind?

Yes, absolutely. Also we should qdevify the non-qdev devices.
This part is something where we have a clear path forwards
for making cleanups (no tricky design decisions/debate required),
it just requires somebody to write the actual code.

> >> The other reason for having to have a qemu_register_reset() handler
> >> to reset something that's a Device is if that Device is not on
> >> a qbus. The most common example of this is CPUs -- since those
> >> don't have a bus to live on they don't get reset by the "reset
> >> everything that's on a QOM bus reachable from the main system
> >> bus" logic. I'm not sure what the nicest way to address this is:
> >> transitioning away from "reset of devices is based on the qdev tree"
> >> to something else seems between difficult and impossible, even
> >> though logically speaking the QOM tree is in many cases closer
> >> to the actual hardware hierarchy of reset.
> >
> > One "solution" to reduce the qemu_register_reset usage would be to do
> > handle in the Device base class (at creation or realize) if it has no
> > parent bus like it is done for buses. But this would probably have an
> > impact on reset ordering.
>
> I'm afraid *any* improvement will have an impact on reset ordering.
> Most reorderings will be just fine.  How terrible could the
> less-than-fine ones be?

If you get "CPU reset" and "built in bootloader sets the PC to the
initial address specified by the -kernel file" the wrong way around
then we break booting :-)

> >>> Registered handlers run in (implicitly defined) registration order,
> >>> reset methods in (explicit) qdev tree post order.  Much better as long
> >>> as that's the order we want.
> >>>
> >>> Say we managed to clean up this mess somehow, so reset handler
> >>> registration order doesn't matter anymore.  Then moving the
> >>> qemu_register_reset() for main_system_bus from main() to wherever we
> >>> create main_system_bus would make sense, wouldn't it?
> >>
> >> I guess so... (There's an argument that the main system bus
> >> should be a child bus of the Machine object, logically speaking,
> >> but Machines aren't subtypes of Device so that doesn't work.)
>
> We could replace the special case "bus's parent is null" by the special
> case "bus's parent is a machine instead of a device", but I'm not sure
> what exactly it would buy us.

It's mostly just logically neater -- you could imagine a future
QEMU version that supported one simulation which had models
of more than one machine simultaneously, in which case there
ought to be two system buses, one per machine. And it's
logical that vl.c has to create the machine that the user
asked for, but it's a bit odder that it also has to create the
system bus specially extra, even though it's really just part
of the machine. But as I say, because Machine isn't a subtype of
Device you can't make buses be children of Machine anyway.
Fixing that is more effort than would be warranted for "it looks
slightly nicer this way around".

thanks
-- PMM