From: Laszlo Ersek <lersek@redhat.com>
To: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>,
qemu-devel@nongnu.org, imammedo@redhat.com, somlo@cmu.edu,
ehabkost@redhat.com, mst@redhat.com, pbonzini@redhat.com,
rjones@redhat.com, peter.maydell@linaro.org
Subject: Re: [Qemu-devel] [PATCHv2 1/4] fw_cfg: don't map the fw_cfg IO ports in fw_cfg_io_realize()
Date: Tue, 13 Jun 2017 00:27:29 +0200 [thread overview]
Message-ID: <8028308f-9aac-abb6-25df-599d32d4d0ce@redhat.com> (raw)
In-Reply-To: <1497302470-10776-2-git-send-email-mark.cave-ayland@ilande.co.uk>
On 06/12/17 23:21, Mark Cave-Ayland wrote:
> As indicated by Laszlo it is a QOM bug for the realize() method to actually
> map the device. Set up the IO regions with sysbus_init_mmio() and defer
> the mapping to the caller, as already done in fw_cfg_init_mem_wide().
>
> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
> ---
> hw/nvram/fw_cfg.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> index 316fca9..be5b04e 100644
> --- a/hw/nvram/fw_cfg.c
> +++ b/hw/nvram/fw_cfg.c
> @@ -936,6 +936,7 @@ FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase,
> AddressSpace *dma_as)
> {
> DeviceState *dev;
> + SysBusDevice *sbd;
> FWCfgState *s;
> uint32_t version = FW_CFG_VERSION;
> bool dma_requested = dma_iobase && dma_as;
> @@ -948,12 +949,17 @@ FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase,
> }
>
> fw_cfg_init1(dev);
> +
> + sbd = SYS_BUS_DEVICE(dev);
> + sysbus_add_io(sbd, iobase, sysbus_mmio_get_region(sbd, 0));
> +
> s = FW_CFG(dev);
>
> if (s->dma_enabled) {
> /* 64 bits for the address field */
> s->dma_as = dma_as;
> s->dma_addr = 0;
> + sysbus_add_io(sbd, dma_iobase, sysbus_mmio_get_region(sbd, 1));
>
> version |= FW_CFG_VERSION_DMA;
> }
> @@ -1085,13 +1091,13 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
> * of the i/o region used is FW_CFG_CTL_SIZE */
> memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops,
> FW_CFG(s), "fwcfg", FW_CFG_CTL_SIZE);
> - sysbus_add_io(sbd, s->iobase, &s->comb_iomem);
> + sysbus_init_mmio(sbd, &s->comb_iomem);
>
> if (FW_CFG(s)->dma_enabled) {
> memory_region_init_io(&FW_CFG(s)->dma_iomem, OBJECT(s),
> &fw_cfg_dma_mem_ops, FW_CFG(s), "fwcfg.dma",
> sizeof(dma_addr_t));
> - sysbus_add_io(sbd, s->dma_iobase, &FW_CFG(s)->dma_iomem);
> + sysbus_init_mmio(sbd, &FW_CFG(s)->dma_iomem);
> }
> }
>
>
This does mostly what I had in mind, but why are the sysbus_init_mmio()
"replacements" necessary?
This is what sysbus_init_mmio() does:
assert(dev->num_mmio < QDEV_MAX_MMIO);
n = dev->num_mmio++;
dev->mmio[n].addr = -1;
dev->mmio[n].memory = memory;
But we don't have MMIO regions here, we have IO ports. This is all what
sysbus_add_io() does:
memory_region_add_subregion(get_system_io(), addr, mem);
It doesn't do anything related to SysBusDevice.mmio[] and mmio.num_mmio.
This patch, as written, changes "num_mmio" from zero to nonzero, and
that could have a bunch of unexpected consequences for
"hw/core/sysbus.c":
- sysbus_has_mmio() would return true
- sysbus_dev_print() produces different output
- sysbus_get_fw_dev_path() formats a different OpenFW device path
fragment
Instead, can we just move the sysbus_add_io() function calls *without*
replacements in fw_cfg_io_realize()?
In fw_cfg_init_io_dma(), you know the object type exactly -- you just
created it with TYPE_FW_CFG_IO --, so after device realization, you can
cast the type as narrowly as necessary, and refer to the fields by name.
Something like (build-tested only):
> diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
> index 316fca9bc1da..a28ce1eacd63 100644
> --- a/hw/nvram/fw_cfg.c
> +++ b/hw/nvram/fw_cfg.c
> @@ -96,7 +96,6 @@ struct FWCfgIoState {
> /*< public >*/
>
> MemoryRegion comb_iomem;
> - uint32_t iobase, dma_iobase;
> };
>
> struct FWCfgMemState {
> @@ -936,24 +935,29 @@ FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase,
> AddressSpace *dma_as)
> {
> DeviceState *dev;
> + SysBusDevice *sbd;
> FWCfgState *s;
> + FWCfgIoState *ios;
> uint32_t version = FW_CFG_VERSION;
> bool dma_requested = dma_iobase && dma_as;
>
> dev = qdev_create(NULL, TYPE_FW_CFG_IO);
> - qdev_prop_set_uint32(dev, "iobase", iobase);
> - qdev_prop_set_uint32(dev, "dma_iobase", dma_iobase);
> if (!dma_requested) {
> qdev_prop_set_bit(dev, "dma_enabled", false);
> }
>
> fw_cfg_init1(dev);
> + sbd = SYS_BUS_DEVICE(dev);
> s = FW_CFG(dev);
> + ios = FW_CFG_IO(dev);
> +
> + sysbus_add_io(sbd, iobase, &ios->comb_iomem);
>
> if (s->dma_enabled) {
> /* 64 bits for the address field */
> s->dma_as = dma_as;
> s->dma_addr = 0;
> + sysbus_add_io(sbd, dma_iobase, &s->dma_iomem);
>
> version |= FW_CFG_VERSION_DMA;
> }
> @@ -1059,8 +1063,6 @@ static void fw_cfg_file_slots_allocate(FWCfgState *s, Error **errp)
> }
>
> static Property fw_cfg_io_properties[] = {
> - DEFINE_PROP_UINT32("iobase", FWCfgIoState, iobase, -1),
> - DEFINE_PROP_UINT32("dma_iobase", FWCfgIoState, dma_iobase, -1),
> DEFINE_PROP_BOOL("dma_enabled", FWCfgIoState, parent_obj.dma_enabled,
> true),
> DEFINE_PROP_UINT16("x-file-slots", FWCfgIoState, parent_obj.file_slots,
> @@ -1071,7 +1073,6 @@ static Property fw_cfg_io_properties[] = {
> static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
> {
> FWCfgIoState *s = FW_CFG_IO(dev);
> - SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> Error *local_err = NULL;
>
> fw_cfg_file_slots_allocate(FW_CFG(s), &local_err);
> @@ -1085,13 +1086,11 @@ static void fw_cfg_io_realize(DeviceState *dev, Error **errp)
> * of the i/o region used is FW_CFG_CTL_SIZE */
> memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops,
> FW_CFG(s), "fwcfg", FW_CFG_CTL_SIZE);
> - sysbus_add_io(sbd, s->iobase, &s->comb_iomem);
>
> if (FW_CFG(s)->dma_enabled) {
> memory_region_init_io(&FW_CFG(s)->dma_iomem, OBJECT(s),
> &fw_cfg_dma_mem_ops, FW_CFG(s), "fwcfg.dma",
> sizeof(dma_addr_t));
> - sysbus_add_io(sbd, s->dma_iobase, &FW_CFG(s)->dma_iomem);
> }
> }
>
It turns out that we introduced the "iobase" and "dma_iobase" properties
*solely* so that we could pass arguments to fw_cfg_io_realize(). But
fw_cfg_io_realize() only needed those parameters for the *wrong* purpose
(namely calling sysbus_add_io()). By eliminating the sysbus_add_io()
calls from fw_cfg_io_realize(), the related properties become
unnecessary too.
(NB, setting the "dma_enabled" property in fw_cfg_init_io_dma(), and
setting "data_width" and "dma_enabled" in fw_cfg_init_mem_wide(), remain
necessary, because those aren't related to region mapping.)
What do you think?
Thanks!
Laszlo
next prev parent reply other threads:[~2017-06-12 22:27 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-12 21:21 [Qemu-devel] [PATCHv2 0/4] fw_cfg: qdev-related tidy-ups Mark Cave-Ayland
2017-06-12 21:21 ` [Qemu-devel] [PATCHv2 1/4] fw_cfg: don't map the fw_cfg IO ports in fw_cfg_io_realize() Mark Cave-Ayland
2017-06-12 22:27 ` Laszlo Ersek [this message]
2017-06-12 23:12 ` Laszlo Ersek
2017-06-13 18:27 ` Mark Cave-Ayland
2017-06-14 12:34 ` Paolo Bonzini
2017-06-12 21:21 ` [Qemu-devel] [PATCHv2 2/4] fw_cfg: move setting of FW_CFG_VERSION_DMA bit to fw_cfg_init1() Mark Cave-Ayland
2017-06-12 22:31 ` Laszlo Ersek
2017-06-12 21:21 ` [Qemu-devel] [PATCHv2 3/4] fw_cfg: move qdev_init_nofail() from fw_cfg_init1() to callers Mark Cave-Ayland
2017-06-12 22:50 ` Laszlo Ersek
2017-06-16 9:52 ` Mark Cave-Ayland
2017-06-12 21:21 ` [Qemu-devel] [PATCHv2 4/4] fw_cfg: move QOM type defines into fw_cfg.h Mark Cave-Ayland
2017-06-12 22:52 ` Laszlo Ersek
2017-06-14 12:38 ` [Qemu-devel] [PATCHv2 0/4] fw_cfg: qdev-related tidy-ups Paolo Bonzini
2017-06-16 10:02 ` Mark Cave-Ayland
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8028308f-9aac-abb6-25df-599d32d4d0ce@redhat.com \
--to=lersek@redhat.com \
--cc=ehabkost@redhat.com \
--cc=imammedo@redhat.com \
--cc=mark.cave-ayland@ilande.co.uk \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=rjones@redhat.com \
--cc=somlo@cmu.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).