If the board code overlaps the (currently only byte-wide) data I/O port with the high byte of the selector I/O port, we install the "comb_iomem" MemoryRegion.
Generalize the check to see if *any* byte of the data I/O port overlaps with the high byte of the selector I/O port. If that's the case: - If the data I/O port is just one byte wide, then keep the current behavior. - Otherwise, reject the combination: qemu-system-target: only a byte-wide data I/O port can be combined qemu-system-target: Initialization of device fw_cfg failed The patch doesn't immediately change behavior, because: - fw_cfg_data_mem_ops.valid.max_access_size == 1 - ctl_io_last == s->ctl_iobase + 1 - data_io_end == s->data_iobase + 1 - The condition ctl_io_last >= s->data_iobase && ctl_io_last < data_io_end is equivalent to ctl_io_last >= s->data_iobase && ctl_io_last < s->data_iobase + 1 after substituting "data_io_end". Further, the second relation can be rewritten as ctl_io_last >= s->data_iobase && ctl_io_last <= s->data_iobase which gives ctl_io_last == s->data_iobase After substituting "ctl_io_last", we get s->ctl_iobase + 1 == s->data_iobase Signed-off-by: Laszlo Ersek <ler...@redhat.com> --- Notes: v4: - new in v4 [Peter] hw/nvram/fw_cfg.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 7f6031c..eb0ad83 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -620,11 +620,24 @@ static void fw_cfg_initfn(Object *obj) static void fw_cfg_realize(DeviceState *dev, Error **errp) { FWCfgState *s = FW_CFG(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + uint32_t ctl_io_last; + uint32_t data_io_end; - if (s->ctl_iobase + 1 == s->data_iobase) { - sysbus_add_io(sbd, s->ctl_iobase, &s->comb_iomem); + if (s->ctl_iobase == 0 && s->data_iobase == 0) { + return; + } + + ctl_io_last = s->ctl_iobase + FW_CFG_SIZE - 1; + data_io_end = s->data_iobase + fw_cfg_data_mem_ops.valid.max_access_size; + if (ctl_io_last >= s->data_iobase && ctl_io_last < data_io_end) { + if (fw_cfg_data_mem_ops.valid.max_access_size == 1) { + sysbus_add_io(sbd, s->ctl_iobase, &s->comb_iomem); + } else { + error_setg(errp, "only a byte-wide data I/O port can be combined"); + return; + } } else { if (s->ctl_iobase) { sysbus_add_io(sbd, s->ctl_iobase, &s->ctl_iomem); } -- 1.8.3.1