Patchwork sysbus: add no_user for devices using mmio or IRQ or GPIO

login
register
mail settings
Submitter Paolo Bonzini
Date March 4, 2013, 5:32 p.m.
Message ID <1362418348-27398-1-git-send-email-pbonzini@redhat.com>
Download mbox | patch
Permalink /patch/224776/
State New
Headers show

Comments

Paolo Bonzini - March 4, 2013, 5:32 p.m.
These features require creating the device specially from board
code.  Therefore, devices that use it cannot be created with
-device.  (And some of them are even visible in binaries for
qemu-system-x86_64, for example the sysbus EHCI device).

Mass-mark these devices as no_user.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/a9scu.c                 | 1 +
 hw/apb_pci.c               | 1 +
 hw/arm_sysctl.c            | 1 +
 hw/arm_timer.c             | 2 ++
 hw/armv7m.c                | 1 +
 hw/bitbang_i2c.c           | 1 +
 hw/cadence_ttc.c           | 1 +
 hw/cadence_uart.c          | 1 +
 hw/cs4231.c                | 1 +
 hw/ds1225y.c               | 1 +
 hw/eccmemctl.c             | 1 +
 hw/empty_slot.c            | 1 +
 hw/escc.c                  | 1 +
 hw/esp.c                   | 1 +
 hw/etraxfs_pic.c           | 1 +
 hw/etraxfs_ser.c           | 1 +
 hw/etraxfs_timer.c         | 1 +
 hw/exynos4210_combiner.c   | 1 +
 hw/exynos4210_fimd.c       | 1 +
 hw/exynos4210_gic.c        | 2 ++
 hw/exynos4210_i2c.c        | 1 +
 hw/exynos4210_mct.c        | 1 +
 hw/exynos4210_pmu.c        | 1 +
 hw/exynos4210_pwm.c        | 1 +
 hw/exynos4210_rtc.c        | 1 +
 hw/exynos4210_uart.c       | 1 +
 hw/fdc.c                   | 2 ++
 hw/g364fb.c                | 1 +
 hw/ide/ahci.c              | 1 +
 hw/imx_avic.c              | 1 +
 hw/imx_ccm.c               | 1 +
 hw/imx_serial.c            | 1 +
 hw/imx_timer.c             | 2 ++
 hw/integratorcp.c          | 1 +
 hw/jazz_led.c              | 1 +
 hw/lan9118.c               | 1 +
 hw/lm32_timer.c            | 1 +
 hw/lm32_uart.c             | 1 +
 hw/marvell_88w8618_audio.c | 1 +
 hw/milkymist-ac97.c        | 1 +
 hw/milkymist-hpdmc.c       | 1 +
 hw/milkymist-memcard.c     | 1 +
 hw/milkymist-minimac2.c    | 1 +
 hw/milkymist-softusb.c     | 1 +
 hw/mipsnet.c               | 1 +
 hw/mpc8544_guts.c          | 1 +
 hw/mst_fpga.c              | 1 +
 hw/musicpal.c              | 8 ++++++++
 hw/omap_gpio.c             | 2 ++
 hw/omap_i2c.c              | 1 +
 hw/omap_intc.c             | 2 ++
 hw/onenand.c               | 1 +
 hw/opencores_eth.c         | 1 +
 hw/openpic.c               | 1 +
 hw/pc_sysfw.c              | 1 +
 hw/pflash_cfi01.c          | 1 +
 hw/pflash_cfi02.c          | 1 +
 hw/pl011.c                 | 4 ++++
 hw/pl022.c                 | 1 +
 hw/pl050.c                 | 2 ++
 hw/pl061.c                 | 2 ++
 hw/pl080.c                 | 2 ++
 hw/ppc/e500.c              | 1 +
 hw/ppce500_pci.c           | 1 +
 hw/ppce500_spin.c          | 1 +
 hw/puv3_dma.c              | 2 ++
 hw/puv3_gpio.c             | 2 ++
 hw/puv3_intc.c             | 2 ++
 hw/puv3_ost.c              | 2 ++
 hw/puv3_pm.c               | 2 ++
 hw/pxa2xx.c                | 4 ++++
 hw/pxa2xx_dma.c            | 1 +
 hw/pxa2xx_gpio.c           | 1 +
 hw/pxa2xx_pic.c            | 1 +
 hw/pxa2xx_timer.c          | 2 ++
 hw/realview_gic.c          | 2 ++
 hw/sdhci.c                 | 1 +
 hw/sh_pci.c                | 2 ++
 hw/slavio_intctl.c         | 1 +
 hw/slavio_misc.c           | 3 +++
 hw/slavio_timer.c          | 1 +
 hw/smc91c111.c             | 1 +
 hw/sparc32_dma.c           | 1 +
 hw/spitz.c                 | 3 +++
 hw/stellaris.c             | 6 ++++++
 hw/stellaris_enet.c        | 1 +
 hw/strongarm.c             | 5 +++++
 hw/sun4m.c                 | 6 ++++++
 hw/sun4m_iommu.c           | 1 +
 hw/tcx.c                   | 1 +
 hw/tusb6010.c              | 1 +
 hw/usb/hcd-ehci-sysbus.c   | 1 +
 hw/usb/hcd-ohci.c          | 1 +
 hw/versatile_i2c.c         | 2 ++
 hw/versatile_pci.c         | 2 ++
 hw/xgmac.c                 | 1 +
 hw/xilinx_axidma.c         | 1 +
 hw/xilinx_axienet.c        | 1 +
 hw/xilinx_ethlite.c        | 1 +
 hw/xilinx_intc.c           | 1 +
 hw/xilinx_spi.c            | 1 +
 hw/xilinx_spips.c          | 1 +
 hw/xilinx_timer.c          | 1 +
 hw/xilinx_uartlite.c       | 2 ++
 hw/zaurus.c                | 1 +
 hw/zynq_slcr.c             | 1 +
 106 files changed, 157 insertions(+)
Peter Maydell - March 4, 2013, 5:58 p.m.
On 5 March 2013 01:32, Paolo Bonzini <pbonzini@redhat.com> wrote:
> These features require creating the device specially from board
> code.  Therefore, devices that use it cannot be created with
> -device.  (And some of them are even visible in binaries for
> qemu-system-x86_64, for example the sysbus EHCI device).
>
> Mass-mark these devices as no_user.

"There is no such thing as a 'no-user' device" -- Anthony
(http://lists.gnu.org/archive/html/qemu-devel/2013-01/msg00896.html)

We should figure out what we might be trying to use 'no-user'
for, and consistently use it that way. Or alternatively we
should remove it (perhaps replacing it with other flags).
Mass-marking all the sysbus devices when we don't have a
consistent sane defined semantics for the flag seems like
a bad idea.

thanks
-- PMM
Paolo Bonzini - March 4, 2013, 8:16 p.m.
Il 04/03/2013 18:58, Peter Maydell ha scritto:
>> > Mass-mark these devices as no_user.
> "There is no such thing as a 'no-user' device" -- Anthony
> (http://lists.gnu.org/archive/html/qemu-devel/2013-01/msg00896.html)
> 
> We should figure out what we might be trying to use 'no-user'
> for, and consistently use it that way. Or alternatively we
> should remove it (perhaps replacing it with other flags).
> Mass-marking all the sysbus devices when we don't have a
> consistent sane defined semantics for the flag seems like
> a bad idea.

$ x86_64-softmmu/qemu-system-x86_64 -device xlnx,,ps7-usb
(qemu) info qtree
bus: main-system-bus
  type System
  dev: xlnx,ps7-usb, id ""
    maxframes = 128
    irq 1
    mmio ffffffffffffffff/0000000000001000
    bus: usb-bus.0
      type usb-bus

I have no idea what this means, but I'm pretty sure that no matter how I
configure it, it will never work.

Yes, the right thing to do would be to QOMify memory regions and
introduce pins, but that's a bit more than the amount of time I have now
for this.

Paolo
Peter Maydell - March 4, 2013, 11:22 p.m.
On 5 March 2013 04:16, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 04/03/2013 18:58, Peter Maydell ha scritto:
>>> > Mass-mark these devices as no_user.
>> "There is no such thing as a 'no-user' device" -- Anthony
>> (http://lists.gnu.org/archive/html/qemu-devel/2013-01/msg00896.html)
>>
>> We should figure out what we might be trying to use 'no-user'
>> for, and consistently use it that way. Or alternatively we
>> should remove it (perhaps replacing it with other flags).
>> Mass-marking all the sysbus devices when we don't have a
>> consistent sane defined semantics for the flag seems like
>> a bad idea.
>
> $ x86_64-softmmu/qemu-system-x86_64 -device xlnx,,ps7-usb
> (qemu) info qtree
> bus: main-system-bus
>   type System
>   dev: xlnx,ps7-usb, id ""
>     maxframes = 128
>     irq 1
>     mmio ffffffffffffffff/0000000000001000
>     bus: usb-bus.0
>       type usb-bus
>
> I have no idea what this means, but I'm pretty sure that no matter how I
> configure it, it will never work.

I agree. Exhibiting something that's a suboptimal user
experience doesn't count as defining consistent semantics
for no_user, though :-)  [and I don't think "this device
can be added via the monitor but not the command line"
counts as consistent or coherent...]

> Yes, the right thing to do would be to QOMify memory regions and
> introduce pins, but that's a bit more than the amount of time I have now
> for this.

...plus it means that when we do have these things we
have to go round and identify the cases where no_user
was set only because we didn't have the features before.

My attitude here really is "yes, it's not great but it's
been like this forever and we don't seem to have had a
huge flood of user complaints, so better not to mess
with it unless what you're doing is going to amount to
some kind of cleanup".

-- PMM
Paolo Bonzini - March 5, 2013, 10:58 a.m.
Il 05/03/2013 00:22, Peter Maydell ha scritto:
>> Yes, the right thing to do would be to QOMify memory regions and
>> introduce pins, but that's a bit more than the amount of time I have now
>> for this.
> 
> ...plus it means that when we do have these things we
> have to go round and identify the cases where no_user
> was set only because we didn't have the features before.

Yes, that's why my patch includes a comment to this end.

> My attitude here really is "yes, it's not great but it's
> been like this forever and we don't seem to have had a
> huge flood of user complaints, so better not to mess
> with it unless what you're doing is going to amount to
> some kind of cleanup".

I did find a complaint from a Red Hat tester about having the sysbus
EHCI device in the help.  I guess an alternative fix will be to move
those device to a separate CONFIG_ symbol.

Paolo
Gerd Hoffmann - March 5, 2013, 11:25 a.m.
On 03/05/13 11:58, Paolo Bonzini wrote:
> Il 05/03/2013 00:22, Peter Maydell ha scritto:
>>> Yes, the right thing to do would be to QOMify memory regions and
>>> introduce pins, but that's a bit more than the amount of time I have now
>>> for this.
>>
>> ...plus it means that when we do have these things we
>> have to go round and identify the cases where no_user
>> was set only because we didn't have the features before.
> 
> Yes, that's why my patch includes a comment to this end.
> 
>> My attitude here really is "yes, it's not great but it's
>> been like this forever and we don't seem to have had a
>> huge flood of user complaints, so better not to mess
>> with it unless what you're doing is going to amount to
>> some kind of cleanup".
> 
> I did find a complaint from a Red Hat tester about having the sysbus
> EHCI device in the help.  I guess an alternative fix will be to move
> those device to a separate CONFIG_ symbol.

Or just exclude any sysbus device?  Or will that kill too much?

cheers,
  Gerd
Markus Armbruster - March 7, 2013, 8:48 a.m.
Peter Maydell <peter.maydell@linaro.org> writes:

> On 5 March 2013 04:16, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> Il 04/03/2013 18:58, Peter Maydell ha scritto:
>>>> > Mass-mark these devices as no_user.
>>> "There is no such thing as a 'no-user' device" -- Anthony
>>> (http://lists.gnu.org/archive/html/qemu-devel/2013-01/msg00896.html)
>>>
>>> We should figure out what we might be trying to use 'no-user'
>>> for, and consistently use it that way. Or alternatively we
>>> should remove it (perhaps replacing it with other flags).
>>> Mass-marking all the sysbus devices when we don't have a
>>> consistent sane defined semantics for the flag seems like
>>> a bad idea.
>>
>> $ x86_64-softmmu/qemu-system-x86_64 -device xlnx,,ps7-usb
>> (qemu) info qtree
>> bus: main-system-bus
>>   type System
>>   dev: xlnx,ps7-usb, id ""
>>     maxframes = 128
>>     irq 1
>>     mmio ffffffffffffffff/0000000000001000
>>     bus: usb-bus.0
>>       type usb-bus
>>
>> I have no idea what this means, but I'm pretty sure that no matter how I
>> configure it, it will never work.
>
> I agree. Exhibiting something that's a suboptimal user
> experience doesn't count as defining consistent semantics
> for no_user, though :-)

Can we make some progress towards something that makes more sense?

First step: reasons for marking a device no_user.

From a user point of view, I think there's just one: -device/device_add
cannot possibly result in a working device.  Coherent enough semantics
for no_user, in my opinion, but I readily concede it's not particularly
useful for maintaining it as infrastructure and device models evolve.

For that, we need to drill down into reasons for "cannot possibly work".
Here are two, please add more:

* Can't make required connections

  -device can make only one connection: to a qbus (first order
  approximation).  Usually suffices for devices on "real" buses like
  PCI, SCSI, ...  Doesn't make any useful connection on "sysbus" (put in
  quotes because it's not really a bus).  Cases in between may exist:
  the bus connection is real enough, but the device wants additional
  connections.

  Additional connections are made by setup code that's not reachable
  from -device.  If they're required for the device to work, then
  -device cannot possibly result in a working device.  Worse, -device
  could happily claim success all the same.

  Are these additional connections always required?

  The need for additional connections depends only on the device, right?

  Automated static reasoning on setup code to determine the value of a
  "makes additional connections" flag feels intractable.  A runtime
  check could be feasible, though.

* Resource collision with board

  The device must connect to some fixed resource, but the board already
  connects something to it.  Without no_user, this should result in an
  error message of sorts, which is much better than the silent breakage
  above.  Whether the message makes any sense to the user is a different
  question.

  Unlike above, this isn't just about the device, it's about the device
  and the board.  Right now, one no_user has to make do for all boards.
  Hmm.

  A -device can also resource-collide with another -device.  But that's
  outside no_user's mission: -device *can* result in a working device
  there, just not in this particular combination.

  In a declarative world, we could automatically filter out devices who
  need resources that are never available on this board.  qdev/QOM is
  moving away from declarative.  Ideas?

>                          [and I don't think "this device
> can be added via the monitor but not the command line"
> counts as consistent or coherent...]

no_user applies equally to -device and device_add.

The command line additionally provides a number of settings the board
setup code may (or may not) use, and no_user has no effect on them.

Coherent enough for me.

>> Yes, the right thing to do would be to QOMify memory regions and
>> introduce pins, but that's a bit more than the amount of time I have now
>> for this.
>
> ...plus it means that when we do have these things we
> have to go round and identify the cases where no_user
> was set only because we didn't have the features before.
>
> My attitude here really is "yes, it's not great but it's
> been like this forever and we don't seem to have had a
> huge flood of user complaints, so better not to mess
> with it unless what you're doing is going to amount to
> some kind of cleanup".

Never underestimate users' capability to suffer quietly.
Peter Maydell - March 7, 2013, 10 a.m.
On 7 March 2013 16:48, Markus Armbruster <armbru@redhat.com> wrote:
> Can we make some progress towards something that makes more sense?
>
> First step: reasons for marking a device no_user.
>
> From a user point of view, I think there's just one: -device/device_add
> cannot possibly result in a working device.  Coherent enough semantics
> for no_user, in my opinion, but I readily concede it's not particularly
> useful for maintaining it as infrastructure and device models evolve.

Ideally it would be nice to move to a model where the error message
was "the device you've created has some required connections which
haven't been wired up", and then for some devices you'd always get
that error [until we implemented syntax for doing the wiring] and
for some you'd only get it if you messed up the command line switches.

> For that, we need to drill down into reasons for "cannot possibly work".
> Here are two, please add more:
>
> * Can't make required connections

> * Resource collision with board
>
>   The device must connect to some fixed resource, but the board already
>   connects something to it.  Without no_user, this should result in an
>   error message of sorts, which is much better than the silent breakage
>   above.  Whether the message makes any sense to the user is a different
>   question.

Do we have any concrete examples of this? I don't think devices should
be making connections to resources themselves. If the only things wiring
up devices are (a) the board models and (b) anything the user says on
the command line, then the conflict only happens if the user says
-device foo,bar=0x42 and bar 0x42 is in use; in that case the message
will make sense to them.

I think a third case for no-user is "this device is actually an
abstract base class" (eg arm_gic_common), which we could deal with
by checking the TypeInfo instead.

Case four: "we really don't expect anybody to be trying to wire this
up dynamically", which would apply to things like the on-cpu peripherals
for some ARM cores. There it is really just an attempt at being friendly
by cutting down the length of the devices list.

Speaking of friendlyness, it might be helpful if the '-devices help'
list was somehow more structured than a single long list and if
more devices had description text?

>>                          [and I don't think "this device
>> can be added via the monitor but not the command line"
>> counts as consistent or coherent...]
>
> no_user applies equally to -device and device_add.

In the codebase as it stands, it applies only to -device.
I agree that we should be consistent here, which we could do
by applying Christian's patch or some variation to make device_add
honour no_user. (Or by removing no_user altogether :-))

-- PMM
Markus Armbruster - March 7, 2013, 12:36 p.m.
Peter Maydell <peter.maydell@linaro.org> writes:

> On 7 March 2013 16:48, Markus Armbruster <armbru@redhat.com> wrote:
>> Can we make some progress towards something that makes more sense?
>>
>> First step: reasons for marking a device no_user.
>>
>> From a user point of view, I think there's just one: -device/device_add
>> cannot possibly result in a working device.  Coherent enough semantics
>> for no_user, in my opinion, but I readily concede it's not particularly
>> useful for maintaining it as infrastructure and device models evolve.
>
> Ideally it would be nice to move to a model where the error message
> was "the device you've created has some required connections which
> haven't been wired up", and then for some devices you'd always get
> that error [until we implemented syntax for doing the wiring] and
> for some you'd only get it if you messed up the command line switches.

Sounds good to me.

>> For that, we need to drill down into reasons for "cannot possibly work".
>> Here are two, please add more:
>>
>> * Can't make required connections
>
>> * Resource collision with board
>>
>>   The device must connect to some fixed resource, but the board already
>>   connects something to it.  Without no_user, this should result in an
>>   error message of sorts, which is much better than the silent breakage
>>   above.  Whether the message makes any sense to the user is a different
>>   question.
>
> Do we have any concrete examples of this? I don't think devices should
> be making connections to resources themselves. If the only things wiring
> up devices are (a) the board models and (b) anything the user says on
> the command line, then the conflict only happens if the user says
> -device foo,bar=0x42 and bar 0x42 is in use; in that case the message
> will make sense to them.

Not exactly what you asked for, but here goes anyway:

    $ qemu-system-x86_64 -nodefaults -S -vnc :0 -monitor stdio -device isa-fdc,id=foo
    QEMU 1.4.50 monitor - type 'help' for more information
    (qemu) info qtree
    bus: main-system-bus
[...]
            bus: isa.0
              type ISA
              dev: isa-fdc, id "foo"
                iobase = 0x3f0
                irq = 6
                dma = 2
                driveA = <null>
                driveB = <null>
                bootindexA = -1
                bootindexB = -1
                check_media_rate = on
                isa irq 6
              dev: isa-fdc, id ""
                iobase = 0x3f0
                irq = 6
                dma = 2
                driveA = <null>
                driveB = <null>
                bootindexA = -1
                bootindexB = -1
                check_media_rate = on
                isa irq 6
[...]
    $ qemu-system-x86_64 -nodefaults -S -vnc :0 -monitor stdio -device q35-pcihost
    Segmentation fault (core dumped)

> I think a third case for no-user is "this device is actually an
> abstract base class" (eg arm_gic_common), which we could deal with
> by checking the TypeInfo instead.

Yes.

> Case four: "we really don't expect anybody to be trying to wire this
> up dynamically", which would apply to things like the on-cpu peripherals
> for some ARM cores. There it is really just an attempt at being friendly
> by cutting down the length of the devices list.

Yes.  Case-by-case decision, I guess.

> Speaking of friendlyness, it might be helpful if the '-devices help'
> list was somehow more structured than a single long list and if
> more devices had description text?

Oh yes.  I wanted to do that, but when Anthony started to dig up qdev, I
hastened to get out of the way.

>>>                          [and I don't think "this device
>>> can be added via the monitor but not the command line"
>>> counts as consistent or coherent...]
>>
>> no_user applies equally to -device and device_add.
>
> In the codebase as it stands, it applies only to -device.
> I agree that we should be consistent here, which we could do
> by applying Christian's patch or some variation to make device_add
> honour no_user. (Or by removing no_user altogether :-))

Actually, it appears to apply only to help now!

git-bisect blames this one:

commit 18b6dade8c0799c48f5c5e124b8c407cd5e22e96
Author: Anthony Liguori <aliguori@us.ibm.com>
Date:   Fri Dec 9 12:08:01 2011 -0600

    qdev: refactor device creation to allow bus_info to be set only in class
    
    As we use class_init to set class members, DeviceInfo no longer holds this
    information.
    
    Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

Review fail, testing fail :(
Peter Crosthwaite - March 7, 2013, 12:45 p.m.
Hi Peter,

[snip]
> Case four: "we really don't expect anybody to be trying to wire this
> up dynamically", which would apply to things like the on-cpu peripherals
> for some ARM cores.

What ARM cores were you thinking here exactly? We are already doing
dynamic machine creation of ARM systems including instantiation of
individual MPCore components.

Regards,
Peter

> There it is really just an attempt at being friendly
> by cutting down the length of the devices list.
>
Peter Maydell - March 7, 2013, 3:41 p.m.
On 7 March 2013 20:45, Peter Crosthwaite <peter.crosthwaite@xilinx.com> wrote:
>> Case four: "we really don't expect anybody to be trying to wire this
>> up dynamically", which would apply to things like the on-cpu peripherals
>> for some ARM cores.
>
> What ARM cores were you thinking here exactly? We are already doing
> dynamic machine creation of ARM systems including instantiation of
> individual MPCore components.

I was handwaving a bit, but for instance arm_mptimer is marked as
no_user. How are you doing dynamic machine creation when neither -device
nor device_add support mapping sysbus mmio or wiring up gpio and irq
lines?

-- PMM
Anthony Liguori - March 7, 2013, 4:09 p.m.
Markus Armbruster <armbru@redhat.com> writes:

> Peter Maydell <peter.maydell@linaro.org> writes:
>>>>                          [and I don't think "this device
>>>> can be added via the monitor but not the command line"
>>>> counts as consistent or coherent...]
>>>
>>> no_user applies equally to -device and device_add.
>>
>> In the codebase as it stands, it applies only to -device.
>> I agree that we should be consistent here, which we could do
>> by applying Christian's patch or some variation to make device_add
>> honour no_user. (Or by removing no_user altogether :-))
>
> Actually, it appears to apply only to help now!
>
> git-bisect blames this one:

Let's step back and try to figure out the problem we're trying to solve.

What is -devices help trying to show?  Devices that are valid to for a
user to pass?  Hint: on a PC, the only thing that's valid to add are
devices that implement a certain bus type.  In fact, it depends on the
bus model.

So if you want to make -device help prettier, we should add a filter
that looks at the busses available and filters anything that isn't an
instance of the appropriate bus types.

Regards,

Anthony Liguori
Peter Maydell - March 7, 2013, 4:22 p.m.
On 8 March 2013 00:09, Anthony Liguori <aliguori@us.ibm.com> wrote:
> What is -devices help trying to show?  Devices that are valid to for a
> user to pass?  Hint: on a PC, the only thing that's valid to add are
> devices that implement a certain bus type.  In fact, it depends on the
> bus model.

Yeah, I think part of the problem is that we are trying to deal
with the QEMU equivalent of the following two scenarios:
 (a) "I opened up my PC and plugged in my new PCI ethernet card"
 (b) "I modified my Dreamcast to have a VGA output with the aid of
      a little circuit board and a soldering iron"
and because we're using the same UI for both, the flexibility
you need for case (b) makes it hopelessly confusing for the
people who are only interested in case (a).

Maybe some sort of "Okay, computer, I want full manual control
now" switch? :-)

-- PMM
Markus Armbruster - March 7, 2013, 5:07 p.m.
Anthony Liguori <aliguori@us.ibm.com> writes:

> Markus Armbruster <armbru@redhat.com> writes:
>
>> Peter Maydell <peter.maydell@linaro.org> writes:
>>>>>                          [and I don't think "this device
>>>>> can be added via the monitor but not the command line"
>>>>> counts as consistent or coherent...]
>>>>
>>>> no_user applies equally to -device and device_add.
>>>
>>> In the codebase as it stands, it applies only to -device.
>>> I agree that we should be consistent here, which we could do
>>> by applying Christian's patch or some variation to make device_add
>>> honour no_user. (Or by removing no_user altogether :-))
>>
>> Actually, it appears to apply only to help now!
>>
>> git-bisect blames this one:
>
> Let's step back and try to figure out the problem we're trying to solve.
>
> What is -devices help trying to show?  Devices that are valid to for a
> user to pass?  Hint: on a PC, the only thing that's valid to add are
> devices that implement a certain bus type.  In fact, it depends on the
> bus model.
>
> So if you want to make -device help prettier, we should add a filter
> that looks at the busses available and filters anything that isn't an
> instance of the appropriate bus types.

Necessary, but not sufficient; see the two examples I posted upstream.
Both devices would pass a "appropriate bus is available" filter.  Both
devices cannot possibly work.  One of them starts up fine (mayhem at
guest runtime expected), the other makes qemu crash & burn immediately.
Anthony Liguori - March 7, 2013, 5:17 p.m.
Markus Armbruster <armbru@redhat.com> writes:

> Anthony Liguori <aliguori@us.ibm.com> writes:
>
>> Markus Armbruster <armbru@redhat.com> writes:
>>
>>> Peter Maydell <peter.maydell@linaro.org> writes:
>>>>>>                          [and I don't think "this device
>>>>>> can be added via the monitor but not the command line"
>>>>>> counts as consistent or coherent...]
>>>>>
>>>>> no_user applies equally to -device and device_add.
>>>>
>>>> In the codebase as it stands, it applies only to -device.
>>>> I agree that we should be consistent here, which we could do
>>>> by applying Christian's patch or some variation to make device_add
>>>> honour no_user. (Or by removing no_user altogether :-))
>>>
>>> Actually, it appears to apply only to help now!
>>>
>>> git-bisect blames this one:
>>
>> Let's step back and try to figure out the problem we're trying to solve.
>>
>> What is -devices help trying to show?  Devices that are valid to for a
>> user to pass?  Hint: on a PC, the only thing that's valid to add are
>> devices that implement a certain bus type.  In fact, it depends on the
>> bus model.
>>
>> So if you want to make -device help prettier, we should add a filter
>> that looks at the busses available and filters anything that isn't an
>> instance of the appropriate bus types.
>
> Necessary, but not sufficient; see the two examples I posted upstream.
> Both devices would pass a "appropriate bus is available" filter.  Both
> devices cannot possibly work.  One of them starts up fine (mayhem at
> guest runtime expected),

Note that what you've done with the first one is 100% representative of
real hardware.  ISA bus conflicts are part of the nature of ISA and
why it was such an awful bus.

> the other makes qemu crash & burn immediately.

This is a modeling problem.  It doesn't make sense for q35-pcihost
to be a PCIDevice.  It's not a PCI device.

But even so, segv'ing is always a bug and we ought to prevent it from
seg faulting.  no_user to hide a SEGV is just using a bandaid.

Regards,

Anthony Liguori
Markus Armbruster - March 7, 2013, 5:45 p.m.
Anthony Liguori <aliguori@us.ibm.com> writes:

> Markus Armbruster <armbru@redhat.com> writes:
>
>> Anthony Liguori <aliguori@us.ibm.com> writes:
>>
>>> Markus Armbruster <armbru@redhat.com> writes:
>>>
>>>> Peter Maydell <peter.maydell@linaro.org> writes:
>>>>>>>                          [and I don't think "this device
>>>>>>> can be added via the monitor but not the command line"
>>>>>>> counts as consistent or coherent...]
>>>>>>
>>>>>> no_user applies equally to -device and device_add.
>>>>>
>>>>> In the codebase as it stands, it applies only to -device.
>>>>> I agree that we should be consistent here, which we could do
>>>>> by applying Christian's patch or some variation to make device_add
>>>>> honour no_user. (Or by removing no_user altogether :-))
>>>>
>>>> Actually, it appears to apply only to help now!
>>>>
>>>> git-bisect blames this one:
>>>
>>> Let's step back and try to figure out the problem we're trying to solve.
>>>
>>> What is -devices help trying to show?  Devices that are valid to for a
>>> user to pass?  Hint: on a PC, the only thing that's valid to add are
>>> devices that implement a certain bus type.  In fact, it depends on the
>>> bus model.
>>>
>>> So if you want to make -device help prettier, we should add a filter
>>> that looks at the busses available and filters anything that isn't an
>>> instance of the appropriate bus types.
>>
>> Necessary, but not sufficient; see the two examples I posted upstream.
>> Both devices would pass a "appropriate bus is available" filter.  Both
>> devices cannot possibly work.  One of them starts up fine (mayhem at
>> guest runtime expected),
>
> Note that what you've done with the first one is 100% representative of
> real hardware.  ISA bus conflicts are part of the nature of ISA and
> why it was such an awful bus.

Would be nice if we could make QEMU behave less awful.

>> the other makes qemu crash & burn immediately.
>
> This is a modeling problem.  It doesn't make sense for q35-pcihost
> to be a PCIDevice.  It's not a PCI device.
>
> But even so, segv'ing is always a bug and we ought to prevent it from
> seg faulting.  no_user to hide a SEGV is just using a bandaid.

A bandaid isn't half bad when you're bleeding :)
Peter Crosthwaite - March 7, 2013, 11:37 p.m.
On Fri, Mar 8, 2013 at 1:41 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 7 March 2013 20:45, Peter Crosthwaite <peter.crosthwaite@xilinx.com> wrote:
>>> Case four: "we really don't expect anybody to be trying to wire this
>>> up dynamically", which would apply to things like the on-cpu peripherals
>>> for some ARM cores.
>>
>> What ARM cores were you thinking here exactly? We are already doing
>> dynamic machine creation of ARM systems including instantiation of
>> individual MPCore components.
>
> I was handwaving a bit, but for instance arm_mptimer is marked as
> no_user. How are you doing dynamic machine creation when neither -device
> nor device_add support mapping sysbus mmio or wiring up gpio and irq
> lines?
>

Its all out of tree using out device tree driven machine instantiation
but we are toying with the idea of moving away from that in favour of
-device and friends (2100 less lines out of tree code for me), once
the aforementioned fixes to sysbus/gpio go through. ARM MPTimer will
still be one of the IPs we will want to dynamically create however.

Regards,
Peter

> -- PMM
>
Peter Maydell - March 7, 2013, 11:53 p.m.
On 8 March 2013 07:37, Peter Crosthwaite <peter.crosthwaite@xilinx.com> wrote:
> Its all out of tree using out device tree driven machine instantiation
> but we are toying with the idea of moving away from that in favour of
> -device and friends (2100 less lines out of tree code for me), once
> the aforementioned fixes to sysbus/gpio go through. ARM MPTimer will
> still be one of the IPs we will want to dynamically create however.

Yeah, I think the 'completely specify your machine from pieces'
usecase is one we have in mind; it's just you can't do it today
(due to the irq/mmio issues). Also as I said it's not clear that
the UI/interface for that should be the same as the one for allowing
the user to plug in PCI cards or disks to a model somebody else
has constructed for them.

-- PMM

Patch

diff --git a/hw/a9scu.c b/hw/a9scu.c
index 0e9e54d..a3f6bfb 100644
--- a/hw/a9scu.c
+++ b/hw/a9scu.c
@@ -147,6 +147,7 @@  static void a9_scu_class_init(ObjectClass *klass, void *data)
     dc->props = a9_scu_properties;
     dc->vmsd = &vmstate_a9_scu;
     dc->reset = a9_scu_reset;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo a9_scu_info = {
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 7eb0c2b..9198de7 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -500,6 +500,7 @@  static void pbm_host_class_init(ObjectClass *klass, void *data)
 
     k->init = pci_pbm_init_device;
     dc->reset = pci_pbm_reset;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pbm_host_info = {
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index 7ecb7da..391709a 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -411,6 +411,7 @@  static void arm_sysctl_class_init(ObjectClass *klass, void *data)
     dc->reset = arm_sysctl_reset;
     dc->vmsd = &vmstate_arm_sysctl;
     dc->props = arm_sysctl_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo arm_sysctl_info = {
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index c1e56be..5d7182a 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -359,6 +359,7 @@  static void icp_pit_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
 
     sdc->init = icp_pit_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo icp_pit_info = {
@@ -381,6 +382,7 @@  static void sp804_class_init(ObjectClass *klass, void *data)
 
     sdc->init = sp804_init;
     k->props = sp804_properties;
+    k->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo sp804_info = {
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 904696c..f9da127 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -267,6 +267,7 @@  static void bitband_class_init(ObjectClass *klass, void *data)
 
     k->init = bitband_init;
     dc->props = bitband_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo bitband_info = {
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 114508f..a153a98 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -228,6 +228,7 @@  static void gpio_i2c_class_init(ObjectClass *klass, void *data)
 
     k->init = gpio_i2c_init;
     dc->desc = "Virtual GPIO to I2C bridge";
+    dc->no_user = 1; /* for gpio pins */
 }
 
 static const TypeInfo gpio_i2c_info = {
diff --git a/hw/cadence_ttc.c b/hw/cadence_ttc.c
index 67028a3..7a7aff4 100644
--- a/hw/cadence_ttc.c
+++ b/hw/cadence_ttc.c
@@ -472,6 +472,7 @@  static void cadence_ttc_class_init(ObjectClass *klass, void *data)
 
     sdc->init = cadence_ttc_init;
     dc->vmsd = &vmstate_cadence_ttc;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo cadence_ttc_info = {
diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
index 5766d38..7d40d0e 100644
--- a/hw/cadence_uart.c
+++ b/hw/cadence_uart.c
@@ -500,6 +500,7 @@  static void cadence_uart_class_init(ObjectClass *klass, void *data)
 
     sdc->init = cadence_uart_init;
     dc->vmsd = &vmstate_cadence_uart;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo cadence_uart_info = {
diff --git a/hw/cs4231.c b/hw/cs4231.c
index ae384b9..ce7c020 100644
--- a/hw/cs4231.c
+++ b/hw/cs4231.c
@@ -164,6 +164,7 @@  static void cs4231_class_init(ObjectClass *klass, void *data)
     dc->reset = cs_reset;
     dc->vmsd = &vmstate_cs4231;
     dc->props = cs4231_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo cs4231_info = {
diff --git a/hw/ds1225y.c b/hw/ds1225y.c
index a6219a7..cb5b835 100644
--- a/hw/ds1225y.c
+++ b/hw/ds1225y.c
@@ -148,6 +148,7 @@  static void nvram_sysbus_class_init(ObjectClass *klass, void *data)
     k->init = nvram_sysbus_initfn;
     dc->vmsd = &vmstate_nvram;
     dc->props = nvram_sysbus_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo nvram_sysbus_info = {
diff --git a/hw/eccmemctl.c b/hw/eccmemctl.c
index dbac2c2..6f28a6b 100644
--- a/hw/eccmemctl.c
+++ b/hw/eccmemctl.c
@@ -322,6 +322,7 @@  static void ecc_class_init(ObjectClass *klass, void *data)
     dc->reset = ecc_reset;
     dc->vmsd = &vmstate_ecc;
     dc->props = ecc_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo ecc_info = {
diff --git a/hw/empty_slot.c b/hw/empty_slot.c
index d7b5497..8802ca7 100644
--- a/hw/empty_slot.c
+++ b/hw/empty_slot.c
@@ -81,6 +81,7 @@  static void empty_slot_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
     k->init = empty_slot_init1;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo empty_slot_info = {
diff --git a/hw/escc.c b/hw/escc.c
index 18c0292..49fabf0 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -921,6 +921,7 @@  static void escc_class_init(ObjectClass *klass, void *data)
     dc->reset = escc_reset;
     dc->vmsd = &vmstate_escc;
     dc->props = escc_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo escc_info = {
diff --git a/hw/esp.c b/hw/esp.c
index 2af48aa..723c221 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -710,6 +710,7 @@  static void sysbus_esp_class_init(ObjectClass *klass, void *data)
     k->init = sysbus_esp_init;
     dc->reset = sysbus_esp_hard_reset;
     dc->vmsd = &vmstate_sysbus_esp_scsi;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo sysbus_esp_info = {
diff --git a/hw/etraxfs_pic.c b/hw/etraxfs_pic.c
index 64af31c..156f006 100644
--- a/hw/etraxfs_pic.c
+++ b/hw/etraxfs_pic.c
@@ -163,6 +163,7 @@  static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
 
     k->init = etraxfs_pic_init;
     dc->props = etraxfs_pic_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo etraxfs_pic_info = {
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index 72c8868..b3ca719 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -231,6 +231,7 @@  static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
 
     k->init = etraxfs_ser_init;
     dc->reset = etraxfs_ser_reset;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo etraxfs_ser_info = {
diff --git a/hw/etraxfs_timer.c b/hw/etraxfs_timer.c
index d3dac52..cc503cb 100644
--- a/hw/etraxfs_timer.c
+++ b/hw/etraxfs_timer.c
@@ -334,6 +334,7 @@  static void etraxfs_timer_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
 
     sdc->init = etraxfs_timer_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo etraxfs_timer_info = {
diff --git a/hw/exynos4210_combiner.c b/hw/exynos4210_combiner.c
index ba644b4..6caae38 100644
--- a/hw/exynos4210_combiner.c
+++ b/hw/exynos4210_combiner.c
@@ -438,6 +438,7 @@  static void exynos4210_combiner_class_init(ObjectClass *klass, void *data)
     dc->reset = exynos4210_combiner_reset;
     dc->props = exynos4210_combiner_properties;
     dc->vmsd = &vmstate_exynos4210_combiner;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo exynos4210_combiner_info = {
diff --git a/hw/exynos4210_fimd.c b/hw/exynos4210_fimd.c
index 3d498b7..be946d4 100644
--- a/hw/exynos4210_fimd.c
+++ b/hw/exynos4210_fimd.c
@@ -1910,6 +1910,7 @@  static void exynos4210_fimd_class_init(ObjectClass *klass, void *data)
 
     dc->vmsd = &exynos4210_fimd_vmstate;
     dc->reset = exynos4210_fimd_reset;
+    dc->no_user = 1; /* for sysbus mmio/irq */
     k->init = exynos4210_fimd_init;
 }
 
diff --git a/hw/exynos4210_gic.c b/hw/exynos4210_gic.c
index 94b138f..8a47ead 100644
--- a/hw/exynos4210_gic.c
+++ b/hw/exynos4210_gic.c
@@ -344,6 +344,7 @@  static void exynos4210_gic_class_init(ObjectClass *klass, void *data)
 
     k->init = exynos4210_gic_init;
     dc->props = exynos4210_gic_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo exynos4210_gic_info = {
@@ -445,6 +446,7 @@  static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
     dc->reset = exynos4210_irq_gate_reset;
     dc->vmsd = &vmstate_exynos4210_irq_gate;
     dc->props = exynos4210_irq_gate_properties;
+    dc->no_user = 1; /* for sysbus irq */
 }
 
 static const TypeInfo exynos4210_irq_gate_info = {
diff --git a/hw/exynos4210_i2c.c b/hw/exynos4210_i2c.c
index cefd736..c546aa6 100644
--- a/hw/exynos4210_i2c.c
+++ b/hw/exynos4210_i2c.c
@@ -316,6 +316,7 @@  static void exynos4210_i2c_class_init(ObjectClass *klass, void *data)
 
     dc->vmsd = &exynos4210_i2c_vmstate;
     dc->reset = exynos4210_i2c_reset;
+    dc->no_user = 1; /* for sysbus mmio/irq */
     sbdc->init = exynos4210_i2c_realize;
 }
 
diff --git a/hw/exynos4210_mct.c b/hw/exynos4210_mct.c
index d7d5904..5c66db3 100644
--- a/hw/exynos4210_mct.c
+++ b/hw/exynos4210_mct.c
@@ -1465,6 +1465,7 @@  static void exynos4210_mct_class_init(ObjectClass *klass, void *data)
     k->init = exynos4210_mct_init;
     dc->reset = exynos4210_mct_reset;
     dc->vmsd = &vmstate_exynos4210_mct_state;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo exynos4210_mct_info = {
diff --git a/hw/exynos4210_pmu.c b/hw/exynos4210_pmu.c
index 7c81a1b..23225ca 100644
--- a/hw/exynos4210_pmu.c
+++ b/hw/exynos4210_pmu.c
@@ -482,6 +482,7 @@  static void exynos4210_pmu_class_init(ObjectClass *klass, void *data)
     k->init = exynos4210_pmu_init;
     dc->reset = exynos4210_pmu_reset;
     dc->vmsd = &exynos4210_pmu_vmstate;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo exynos4210_pmu_info = {
diff --git a/hw/exynos4210_pwm.c b/hw/exynos4210_pwm.c
index c865624..1b2fd7d 100644
--- a/hw/exynos4210_pwm.c
+++ b/hw/exynos4210_pwm.c
@@ -405,6 +405,7 @@  static void exynos4210_pwm_class_init(ObjectClass *klass, void *data)
     k->init = exynos4210_pwm_init;
     dc->reset = exynos4210_pwm_reset;
     dc->vmsd = &vmstate_exynos4210_pwm_state;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo exynos4210_pwm_info = {
diff --git a/hw/exynos4210_rtc.c b/hw/exynos4210_rtc.c
index 5694a62..b83dfca 100644
--- a/hw/exynos4210_rtc.c
+++ b/hw/exynos4210_rtc.c
@@ -575,6 +575,7 @@  static void exynos4210_rtc_class_init(ObjectClass *klass, void *data)
     k->init = exynos4210_rtc_init;
     dc->reset = exynos4210_rtc_reset;
     dc->vmsd = &vmstate_exynos4210_rtc_state;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo exynos4210_rtc_info = {
diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c
index bdf797a..8fbd4b8 100644
--- a/hw/exynos4210_uart.c
+++ b/hw/exynos4210_uart.c
@@ -659,6 +659,7 @@  static void exynos4210_uart_class_init(ObjectClass *klass, void *data)
     dc->reset = exynos4210_uart_reset;
     dc->props = exynos4210_uart_properties;
     dc->vmsd = &vmstate_exynos4210_uart;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo exynos4210_uart_info = {
diff --git a/hw/fdc.c b/hw/fdc.c
index 976a587..7fa3576 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -2242,6 +2242,7 @@  static void sysbus_fdc_class_init(ObjectClass *klass, void *data)
     dc->reset = fdctrl_external_reset_sysbus;
     dc->vmsd = &vmstate_sysbus_fdc;
     dc->props = sysbus_fdc_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo sysbus_fdc_info = {
@@ -2265,6 +2266,7 @@  static void sun4m_fdc_class_init(ObjectClass *klass, void *data)
     dc->reset = fdctrl_external_reset_sysbus;
     dc->vmsd = &vmstate_sysbus_fdc;
     dc->props = sun4m_fdc_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo sun4m_fdc_info = {
diff --git a/hw/g364fb.c b/hw/g364fb.c
index 0c0c8ba..e897838 100644
--- a/hw/g364fb.c
+++ b/hw/g364fb.c
@@ -595,6 +595,7 @@  static void g364fb_sysbus_class_init(ObjectClass *klass, void *data)
     dc->reset = g364fb_sysbus_reset;
     dc->vmsd = &vmstate_g364fb;
     dc->props = g364fb_sysbus_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo g364fb_sysbus_info = {
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index ad0094f..f27c05e 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1321,6 +1321,7 @@  static void sysbus_ahci_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_sysbus_ahci;
     dc->props = sysbus_ahci_properties;
     dc->reset = sysbus_ahci_reset;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo sysbus_ahci_info = {
diff --git a/hw/imx_avic.c b/hw/imx_avic.c
index f1f066c..9a4a019 100644
--- a/hw/imx_avic.c
+++ b/hw/imx_avic.c
@@ -391,6 +391,7 @@  static void imx_avic_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_imx_avic;
     dc->reset = imx_avic_reset;
     dc->desc = "i.MX Advanced Vector Interrupt Controller";
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo imx_avic_info = {
diff --git a/hw/imx_ccm.c b/hw/imx_ccm.c
index 477903a..e20f339 100644
--- a/hw/imx_ccm.c
+++ b/hw/imx_ccm.c
@@ -304,6 +304,7 @@  static void imx_ccm_class_init(ObjectClass *klass, void *data)
     dc->reset = imx_ccm_reset;
     dc->vmsd = &vmstate_imx_ccm;
     dc->desc = "i.MX Clock Control Module";
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo imx_ccm_info = {
diff --git a/hw/imx_serial.c b/hw/imx_serial.c
index 2d8253e..24fd96f 100644
--- a/hw/imx_serial.c
+++ b/hw/imx_serial.c
@@ -450,6 +450,7 @@  static void imx_serial_class_init(ObjectClass *klass, void *data)
     dc->reset = imx_serial_reset_at_boot;
     dc->desc = "i.MX series UART";
     dc->props = imx32_serial_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo imx_serial_info = {
diff --git a/hw/imx_timer.c b/hw/imx_timer.c
index e924c74..feba982 100644
--- a/hw/imx_timer.c
+++ b/hw/imx_timer.c
@@ -654,6 +654,7 @@  static void imx_timerg_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_imx_timerg;
     dc->reset = imx_timerg_reset;
     dc->desc = "i.MX general timer";
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static void imx_timerp_class_init(ObjectClass *klass, void *data)
@@ -664,6 +665,7 @@  static void imx_timerp_class_init(ObjectClass *klass, void *data)
     dc->vmsd = &vmstate_imx_timerp;
     dc->reset = imx_timerp_reset;
     dc->desc = "i.MX periodic timer";
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo imx_timerp_info = {
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index 9e3630a..dd8cd1d 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -534,6 +534,7 @@  static void core_class_init(ObjectClass *klass, void *data)
 
     k->init = integratorcm_init;
     dc->props = core_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo core_info = {
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index 4822c48..4e6dfd9 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -275,6 +275,7 @@  static void jazz_led_class_init(ObjectClass *klass, void *data)
     dc->desc = "Jazz LED display",
     dc->vmsd = &vmstate_jazz_led;
     dc->reset = jazz_led_reset;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo jazz_led_info = {
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 0e844e5..16bff88 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -1366,6 +1366,7 @@  static void lan9118_class_init(ObjectClass *klass, void *data)
     dc->reset = lan9118_reset;
     dc->props = lan9118_properties;
     dc->vmsd = &vmstate_lan9118;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo lan9118_info = {
diff --git a/hw/lm32_timer.c b/hw/lm32_timer.c
index db527e9..6da6ace 100644
--- a/hw/lm32_timer.c
+++ b/hw/lm32_timer.c
@@ -213,6 +213,7 @@  static void lm32_timer_class_init(ObjectClass *klass, void *data)
     dc->reset = timer_reset;
     dc->vmsd = &vmstate_lm32_timer;
     dc->props = lm32_timer_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo lm32_timer_info = {
diff --git a/hw/lm32_uart.c b/hw/lm32_uart.c
index 9c89cca..94f6aa6 100644
--- a/hw/lm32_uart.c
+++ b/hw/lm32_uart.c
@@ -279,6 +279,7 @@  static void lm32_uart_class_init(ObjectClass *klass, void *data)
     k->init = lm32_uart_init;
     dc->reset = uart_reset;
     dc->vmsd = &vmstate_lm32_uart;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo lm32_uart_info = {
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index c792caf..2915844 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -286,6 +286,7 @@  static void mv88w8618_audio_class_init(ObjectClass *klass, void *data)
     dc->reset = mv88w8618_audio_reset;
     dc->vmsd = &mv88w8618_audio_vmsd;
     dc->props = mv88w8618_audio_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo mv88w8618_audio_info = {
diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c
index d51d1ac..f6e8730 100644
--- a/hw/milkymist-ac97.c
+++ b/hw/milkymist-ac97.c
@@ -327,6 +327,7 @@  static void milkymist_ac97_class_init(ObjectClass *klass, void *data)
     k->init = milkymist_ac97_init;
     dc->reset = milkymist_ac97_reset;
     dc->vmsd = &vmstate_milkymist_ac97;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo milkymist_ac97_info = {
diff --git a/hw/milkymist-hpdmc.c b/hw/milkymist-hpdmc.c
index ea4d210..5f77d67 100644
--- a/hw/milkymist-hpdmc.c
+++ b/hw/milkymist-hpdmc.c
@@ -153,6 +153,7 @@  static void milkymist_hpdmc_class_init(ObjectClass *klass, void *data)
     k->init = milkymist_hpdmc_init;
     dc->reset = milkymist_hpdmc_reset;
     dc->vmsd = &vmstate_milkymist_hpdmc;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo milkymist_hpdmc_info = {
diff --git a/hw/milkymist-memcard.c b/hw/milkymist-memcard.c
index 9d15309..8fc44b4 100644
--- a/hw/milkymist-memcard.c
+++ b/hw/milkymist-memcard.c
@@ -286,6 +286,7 @@  static void milkymist_memcard_class_init(ObjectClass *klass, void *data)
     k->init = milkymist_memcard_init;
     dc->reset = milkymist_memcard_reset;
     dc->vmsd = &vmstate_milkymist_memcard;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo milkymist_memcard_info = {
diff --git a/hw/milkymist-minimac2.c b/hw/milkymist-minimac2.c
index 9992dcc..7875bd8 100644
--- a/hw/milkymist-minimac2.c
+++ b/hw/milkymist-minimac2.c
@@ -533,6 +533,7 @@  static void milkymist_minimac2_class_init(ObjectClass *klass, void *data)
     dc->reset = milkymist_minimac2_reset;
     dc->vmsd = &vmstate_milkymist_minimac2;
     dc->props = milkymist_minimac2_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo milkymist_minimac2_info = {
diff --git a/hw/milkymist-softusb.c b/hw/milkymist-softusb.c
index 01660be..3dc6438 100644
--- a/hw/milkymist-softusb.c
+++ b/hw/milkymist-softusb.c
@@ -314,6 +314,7 @@  static void milkymist_softusb_class_init(ObjectClass *klass, void *data)
     dc->reset = milkymist_softusb_reset;
     dc->vmsd = &vmstate_milkymist_softusb;
     dc->props = milkymist_softusb_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo milkymist_softusb_info = {
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index ff6bf7f..5887bb2 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -267,6 +267,7 @@  static void mipsnet_class_init(ObjectClass *klass, void *data)
     dc->reset = mipsnet_sysbus_reset;
     dc->vmsd = &vmstate_mipsnet;
     dc->props = mipsnet_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo mipsnet_info = {
diff --git a/hw/mpc8544_guts.c b/hw/mpc8544_guts.c
index 728723c..de6d037 100644
--- a/hw/mpc8544_guts.c
+++ b/hw/mpc8544_guts.c
@@ -126,6 +126,7 @@  static void mpc8544_guts_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
     k->init = mpc8544_guts_initfn;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo mpc8544_guts_info = {
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 7ae05e3..0a5fe7e 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -246,6 +246,7 @@  static void mst_fpga_class_init(ObjectClass *klass, void *data)
     k->init = mst_fpga_init;
     dc->desc = "Mainstone II FPGA";
     dc->vmsd = &vmstate_mst_fpga_regs;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo mst_fpga_info = {
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 272cb80..e844daf 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -641,6 +641,7 @@  static void musicpal_lcd_class_init(ObjectClass *klass, void *data)
 
     k->init = musicpal_lcd_init;
     dc->vmsd = &musicpal_lcd_vmsd;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo musicpal_lcd_info = {
@@ -760,6 +761,7 @@  static void mv88w8618_pic_class_init(ObjectClass *klass, void *data)
     k->init = mv88w8618_pic_init;
     dc->reset = mv88w8618_pic_reset;
     dc->vmsd = &mv88w8618_pic_vmsd;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo mv88w8618_pic_info = {
@@ -937,6 +939,7 @@  static void mv88w8618_pit_class_init(ObjectClass *klass, void *data)
     k->init = mv88w8618_pit_init;
     dc->reset = mv88w8618_pit_reset;
     dc->vmsd = &mv88w8618_pit_vmsd;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo mv88w8618_pit_info = {
@@ -1017,6 +1020,7 @@  static void mv88w8618_flashcfg_class_init(ObjectClass *klass, void *data)
 
     k->init = mv88w8618_flashcfg_init;
     dc->vmsd = &mv88w8618_flashcfg_vmsd;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo mv88w8618_flashcfg_info = {
@@ -1339,6 +1343,7 @@  static void musicpal_gpio_class_init(ObjectClass *klass, void *data)
     k->init = musicpal_gpio_init;
     dc->reset = musicpal_gpio_reset;
     dc->vmsd = &musicpal_gpio_vmsd;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo musicpal_gpio_info = {
@@ -1493,6 +1498,7 @@  static void musicpal_key_class_init(ObjectClass *klass, void *data)
 
     k->init = musicpal_key_init;
     dc->vmsd = &musicpal_key_vmsd;
+    dc->no_user = 1; /* for gpio */
 }
 
 static const TypeInfo musicpal_key_info = {
@@ -1671,8 +1677,10 @@  machine_init(musicpal_machine_init);
 static void mv88w8618_wlan_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = mv88w8618_wlan_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo mv88w8618_wlan_info = {
diff --git a/hw/omap_gpio.c b/hw/omap_gpio.c
index aadf1cc..2d81a6a 100644
--- a/hw/omap_gpio.c
+++ b/hw/omap_gpio.c
@@ -745,6 +745,7 @@  static void omap_gpio_class_init(ObjectClass *klass, void *data)
     k->init = omap_gpio_init;
     dc->reset = omap_gpif_reset;
     dc->props = omap_gpio_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo omap_gpio_info = {
@@ -774,6 +775,7 @@  static void omap2_gpio_class_init(ObjectClass *klass, void *data)
     k->init = omap2_gpio_init;
     dc->reset = omap2_gpif_reset;
     dc->props = omap2_gpio_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo omap2_gpio_info = {
diff --git a/hw/omap_i2c.c b/hw/omap_i2c.c
index 143b198..8f8c738 100644
--- a/hw/omap_i2c.c
+++ b/hw/omap_i2c.c
@@ -469,6 +469,7 @@  static void omap_i2c_class_init(ObjectClass *klass, void *data)
     k->init = omap_i2c_init;
     dc->props = omap_i2c_properties;
     dc->reset = omap_i2c_reset;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo omap_i2c_info = {
diff --git a/hw/omap_intc.c b/hw/omap_intc.c
index 4b0acd0..37c1965 100644
--- a/hw/omap_intc.c
+++ b/hw/omap_intc.c
@@ -387,6 +387,7 @@  static void omap_intc_class_init(ObjectClass *klass, void *data)
     k->init = omap_intc_init;
     dc->reset = omap_inth_reset;
     dc->props = omap_intc_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo omap_intc_info = {
@@ -631,6 +632,7 @@  static void omap2_intc_class_init(ObjectClass *klass, void *data)
     k->init = omap2_intc_init;
     dc->reset = omap_inth_reset;
     dc->props = omap2_intc_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo omap2_intc_info = {
diff --git a/hw/onenand.c b/hw/onenand.c
index 00a8738..ab70ca0 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -819,6 +819,7 @@  static void onenand_class_init(ObjectClass *klass, void *data)
     k->init = onenand_initfn;
     dc->reset = onenand_system_reset;
     dc->props = onenand_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo onenand_info = {
diff --git a/hw/opencores_eth.c b/hw/opencores_eth.c
index f9ba5ee..5f93475 100644
--- a/hw/opencores_eth.c
+++ b/hw/opencores_eth.c
@@ -716,6 +716,7 @@  static void open_eth_class_init(ObjectClass *klass, void *data)
     dc->desc = "Opencores 10/100 Mbit Ethernet";
     dc->reset = qdev_open_eth_reset;
     dc->props = open_eth_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo open_eth_info = {
diff --git a/hw/openpic.c b/hw/openpic.c
index 20a479c..07dfd59 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -1644,6 +1644,7 @@  static void openpic_class_init(ObjectClass *klass, void *data)
     k->init = openpic_init;
     dc->props = openpic_properties;
     dc->reset = openpic_reset;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo openpic_info = {
diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
index 7f6c12c..785e7f4 100644
--- a/hw/pc_sysfw.c
+++ b/hw/pc_sysfw.c
@@ -254,6 +254,7 @@  static void pcsysfw_class_init (ObjectClass *klass, void *data)
     dc->desc = "PC System Firmware";
     dc->init = pcsysfw_init;
     dc->props = pcsysfw_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pcsysfw_info = {
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 123b006..0524cc8 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -707,6 +707,7 @@  static void pflash_cfi01_class_init(ObjectClass *klass, void *data)
 
     k->init = pflash_cfi01_init;
     dc->props = pflash_cfi01_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index 44bd465..ee1c530 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -734,6 +734,7 @@  static void pflash_cfi02_class_init(ObjectClass *klass, void *data)
 
     k->init = pflash_cfi02_init;
     dc->props = pflash_cfi02_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pflash_cfi02_info = {
diff --git a/hw/pl011.c b/hw/pl011.c
index 002a50e..2910684 100644
--- a/hw/pl011.c
+++ b/hw/pl011.c
@@ -296,8 +296,10 @@  static int pl011_luminary_init(SysBusDevice *dev)
 static void pl011_arm_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = pl011_arm_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pl011_arm_info = {
@@ -310,8 +312,10 @@  static const TypeInfo pl011_arm_info = {
 static void pl011_luminary_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = pl011_luminary_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pl011_luminary_info = {
diff --git a/hw/pl022.c b/hw/pl022.c
index c160e90..2159cc4 100644
--- a/hw/pl022.c
+++ b/hw/pl022.c
@@ -291,6 +291,7 @@  static void pl022_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
 
     sdc->init = pl022_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pl022_info = {
diff --git a/hw/pl050.c b/hw/pl050.c
index 5d06bc9..d3efdd9 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -166,6 +166,7 @@  static void pl050_kbd_class_init(ObjectClass *klass, void *data)
 
     k->init = pl050_init_keyboard;
     dc->vmsd = &vmstate_pl050;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pl050_kbd_info = {
@@ -182,6 +183,7 @@  static void pl050_mouse_class_init(ObjectClass *klass, void *data)
 
     k->init = pl050_init_mouse;
     dc->vmsd = &vmstate_pl050;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pl050_mouse_info = {
diff --git a/hw/pl061.c b/hw/pl061.c
index a78e819..c919f56 100644
--- a/hw/pl061.c
+++ b/hw/pl061.c
@@ -302,6 +302,7 @@  static void pl061_class_init(ObjectClass *klass, void *data)
 
     k->init = pl061_init_arm;
     dc->vmsd = &vmstate_pl061;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pl061_info = {
@@ -318,6 +319,7 @@  static void pl061_luminary_class_init(ObjectClass *klass, void *data)
 
     k->init = pl061_init_luminary;
     dc->vmsd = &vmstate_pl061;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pl061_luminary_info = {
diff --git a/hw/pl080.c b/hw/pl080.c
index f6bbf98..d6e52b2 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -384,6 +384,7 @@  static void pl080_class_init(ObjectClass *klass, void *data)
     k->init = pl080_init;
     dc->no_user = 1;
     dc->vmsd = &vmstate_pl080;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pl080_info = {
@@ -401,6 +402,7 @@  static void pl081_class_init(ObjectClass *klass, void *data)
     k->init = pl081_init;
     dc->no_user = 1;
     dc->vmsd = &vmstate_pl080;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pl081_info = {
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 451682c..6a09671 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -684,6 +684,7 @@  static void e500_ccsr_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
     k->init = e500_ccsr_initfn;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo e500_ccsr_info = {
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 1e1ade3..03f054a 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -387,6 +387,7 @@  static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
     k->device_id = PCI_DEVICE_ID_MPC8533E;
     k->class_id = PCI_CLASS_PROCESSOR_POWERPC;
     dc->desc = "Host bridge";
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo e500_host_bridge_info = {
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index 5bdce52..5b4e027 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -205,6 +205,7 @@  static void ppce500_spin_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 
     k->init = ppce500_spin_initfn;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo ppce500_spin_info = {
diff --git a/hw/puv3_dma.c b/hw/puv3_dma.c
index 9de63b4..f3731c5 100644
--- a/hw/puv3_dma.c
+++ b/hw/puv3_dma.c
@@ -90,8 +90,10 @@  static int puv3_dma_init(SysBusDevice *dev)
 static void puv3_dma_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = puv3_dma_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo puv3_dma_info = {
diff --git a/hw/puv3_gpio.c b/hw/puv3_gpio.c
index 152248d..2259259 100644
--- a/hw/puv3_gpio.c
+++ b/hw/puv3_gpio.c
@@ -122,8 +122,10 @@  static int puv3_gpio_init(SysBusDevice *dev)
 static void puv3_gpio_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = puv3_gpio_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo puv3_gpio_info = {
diff --git a/hw/puv3_intc.c b/hw/puv3_intc.c
index 07f5649..c968ed1 100644
--- a/hw/puv3_intc.c
+++ b/hw/puv3_intc.c
@@ -116,8 +116,10 @@  static int puv3_intc_init(SysBusDevice *dev)
 static void puv3_intc_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = puv3_intc_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo puv3_intc_info = {
diff --git a/hw/puv3_ost.c b/hw/puv3_ost.c
index 14c6f21..f5556d0 100644
--- a/hw/puv3_ost.c
+++ b/hw/puv3_ost.c
@@ -132,8 +132,10 @@  static int puv3_ost_init(SysBusDevice *dev)
 static void puv3_ost_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = puv3_ost_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo puv3_ost_info = {
diff --git a/hw/puv3_pm.c b/hw/puv3_pm.c
index 87a687a..9a1bcd3 100644
--- a/hw/puv3_pm.c
+++ b/hw/puv3_pm.c
@@ -130,8 +130,10 @@  static int puv3_pm_init(SysBusDevice *dev)
 static void puv3_pm_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = puv3_pm_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo puv3_pm_info = {
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index d303320..d6fe863 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1192,6 +1192,7 @@  static void pxa2xx_rtc_sysbus_class_init(ObjectClass *klass, void *data)
     k->init = pxa2xx_rtc_init;
     dc->desc = "PXA2xx RTC Controller";
     dc->vmsd = &vmstate_pxa2xx_rtc_regs;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pxa2xx_rtc_sysbus_info = {
@@ -1508,6 +1509,7 @@  static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data)
     dc->desc = "PXA2xx I2C Bus Controller";
     dc->vmsd = &vmstate_pxa2xx_i2c;
     dc->props = pxa2xx_i2c_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pxa2xx_i2c_info = {
@@ -2269,8 +2271,10 @@  PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
 static void pxa2xx_ssp_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = pxa2xx_ssp_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pxa2xx_ssp_info = {
diff --git a/hw/pxa2xx_dma.c b/hw/pxa2xx_dma.c
index c0dba45..8df1cdc 100644
--- a/hw/pxa2xx_dma.c
+++ b/hw/pxa2xx_dma.c
@@ -557,6 +557,7 @@  static void pxa2xx_dma_class_init(ObjectClass *klass, void *data)
     dc->desc = "PXA2xx DMA controller";
     dc->vmsd = &vmstate_pxa2xx_dma;
     dc->props = pxa2xx_dma_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pxa2xx_dma_info = {
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 05d2ad2..81bbf47 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -333,6 +333,7 @@  static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data)
     k->init = pxa2xx_gpio_initfn;
     dc->desc = "PXA2xx GPIO controller";
     dc->props = pxa2xx_gpio_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pxa2xx_gpio_info = {
diff --git a/hw/pxa2xx_pic.c b/hw/pxa2xx_pic.c
index 90b8fef..e576b93 100644
--- a/hw/pxa2xx_pic.c
+++ b/hw/pxa2xx_pic.c
@@ -317,6 +317,7 @@  static void pxa2xx_pic_class_init(ObjectClass *klass, void *data)
     k->init = pxa2xx_pic_initfn;
     dc->desc = "PXA2xx PIC";
     dc->vmsd = &vmstate_pxa2xx_pic_regs;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pxa2xx_pic_info = {
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 5c9d2e8..c21f185 100644
--- a/hw/pxa2xx_timer.c
+++ b/hw/pxa2xx_timer.c
@@ -540,6 +540,7 @@  static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
     dc->desc = "PXA25x timer";
     dc->vmsd = &vmstate_pxa2xx_timer_regs;
     dc->props = pxa25x_timer_dev_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pxa25x_timer_dev_info = {
@@ -565,6 +566,7 @@  static void pxa27x_timer_dev_class_init(ObjectClass *klass, void *data)
     dc->desc = "PXA27x timer";
     dc->vmsd = &vmstate_pxa2xx_timer_regs;
     dc->props = pxa27x_timer_dev_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pxa27x_timer_dev_info = {
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8f2a7e2..0f2b4f1 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -55,8 +55,10 @@  static int realview_gic_init(SysBusDevice *dev)
 static void realview_gic_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = realview_gic_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo realview_gic_info = {
diff --git a/hw/sdhci.c b/hw/sdhci.c
index e535df9..abcb3ae 100644
--- a/hw/sdhci.c
+++ b/hw/sdhci.c
@@ -1265,6 +1265,7 @@  static void sdhci_class_init(ObjectClass *klass, void *data)
     dc->props = sdhci_properties;
     dc->reset = sdhci_generic_reset;
     dc->realize = sdhci_realize;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 
     k->reset = sdhci_reset;
     k->mem_read = sdhci_read;
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index 077d957..60b21ed 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -166,8 +166,10 @@  static const TypeInfo sh_pci_host_info = {
 static void sh_pci_device_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = sh_pci_device_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo sh_pci_device_info = {
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index 136ceeb..fdb4877 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -454,6 +454,7 @@  static void slavio_intctl_class_init(ObjectClass *klass, void *data)
     k->init = slavio_intctl_init1;
     dc->reset = slavio_intctl_reset;
     dc->vmsd = &vmstate_intctl;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo slavio_intctl_info = {
diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c
index af24cc1..cf7cb9e 100644
--- a/hw/slavio_misc.c
+++ b/hw/slavio_misc.c
@@ -476,6 +476,7 @@  static void slavio_misc_class_init(ObjectClass *klass, void *data)
     k->init = slavio_misc_init1;
     dc->reset = slavio_misc_reset;
     dc->vmsd = &vmstate_misc;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo slavio_misc_info = {
@@ -488,8 +489,10 @@  static const TypeInfo slavio_misc_info = {
 static void apc_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(dc);
 
     k->init = apc_init1;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo apc_info = {
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
index 68a4c0c..595d1f4 100644
--- a/hw/slavio_timer.c
+++ b/hw/slavio_timer.c
@@ -418,6 +418,7 @@  static void slavio_timer_class_init(ObjectClass *klass, void *data)
     dc->reset = slavio_timer_reset;
     dc->vmsd = &vmstate_slavio_timer;
     dc->props = slavio_timer_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo slavio_timer_info = {
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index 67fd074..0e4e2fc 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -773,6 +773,7 @@  static void smc91c111_class_init(ObjectClass *klass, void *data)
     dc->reset = smc91c111_reset;
     dc->vmsd = &vmstate_smc91c111;
     dc->props = smc91c111_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo smc91c111_info = {
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index 6d0df51..26f327d 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -298,6 +298,7 @@  static void sparc32_dma_class_init(ObjectClass *klass, void *data)
     dc->reset = dma_reset;
     dc->vmsd = &vmstate_dma;
     dc->props = sparc32_dma_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo sparc32_dma_info = {
diff --git a/hw/spitz.c b/hw/spitz.c
index 5bc49fc..d338bd6 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -1024,6 +1024,7 @@  static void sl_nand_class_init(ObjectClass *klass, void *data)
     k->init = sl_nand_init;
     dc->vmsd = &vmstate_sl_nand_info;
     dc->props = sl_nand_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo sl_nand_info = {
@@ -1059,6 +1060,7 @@  static void spitz_keyboard_class_init(ObjectClass *klass, void *data)
     k->init = spitz_keyboard_init;
     dc->vmsd = &vmstate_spitz_kbd;
     dc->props = spitz_keyboard_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo spitz_keyboard_info = {
@@ -1088,6 +1090,7 @@  static void corgi_ssp_class_init(ObjectClass *klass, void *data)
     k->init = corgi_ssp_init;
     k->transfer = corgi_ssp_transfer;
     dc->vmsd = &vmstate_corgi_ssp_regs;
+    dc->no_user = 1; /* for gpio */
 }
 
 static const TypeInfo corgi_ssp_info = {
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 9b8f203..0786922 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -1352,8 +1352,10 @@  machine_init(stellaris_machine_init);
 static void stellaris_i2c_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = stellaris_i2c_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo stellaris_i2c_info = {
@@ -1366,8 +1368,10 @@  static const TypeInfo stellaris_i2c_info = {
 static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = stellaris_gptm_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo stellaris_gptm_info = {
@@ -1380,8 +1384,10 @@  static const TypeInfo stellaris_gptm_info = {
 static void stellaris_adc_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = stellaris_adc_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo stellaris_adc_info = {
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index 6c701fb..270862e 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -433,6 +433,7 @@  static void stellaris_enet_class_init(ObjectClass *klass, void *data)
 
     k->init = stellaris_enet_init;
     dc->props = stellaris_enet_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo stellaris_enet_info = {
diff --git a/hw/strongarm.c b/hw/strongarm.c
index ab736e3..ab61dec 100644
--- a/hw/strongarm.c
+++ b/hw/strongarm.c
@@ -210,6 +210,7 @@  static void strongarm_pic_class_init(ObjectClass *klass, void *data)
     k->init = strongarm_pic_initfn;
     dc->desc = "StrongARM PIC";
     dc->vmsd = &vmstate_strongarm_pic_regs;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo strongarm_pic_info = {
@@ -431,6 +432,7 @@  static void strongarm_rtc_sysbus_class_init(ObjectClass *klass, void *data)
     k->init = strongarm_rtc_init;
     dc->desc = "StrongARM RTC Controller";
     dc->vmsd = &vmstate_strongarm_rtc_regs;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo strongarm_rtc_sysbus_info = {
@@ -672,6 +674,7 @@  static void strongarm_gpio_class_init(ObjectClass *klass, void *data)
 
     k->init = strongarm_gpio_initfn;
     dc->desc = "StrongARM GPIO controller";
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo strongarm_gpio_info = {
@@ -838,6 +841,7 @@  static void strongarm_ppc_class_init(ObjectClass *klass, void *data)
 
     k->init = strongarm_ppc_init;
     dc->desc = "StrongARM PPC controller";
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo strongarm_ppc_info = {
@@ -1297,6 +1301,7 @@  static void strongarm_uart_class_init(ObjectClass *klass, void *data)
     dc->reset = strongarm_uart_reset;
     dc->vmsd = &vmstate_strongarm_uart_regs;
     dc->props = strongarm_uart_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo strongarm_uart_info = {
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 9903f44..89dc058 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -629,8 +629,10 @@  static int idreg_init1(SysBusDevice *dev)
 static void idreg_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     k->init = idreg_init1;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo idreg_info = {
@@ -671,8 +673,10 @@  static int afx_init1(SysBusDevice *dev)
 static void afx_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     k->init = afx_init1;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo afx_info = {
@@ -750,6 +754,7 @@  static void prom_class_init(ObjectClass *klass, void *data)
 
     k->init = prom_init1;
     dc->props = prom_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo prom_info = {
@@ -814,6 +819,7 @@  static void ram_class_init(ObjectClass *klass, void *data)
 
     k->init = ram_init1;
     dc->props = ram_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo ram_info = {
diff --git a/hw/sun4m_iommu.c b/hw/sun4m_iommu.c
index 8f9635f..8cbfeb9 100644
--- a/hw/sun4m_iommu.c
+++ b/hw/sun4m_iommu.c
@@ -371,6 +371,7 @@  static void iommu_class_init(ObjectClass *klass, void *data)
     dc->reset = iommu_reset;
     dc->vmsd = &vmstate_iommu;
     dc->props = iommu_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo iommu_info = {
diff --git a/hw/tcx.c b/hw/tcx.c
index 0ce2952..38681b5 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -714,6 +714,7 @@  static void tcx_class_init(ObjectClass *klass, void *data)
     dc->reset = tcx_reset;
     dc->vmsd = &vmstate_tcx;
     dc->props = tcx_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo tcx_info = {
diff --git a/hw/tusb6010.c b/hw/tusb6010.c
index 2c7d033..ac2357c 100644
--- a/hw/tusb6010.c
+++ b/hw/tusb6010.c
@@ -796,6 +796,7 @@  static void tusb6010_class_init(ObjectClass *klass, void *data)
 
     k->init = tusb6010_init;
     dc->reset = tusb6010_reset;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo tusb6010_info = {
diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c
index b68a66a..28f6070 100644
--- a/hw/usb/hcd-ehci-sysbus.c
+++ b/hw/usb/hcd-ehci-sysbus.c
@@ -56,6 +56,7 @@  static void ehci_sysbus_class_init(ObjectClass *klass, void *data)
     k->init = usb_ehci_sysbus_initfn;
     dc->vmsd = &vmstate_ehci_sysbus;
     dc->props = ehci_sysbus_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo ehci_type_info = {
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 51241cd..2408e9e 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -1931,6 +1931,7 @@  static void ohci_sysbus_class_init(ObjectClass *klass, void *data)
     sbc->init = ohci_init_pxa;
     dc->desc = "OHCI USB Controller";
     dc->props = ohci_sysbus_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo ohci_sysbus_info = {
diff --git a/hw/versatile_i2c.c b/hw/versatile_i2c.c
index ad71e9d..a5bbb42 100644
--- a/hw/versatile_i2c.c
+++ b/hw/versatile_i2c.c
@@ -88,8 +88,10 @@  static int versatile_i2c_init(SysBusDevice *dev)
 static void versatile_i2c_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     k->init = versatile_i2c_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo versatile_i2c_info = {
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 9d99159..68a4f1a 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -143,8 +143,10 @@  static const TypeInfo pci_vpb_info = {
 static void pci_realview_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = pci_realview_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo pci_realview_info = {
diff --git a/hw/xgmac.c b/hw/xgmac.c
index 5072298..36c53de 100644
--- a/hw/xgmac.c
+++ b/hw/xgmac.c
@@ -416,6 +416,7 @@  static void xgmac_enet_class_init(ObjectClass *klass, void *data)
     sbc->init = xgmac_enet_init;
     dc->vmsd = &vmstate_xgmac;
     dc->props = xgmac_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo xgmac_enet_info = {
diff --git a/hw/xilinx_axidma.c b/hw/xilinx_axidma.c
index cc51584..35c7776 100644
--- a/hw/xilinx_axidma.c
+++ b/hw/xilinx_axidma.c
@@ -500,6 +500,7 @@  static void axidma_class_init(ObjectClass *klass, void *data)
 
     k->init = xilinx_axidma_init;
     dc->props = axidma_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
     ssc->push = axidma_push;
 }
 
diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c
index e5d9251..862ad08 100644
--- a/hw/xilinx_axienet.c
+++ b/hw/xilinx_axienet.c
@@ -892,6 +892,7 @@  static void xilinx_enet_class_init(ObjectClass *klass, void *data)
 
     k->init = xilinx_enet_init;
     dc->props = xilinx_enet_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
     ssc->push = axienet_stream_push;
 }
 
diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c
index 21c6f8c..d987d66 100644
--- a/hw/xilinx_ethlite.c
+++ b/hw/xilinx_ethlite.c
@@ -246,6 +246,7 @@  static void xilinx_ethlite_class_init(ObjectClass *klass, void *data)
 
     k->init = xilinx_ethlite_init;
     dc->props = xilinx_ethlite_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo xilinx_ethlite_info = {
diff --git a/hw/xilinx_intc.c b/hw/xilinx_intc.c
index 0c34149..9b8caad 100644
--- a/hw/xilinx_intc.c
+++ b/hw/xilinx_intc.c
@@ -173,6 +173,7 @@  static void xilinx_intc_class_init(ObjectClass *klass, void *data)
 
     k->init = xilinx_intc_init;
     dc->props = xilinx_intc_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo xilinx_intc_info = {
diff --git a/hw/xilinx_spi.c b/hw/xilinx_spi.c
index be581c2..785e858 100644
--- a/hw/xilinx_spi.c
+++ b/hw/xilinx_spi.c
@@ -368,6 +368,7 @@  static void xilinx_spi_class_init(ObjectClass *klass, void *data)
     dc->reset = xlx_spi_reset;
     dc->props = xilinx_spi_properties;
     dc->vmsd = &vmstate_xilinx_spi;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo xilinx_spi_info = {
diff --git a/hw/xilinx_spips.c b/hw/xilinx_spips.c
index 42e019d..91c496a 100644
--- a/hw/xilinx_spips.c
+++ b/hw/xilinx_spips.c
@@ -558,6 +558,7 @@  static void xilinx_spips_class_init(ObjectClass *klass, void *data)
     dc->reset = xilinx_spips_reset;
     dc->props = xilinx_spips_properties;
     dc->vmsd = &vmstate_xilinx_spips;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo xilinx_spips_info = {
diff --git a/hw/xilinx_timer.c b/hw/xilinx_timer.c
index aa162ef..3b614a6 100644
--- a/hw/xilinx_timer.c
+++ b/hw/xilinx_timer.c
@@ -238,6 +238,7 @@  static void xilinx_timer_class_init(ObjectClass *klass, void *data)
 
     k->init = xilinx_timer_init;
     dc->props = xilinx_timer_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo xilinx_timer_info = {
diff --git a/hw/xilinx_uartlite.c b/hw/xilinx_uartlite.c
index 9963982..e55212a 100644
--- a/hw/xilinx_uartlite.c
+++ b/hw/xilinx_uartlite.c
@@ -212,8 +212,10 @@  static int xilinx_uartlite_init(SysBusDevice *dev)
 static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
 {
     SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
     sdc->init = xilinx_uartlite_init;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo xilinx_uartlite_info = {
diff --git a/hw/zaurus.c b/hw/zaurus.c
index 2defe3b..b53f4c4 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -234,6 +234,7 @@  static void scoop_sysbus_class_init(ObjectClass *klass, void *data)
     dc->desc = "Scoop2 Sharp custom ASIC";
     dc->vmsd = &vmstate_scoop_regs;
     dc->props = scoop_sysbus_properties;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo scoop_sysbus_info = {
diff --git a/hw/zynq_slcr.c b/hw/zynq_slcr.c
index 27b00f0..7b80c48 100644
--- a/hw/zynq_slcr.c
+++ b/hw/zynq_slcr.c
@@ -519,6 +519,7 @@  static void zynq_slcr_class_init(ObjectClass *klass, void *data)
     sdc->init = zynq_slcr_init;
     dc->vmsd = &vmstate_zynq_slcr;
     dc->reset = zynq_slcr_reset;
+    dc->no_user = 1; /* for sysbus mmio/irq */
 }
 
 static const TypeInfo zynq_slcr_info = {