qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v4 2/8] fw_cfg: generalize overlap check for combini


From: Laszlo Ersek
Subject: [Qemu-devel] [PATCH v4 2/8] fw_cfg: generalize overlap check for combining control and data I/O ports
Date: Fri, 12 Dec 2014 16:58:46 +0100

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 <address@hidden>
---

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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]