All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/23] Memory API, batch 1
@ 2011-07-25 14:02 ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

This patchset contains the core of the memory API, with one device
(usb-ohci) coverted for reference.  The API is currently implemented on
top of the old ram_addr_t/cpu_register_physical_memory() API, but the plan
is to make it standalone later.

The goals of the API are:
 - correctness: by modelling the memory hierarchy, things like the 440FX PAM
   registers and movable, overlapping PCI BARs can be modelled accurately.
 - efficiency: by maintaining an object tree describing guest memory, we
   can eventually get rid of the page descriptor array
 - security: by having more information available declaratively, we reduce
   coding errors that may be exploited by malicious guests

Also available from

  git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git
     refs/tags/memory-region-batch-1

Avi Kivity (23):
  Hierarchical memory region API
  memory: implement dirty tracking
  memory: merge adjacent segments of a single memory region
  Internal interfaces for memory API
  memory: abstract address space operations
  memory: rename MemoryRegion::has_ram_addr to ::terminates
  memory: late initialization of ram_addr
  memory:  I/O address space support
  memory: add backward compatibility for old portio registration
  memory: add backward compatibility for old mmio registration
  memory: add ioeventfd support
  memory: separate building the final memory map into two steps
  memory: document the memory API
  memory: transaction API
  exec.c: initialize memory map
  ioport: register ranges by byte aligned addresses always
  pc: grab system_memory
  pc: convert pc_memory_init() to memory API
  pc: move global memory map out of pc_init1() and into its callers
  pci: pass address space to pci bus when created
  pci: add MemoryRegion based BAR management API
  sysbus: add MemoryRegion based memory management API
  usb-ohci: convert to MemoryRegion

 Makefile.target    |    1 +
 docs/memory.txt    |  172 ++++++++
 exec-memory.h      |   26 ++
 exec.c             |   19 +
 hw/apb_pci.c       |    2 +
 hw/bonito.c        |    4 +-
 hw/grackle_pci.c   |    5 +-
 hw/gt64xxx.c       |    4 +-
 hw/pc.c            |   62 ++-
 hw/pc.h            |    9 +-
 hw/pc_piix.c       |   20 +-
 hw/pci.c           |   63 +++-
 hw/pci.h           |   15 +-
 hw/pci_host.h      |    1 +
 hw/pci_internals.h |    1 +
 hw/piix_pci.c      |   13 +-
 hw/ppc4xx_pci.c    |    5 +-
 hw/ppc_mac.h       |    9 +-
 hw/ppc_newworld.c  |    5 +-
 hw/ppc_oldworld.c  |    3 +-
 hw/ppc_prep.c      |    3 +-
 hw/ppce500_pci.c   |    6 +-
 hw/prep_pci.c      |    5 +-
 hw/prep_pci.h      |    3 +-
 hw/sh_pci.c        |    4 +-
 hw/sysbus.c        |   27 ++-
 hw/sysbus.h        |    3 +
 hw/unin_pci.c      |   10 +-
 hw/usb-ohci.c      |   42 +--
 hw/versatile_pci.c |    2 +
 ioport.c           |    4 +-
 memory.c           | 1144 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory.h           |  259 ++++++++++++
 33 files changed, 1852 insertions(+), 99 deletions(-)
 create mode 100644 docs/memory.txt
 create mode 100644 exec-memory.h
 create mode 100644 memory.c
 create mode 100644 memory.h

-- 
1.7.5.3

^ permalink raw reply	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 00/23] Memory API, batch 1
@ 2011-07-25 14:02 ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

This patchset contains the core of the memory API, with one device
(usb-ohci) coverted for reference.  The API is currently implemented on
top of the old ram_addr_t/cpu_register_physical_memory() API, but the plan
is to make it standalone later.

The goals of the API are:
 - correctness: by modelling the memory hierarchy, things like the 440FX PAM
   registers and movable, overlapping PCI BARs can be modelled accurately.
 - efficiency: by maintaining an object tree describing guest memory, we
   can eventually get rid of the page descriptor array
 - security: by having more information available declaratively, we reduce
   coding errors that may be exploited by malicious guests

Also available from

  git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git
     refs/tags/memory-region-batch-1

Avi Kivity (23):
  Hierarchical memory region API
  memory: implement dirty tracking
  memory: merge adjacent segments of a single memory region
  Internal interfaces for memory API
  memory: abstract address space operations
  memory: rename MemoryRegion::has_ram_addr to ::terminates
  memory: late initialization of ram_addr
  memory:  I/O address space support
  memory: add backward compatibility for old portio registration
  memory: add backward compatibility for old mmio registration
  memory: add ioeventfd support
  memory: separate building the final memory map into two steps
  memory: document the memory API
  memory: transaction API
  exec.c: initialize memory map
  ioport: register ranges by byte aligned addresses always
  pc: grab system_memory
  pc: convert pc_memory_init() to memory API
  pc: move global memory map out of pc_init1() and into its callers
  pci: pass address space to pci bus when created
  pci: add MemoryRegion based BAR management API
  sysbus: add MemoryRegion based memory management API
  usb-ohci: convert to MemoryRegion

 Makefile.target    |    1 +
 docs/memory.txt    |  172 ++++++++
 exec-memory.h      |   26 ++
 exec.c             |   19 +
 hw/apb_pci.c       |    2 +
 hw/bonito.c        |    4 +-
 hw/grackle_pci.c   |    5 +-
 hw/gt64xxx.c       |    4 +-
 hw/pc.c            |   62 ++-
 hw/pc.h            |    9 +-
 hw/pc_piix.c       |   20 +-
 hw/pci.c           |   63 +++-
 hw/pci.h           |   15 +-
 hw/pci_host.h      |    1 +
 hw/pci_internals.h |    1 +
 hw/piix_pci.c      |   13 +-
 hw/ppc4xx_pci.c    |    5 +-
 hw/ppc_mac.h       |    9 +-
 hw/ppc_newworld.c  |    5 +-
 hw/ppc_oldworld.c  |    3 +-
 hw/ppc_prep.c      |    3 +-
 hw/ppce500_pci.c   |    6 +-
 hw/prep_pci.c      |    5 +-
 hw/prep_pci.h      |    3 +-
 hw/sh_pci.c        |    4 +-
 hw/sysbus.c        |   27 ++-
 hw/sysbus.h        |    3 +
 hw/unin_pci.c      |   10 +-
 hw/usb-ohci.c      |   42 +--
 hw/versatile_pci.c |    2 +
 ioport.c           |    4 +-
 memory.c           | 1144 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory.h           |  259 ++++++++++++
 33 files changed, 1852 insertions(+), 99 deletions(-)
 create mode 100644 docs/memory.txt
 create mode 100644 exec-memory.h
 create mode 100644 memory.c
 create mode 100644 memory.h

-- 
1.7.5.3

^ permalink raw reply	[flat|nested] 100+ messages in thread

* [PATCH 01/23] Hierarchical memory region API
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

The memory API separates the attributes of a memory region (its size, how
reads or writes are handled, dirty logging, and coalescing) from where it
is mapped and whether it is enabled.  This allows a device to configure
a memory region once, then hand it off to its parent bus to map it according
to the bus configuration.

Hierarchical registration also allows a device to compose a region out of
a number of sub-regions with different properties; for example some may be
RAM while others may be MMIO.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 Makefile.target |    1 +
 memory.c        |  655 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory.h        |  200 +++++++++++++++++
 3 files changed, 856 insertions(+), 0 deletions(-)
 create mode 100644 memory.c
 create mode 100644 memory.h

diff --git a/Makefile.target b/Makefile.target
index cde509b..8884a56 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -198,6 +198,7 @@ obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
+obj-y += memory.o
 LIBS+=-lz
 
 QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
diff --git a/memory.c b/memory.c
new file mode 100644
index 0000000..10591bf
--- /dev/null
+++ b/memory.c
@@ -0,0 +1,655 @@
+/*
+ * Physical memory management
+ *
+ * Copyright 2011 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *  Avi Kivity <avi@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "memory.h"
+#include <assert.h>
+
+typedef struct AddrRange AddrRange;
+
+struct AddrRange {
+    uint64_t start;
+    uint64_t size;
+};
+
+static AddrRange addrrange_make(uint64_t start, uint64_t size)
+{
+    return (AddrRange) { start, size };
+}
+
+static bool addrrange_equal(AddrRange r1, AddrRange r2)
+{
+    return r1.start == r2.start && r1.size == r2.size;
+}
+
+static uint64_t addrrange_end(AddrRange r)
+{
+    return r.start + r.size;
+}
+
+static AddrRange addrrange_shift(AddrRange range, int64_t delta)
+{
+    range.start += delta;
+    return range;
+}
+
+static bool addrrange_intersects(AddrRange r1, AddrRange r2)
+{
+    return (r1.start >= r2.start && r1.start < r2.start + r2.size)
+        || (r2.start >= r1.start && r2.start < r1.start + r1.size);
+}
+
+static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
+{
+    uint64_t start = MAX(r1.start, r2.start);
+    /* off-by-one arithmetic to prevent overflow */
+    uint64_t end = MIN(addrrange_end(r1) - 1, addrrange_end(r2) - 1);
+    return addrrange_make(start, end - start + 1);
+}
+
+struct CoalescedMemoryRange {
+    AddrRange addr;
+    QTAILQ_ENTRY(CoalescedMemoryRange) link;
+};
+
+typedef struct FlatRange FlatRange;
+typedef struct FlatView FlatView;
+
+/* Range of memory in the global map.  Addresses are absolute. */
+struct FlatRange {
+    MemoryRegion *mr;
+    target_phys_addr_t offset_in_region;
+    AddrRange addr;
+};
+
+/* Flattened global view of current active memory hierarchy.  Kept in sorted
+ * order.
+ */
+struct FlatView {
+    FlatRange *ranges;
+    unsigned nr;
+    unsigned nr_allocated;
+};
+
+#define FOR_EACH_FLAT_RANGE(var, view)          \
+    for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
+
+static FlatView current_memory_map;
+static MemoryRegion *root_memory_region;
+
+static bool flatrange_equal(FlatRange *a, FlatRange *b)
+{
+    return a->mr == b->mr
+        && addrrange_equal(a->addr, b->addr)
+        && a->offset_in_region == b->offset_in_region;
+}
+
+static void flatview_init(FlatView *view)
+{
+    view->ranges = NULL;
+    view->nr = 0;
+    view->nr_allocated = 0;
+}
+
+/* Insert a range into a given position.  Caller is responsible for maintaining
+ * sorting order.
+ */
+static void flatview_insert(FlatView *view, unsigned pos, FlatRange *range)
+{
+    if (view->nr == view->nr_allocated) {
+        view->nr_allocated = MAX(2 * view->nr, 10);
+        view->ranges = qemu_realloc(view->ranges,
+                                    view->nr_allocated * sizeof(*view->ranges));
+    }
+    memmove(view->ranges + pos + 1, view->ranges + pos,
+            (view->nr - pos) * sizeof(FlatRange));
+    view->ranges[pos] = *range;
+    ++view->nr;
+}
+
+static void flatview_destroy(FlatView *view)
+{
+    qemu_free(view->ranges);
+}
+
+/* Render a memory region into the global view.  Ranges in @view obscure
+ * ranges in @mr.
+ */
+static void render_memory_region(FlatView *view,
+                                 MemoryRegion *mr,
+                                 target_phys_addr_t base,
+                                 AddrRange clip)
+{
+    MemoryRegion *subregion;
+    unsigned i;
+    target_phys_addr_t offset_in_region;
+    uint64_t remain;
+    uint64_t now;
+    FlatRange fr;
+    AddrRange tmp;
+
+    base += mr->addr;
+
+    tmp = addrrange_make(base, mr->size);
+
+    if (!addrrange_intersects(tmp, clip)) {
+        return;
+    }
+
+    clip = addrrange_intersection(tmp, clip);
+
+    if (mr->alias) {
+        base -= mr->alias->addr;
+        base -= mr->alias_offset;
+        render_memory_region(view, mr->alias, base, clip);
+        return;
+    }
+
+    /* Render subregions in priority order. */
+    QTAILQ_FOREACH(subregion, &mr->subregions, subregions_link) {
+        render_memory_region(view, subregion, base, clip);
+    }
+
+    if (!mr->has_ram_addr) {
+        return;
+    }
+
+    offset_in_region = clip.start - base;
+    base = clip.start;
+    remain = clip.size;
+
+    /* Render the region itself into any gaps left by the current view. */
+    for (i = 0; i < view->nr && remain; ++i) {
+        if (base >= addrrange_end(view->ranges[i].addr)) {
+            continue;
+        }
+        if (base < view->ranges[i].addr.start) {
+            now = MIN(remain, view->ranges[i].addr.start - base);
+            fr.mr = mr;
+            fr.offset_in_region = offset_in_region;
+            fr.addr = addrrange_make(base, now);
+            flatview_insert(view, i, &fr);
+            ++i;
+            base += now;
+            offset_in_region += now;
+            remain -= now;
+        }
+        if (base == view->ranges[i].addr.start) {
+            now = MIN(remain, view->ranges[i].addr.size);
+            base += now;
+            offset_in_region += now;
+            remain -= now;
+        }
+    }
+    if (remain) {
+        fr.mr = mr;
+        fr.offset_in_region = offset_in_region;
+        fr.addr = addrrange_make(base, remain);
+        flatview_insert(view, i, &fr);
+    }
+}
+
+/* Render a memory topology into a list of disjoint absolute ranges. */
+static FlatView generate_memory_topology(MemoryRegion *mr)
+{
+    FlatView view;
+
+    flatview_init(&view);
+
+    render_memory_region(&view, mr, 0, addrrange_make(0, UINT64_MAX));
+
+    return view;
+}
+
+static void memory_region_update_topology(void)
+{
+    FlatView old_view = current_memory_map;
+    FlatView new_view = generate_memory_topology(root_memory_region);
+    unsigned iold, inew;
+    FlatRange *frold, *frnew;
+    ram_addr_t phys_offset, region_offset;
+
+    /* Generate a symmetric difference of the old and new memory maps.
+     * Kill ranges in the old map, and instantiate ranges in the new map.
+     */
+    iold = inew = 0;
+    while (iold < old_view.nr || inew < new_view.nr) {
+        if (iold < old_view.nr) {
+            frold = &old_view.ranges[iold];
+        } else {
+            frold = NULL;
+        }
+        if (inew < new_view.nr) {
+            frnew = &new_view.ranges[inew];
+        } else {
+            frnew = NULL;
+        }
+
+        if (frold
+            && (!frnew
+                || frold->addr.start < frnew->addr.start
+                || (frold->addr.start == frnew->addr.start
+                    && !flatrange_equal(frold, frnew)))) {
+            /* In old, but (not in new, or in new but attributes changed). */
+
+            cpu_register_physical_memory(frold->addr.start, frold->addr.size,
+                                         IO_MEM_UNASSIGNED);
+            ++iold;
+        } else if (frold && frnew && flatrange_equal(frold, frnew)) {
+            /* In both (logging may have changed) */
+
+            ++iold;
+            ++inew;
+            /* FIXME: dirty logging */
+        } else {
+            /* In new */
+
+            phys_offset = frnew->mr->ram_addr;
+            region_offset = frnew->offset_in_region;
+            /* cpu_register_physical_memory_log() wants region_offset for
+             * mmio, but prefers offseting phys_offset for RAM.  Humour it.
+             */
+            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
+                phys_offset += region_offset;
+                region_offset = 0;
+            }
+
+            cpu_register_physical_memory_log(frnew->addr.start,
+                                             frnew->addr.size,
+                                             phys_offset,
+                                             region_offset,
+                                             0);
+            ++inew;
+        }
+    }
+    current_memory_map = new_view;
+    flatview_destroy(&old_view);
+}
+
+void memory_region_init(MemoryRegion *mr,
+                        const char *name,
+                        uint64_t size)
+{
+    mr->ops = NULL;
+    mr->parent = NULL;
+    mr->size = size;
+    mr->addr = 0;
+    mr->offset = 0;
+    mr->has_ram_addr = false;
+    mr->priority = 0;
+    mr->may_overlap = false;
+    mr->alias = NULL;
+    QTAILQ_INIT(&mr->subregions);
+    memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
+    QTAILQ_INIT(&mr->coalesced);
+    mr->name = qemu_strdup(name);
+}
+
+static bool memory_region_access_valid(MemoryRegion *mr,
+                                       target_phys_addr_t addr,
+                                       unsigned size)
+{
+    if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
+        return false;
+    }
+
+    /* Treat zero as compatibility all valid */
+    if (!mr->ops->valid.max_access_size) {
+        return true;
+    }
+
+    if (size > mr->ops->valid.max_access_size
+        || size < mr->ops->valid.min_access_size) {
+        return false;
+    }
+    return true;
+}
+
+static uint32_t memory_region_read_thunk_n(void *_mr,
+                                           target_phys_addr_t addr,
+                                           unsigned size)
+{
+    MemoryRegion *mr = _mr;
+    unsigned access_size, access_size_min, access_size_max;
+    uint64_t access_mask;
+    uint32_t data = 0, tmp;
+    unsigned i;
+
+    if (!memory_region_access_valid(mr, addr, size)) {
+        return -1U; /* FIXME: better signalling */
+    }
+
+    /* FIXME: support unaligned access */
+
+    access_size_min = mr->ops->impl.min_access_size;
+    if (!access_size_min) {
+        access_size_min = 1;
+    }
+    access_size_max = mr->ops->impl.max_access_size;
+    if (!access_size_max) {
+        access_size_max = 4;
+    }
+    access_size = MAX(MIN(size, access_size_max), access_size_min);
+    access_mask = -1ULL >> (64 - access_size * 8);
+    addr += mr->offset;
+    for (i = 0; i < size; i += access_size) {
+        /* FIXME: big-endian support */
+        tmp = mr->ops->read(mr->opaque, addr + i, access_size);
+        data |= (tmp & access_mask) << (i * 8);
+    }
+
+    return data;
+}
+
+static void memory_region_write_thunk_n(void *_mr,
+                                        target_phys_addr_t addr,
+                                        unsigned size,
+                                        uint64_t data)
+{
+    MemoryRegion *mr = _mr;
+    unsigned access_size, access_size_min, access_size_max;
+    uint64_t access_mask;
+    unsigned i;
+
+    if (!memory_region_access_valid(mr, addr, size)) {
+        return; /* FIXME: better signalling */
+    }
+
+    /* FIXME: support unaligned access */
+
+    access_size_min = mr->ops->impl.min_access_size;
+    if (!access_size_min) {
+        access_size_min = 1;
+    }
+    access_size_max = mr->ops->impl.max_access_size;
+    if (!access_size_max) {
+        access_size_max = 4;
+    }
+    access_size = MAX(MIN(size, access_size_max), access_size_min);
+    access_mask = -1ULL >> (64 - access_size * 8);
+    addr += mr->offset;
+    for (i = 0; i < size; i += access_size) {
+        /* FIXME: big-endian support */
+        mr->ops->write(mr->opaque, addr + i, (data >> (i * 8)) & access_mask,
+                       access_size);
+    }
+}
+
+static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr)
+{
+    return memory_region_read_thunk_n(mr, addr, 1);
+}
+
+static uint32_t memory_region_read_thunk_w(void *mr, target_phys_addr_t addr)
+{
+    return memory_region_read_thunk_n(mr, addr, 2);
+}
+
+static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr)
+{
+    return memory_region_read_thunk_n(mr, addr, 4);
+}
+
+static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
+                                        uint32_t data)
+{
+    memory_region_write_thunk_n(mr, addr, 1, data);
+}
+
+static void memory_region_write_thunk_w(void *mr, target_phys_addr_t addr,
+                                        uint32_t data)
+{
+    memory_region_write_thunk_n(mr, addr, 2, data);
+}
+
+static void memory_region_write_thunk_l(void *mr, target_phys_addr_t addr,
+                                        uint32_t data)
+{
+    memory_region_write_thunk_n(mr, addr, 4, data);
+}
+
+static CPUReadMemoryFunc * const memory_region_read_thunk[] = {
+    memory_region_read_thunk_b,
+    memory_region_read_thunk_w,
+    memory_region_read_thunk_l,
+};
+
+static CPUWriteMemoryFunc * const memory_region_write_thunk[] = {
+    memory_region_write_thunk_b,
+    memory_region_write_thunk_w,
+    memory_region_write_thunk_l,
+};
+
+void memory_region_init_io(MemoryRegion *mr,
+                           const MemoryRegionOps *ops,
+                           void *opaque,
+                           const char *name,
+                           uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->ops = ops;
+    mr->opaque = opaque;
+    mr->has_ram_addr = true;
+    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
+                                          memory_region_write_thunk,
+                                          mr,
+                                          mr->ops->endianness);
+}
+
+void memory_region_init_ram(MemoryRegion *mr,
+                            DeviceState *dev,
+                            const char *name,
+                            uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->has_ram_addr = true;
+    mr->ram_addr = qemu_ram_alloc(dev, name, size);
+}
+
+void memory_region_init_ram_ptr(MemoryRegion *mr,
+                                DeviceState *dev,
+                                const char *name,
+                                uint64_t size,
+                                void *ptr)
+{
+    memory_region_init(mr, name, size);
+    mr->has_ram_addr = true;
+    mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
+}
+
+void memory_region_init_alias(MemoryRegion *mr,
+                              const char *name,
+                              MemoryRegion *orig,
+                              target_phys_addr_t offset,
+                              uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->alias = orig;
+    mr->alias_offset = offset;
+}
+
+void memory_region_destroy(MemoryRegion *mr)
+{
+    assert(QTAILQ_EMPTY(&mr->subregions));
+    memory_region_clear_coalescing(mr);
+    qemu_free((char *)mr->name);
+}
+
+target_phys_addr_t memory_region_size(MemoryRegion *mr)
+{
+    return mr->size;
+}
+
+void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
+{
+    mr->offset = offset;
+}
+
+void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
+{
+    /* FIXME */
+}
+
+bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned client)
+{
+    /* FIXME */
+    return true;
+}
+
+void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
+{
+    /* FIXME */
+}
+
+void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
+{
+    /* FIXME */
+}
+
+void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
+{
+    /* FIXME */
+}
+
+void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                               target_phys_addr_t size, unsigned client)
+{
+    /* FIXME */
+}
+
+void *memory_region_get_ram_ptr(MemoryRegion *mr)
+{
+    if (mr->alias) {
+        return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
+    }
+
+    if (!mr->has_ram_addr) {
+        abort();
+    }
+
+    return qemu_get_ram_ptr(mr->ram_addr);
+}
+
+static void memory_region_update_coalesced_range(MemoryRegion *mr)
+{
+    FlatRange *fr;
+    CoalescedMemoryRange *cmr;
+    AddrRange tmp;
+
+    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+        if (fr->mr == mr) {
+            qemu_unregister_coalesced_mmio(fr->addr.start, fr->addr.size);
+            QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
+                tmp = addrrange_shift(cmr->addr,
+                                      fr->addr.start - fr->offset_in_region);
+                if (!addrrange_intersects(tmp, fr->addr)) {
+                    continue;
+                }
+                tmp = addrrange_intersection(tmp, fr->addr);
+                qemu_register_coalesced_mmio(tmp.start, tmp.size);
+            }
+        }
+    }
+}
+
+void memory_region_set_coalescing(MemoryRegion *mr)
+{
+    memory_region_clear_coalescing(mr);
+    memory_region_add_coalescing(mr, 0, mr->size);
+}
+
+void memory_region_add_coalescing(MemoryRegion *mr,
+                                  target_phys_addr_t offset,
+                                  uint64_t size)
+{
+    CoalescedMemoryRange *cmr = qemu_malloc(sizeof(*cmr));
+
+    cmr->addr = addrrange_make(offset, size);
+    QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
+    memory_region_update_coalesced_range(mr);
+}
+
+void memory_region_clear_coalescing(MemoryRegion *mr)
+{
+    CoalescedMemoryRange *cmr;
+
+    while (!QTAILQ_EMPTY(&mr->coalesced)) {
+        cmr = QTAILQ_FIRST(&mr->coalesced);
+        QTAILQ_REMOVE(&mr->coalesced, cmr, link);
+        qemu_free(cmr);
+    }
+    memory_region_update_coalesced_range(mr);
+}
+
+static void memory_region_add_subregion_common(MemoryRegion *mr,
+                                               target_phys_addr_t offset,
+                                               MemoryRegion *subregion)
+{
+    MemoryRegion *other;
+
+    assert(!subregion->parent);
+    subregion->parent = mr;
+    subregion->addr = offset;
+    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
+        if (subregion->may_overlap || other->may_overlap) {
+            continue;
+        }
+        if (offset >= other->offset + other->size
+            || offset + subregion->size <= other->offset) {
+            continue;
+        }
+        printf("warning: subregion collision %llx/%llx vs %llx/%llx\n",
+               (unsigned long long)offset,
+               (unsigned long long)subregion->size,
+               (unsigned long long)other->offset,
+               (unsigned long long)other->size);
+    }
+    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
+        if (subregion->priority >= other->priority) {
+            QTAILQ_INSERT_BEFORE(other, subregion, subregions_link);
+            goto done;
+        }
+    }
+    QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
+done:
+    memory_region_update_topology();
+}
+
+
+void memory_region_add_subregion(MemoryRegion *mr,
+                                 target_phys_addr_t offset,
+                                 MemoryRegion *subregion)
+{
+    subregion->may_overlap = false;
+    subregion->priority = 0;
+    memory_region_add_subregion_common(mr, offset, subregion);
+}
+
+void memory_region_add_subregion_overlap(MemoryRegion *mr,
+                                         target_phys_addr_t offset,
+                                         MemoryRegion *subregion,
+                                         unsigned priority)
+{
+    subregion->may_overlap = true;
+    subregion->priority = priority;
+    memory_region_add_subregion_common(mr, offset, subregion);
+}
+
+void memory_region_del_subregion(MemoryRegion *mr,
+                                 MemoryRegion *subregion)
+{
+    assert(subregion->parent == mr);
+    subregion->parent = NULL;
+    QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
+    memory_region_update_topology();
+}
diff --git a/memory.h b/memory.h
new file mode 100644
index 0000000..95270aa
--- /dev/null
+++ b/memory.h
@@ -0,0 +1,200 @@
+#ifndef MEMORY_H
+#define MEMORY_H
+
+#ifndef CONFIG_USER_ONLY
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "qemu-common.h"
+#include "cpu-common.h"
+#include "targphys.h"
+#include "qemu-queue.h"
+
+typedef struct MemoryRegionOps MemoryRegionOps;
+typedef struct MemoryRegion MemoryRegion;
+
+/* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
+ * registration.
+ */
+#define DIRTY_MEMORY_VGA       0
+#define DIRTY_MEMORY_CODE      1
+#define DIRTY_MEMORY_MIGRATION 3
+
+/*
+ * Memory region callbacks
+ */
+struct MemoryRegionOps {
+    /* Read from the memory region. @addr is relative to @mr; @size is
+     * in bytes. */
+    uint64_t (*read)(void *opaque,
+                     target_phys_addr_t addr,
+                     unsigned size);
+    /* Write to the memory region. @addr is relative to @mr; @size is
+     * in bytes. */
+    void (*write)(void *opaque,
+                  target_phys_addr_t addr,
+                  uint64_t data,
+                  unsigned size);
+
+    enum device_endian endianness;
+    /* Guest-visible constraints: */
+    struct {
+        /* If nonzero, specify bounds on access sizes beyond which a machine
+         * check is thrown.
+         */
+        unsigned min_access_size;
+        unsigned max_access_size;
+        /* If true, unaligned accesses are supported.  Otherwise unaligned
+         * accesses throw machine checks.
+         */
+         bool unaligned;
+    } valid;
+    /* Internal implementation constraints: */
+    struct {
+        /* If nonzero, specifies the minimum size implemented.  Smaller sizes
+         * will be rounded upwards and a partial result will be returned.
+         */
+        unsigned min_access_size;
+        /* If nonzero, specifies the maximum size implemented.  Larger sizes
+         * will be done as a series of accesses with smaller sizes.
+         */
+        unsigned max_access_size;
+        /* If true, unaligned accesses are supported.  Otherwise all accesses
+         * are converted to (possibly multiple) naturally aligned accesses.
+         */
+         bool unaligned;
+    } impl;
+};
+
+typedef struct CoalescedMemoryRange CoalescedMemoryRange;
+
+struct MemoryRegion {
+    /* All fields are private - violators will be prosecuted */
+    const MemoryRegionOps *ops;
+    void *opaque;
+    MemoryRegion *parent;
+    uint64_t size;
+    target_phys_addr_t addr;
+    target_phys_addr_t offset;
+    ram_addr_t ram_addr;
+    bool has_ram_addr;
+    MemoryRegion *alias;
+    target_phys_addr_t alias_offset;
+    unsigned priority;
+    bool may_overlap;
+    QTAILQ_HEAD(subregions, MemoryRegion) subregions;
+    QTAILQ_ENTRY(MemoryRegion) subregions_link;
+    QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
+    const char *name;
+};
+
+/* Initialize a memory region
+ *
+ * The region typically acts as a container for other memory regions.
+ */
+void memory_region_init(MemoryRegion *mr,
+                        const char *name,
+                        uint64_t size);
+/* Initialize an I/O memory region.  Accesses into the region will be
+ * cause the callbacks in @ops to be called.
+ *
+ * if @size is nonzero, subregions will be clipped to @size.
+ */
+void memory_region_init_io(MemoryRegion *mr,
+                           const MemoryRegionOps *ops,
+                           void *opaque,
+                           const char *name,
+                           uint64_t size);
+/* Initialize an I/O memory region.  Accesses into the region will be
+ * modify memory directly.
+ */
+void memory_region_init_ram(MemoryRegion *mr,
+                            DeviceState *dev, /* FIXME: layering violation */
+                            const char *name,
+                            uint64_t size);
+/* Initialize a RAM memory region.  Accesses into the region will be
+ * modify memory in @ptr directly.
+ */
+void memory_region_init_ram_ptr(MemoryRegion *mr,
+                                DeviceState *dev, /* FIXME: layering violation */
+                                const char *name,
+                                uint64_t size,
+                                void *ptr);
+/* Initializes a memory region which aliases a section of another memory
+ * region.
+ */
+void memory_region_init_alias(MemoryRegion *mr,
+                              const char *name,
+                              MemoryRegion *orig,
+                              target_phys_addr_t offset,
+                              uint64_t size);
+
+/* Destroy a memory region.  The memory becomes inaccessible. */
+void memory_region_destroy(MemoryRegion *mr);
+
+target_phys_addr_t memory_region_size(MemoryRegion *mr);
+
+/* Get a pointer into a RAM memory region; use with care */
+void *memory_region_get_ram_ptr(MemoryRegion *mr);
+
+/* Sets an offset to be added to MemoryRegionOps callbacks.  This function
+ * is deprecated and should not be used in new code. */
+void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset);
+
+/* Turn logging on or off for specified client (display, migration) */
+void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client);
+
+/* Check whether a page is dirty for a specified client. */
+bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned client);
+
+/* Mark a page as dirty in a memory region, after it has been dirtied outside
+ * guest code
+ */
+void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr);
+
+/* Synchronize a region's dirty bitmap with any external TLBs (e.g. kvm) */
+void memory_region_sync_dirty_bitmap(MemoryRegion *mr);
+
+/* Mark a range of pages as not dirty, for a specified client. */
+void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                               target_phys_addr_t size, unsigned client);
+
+/* Turn a memory region read-only (or read-write) */
+void memory_region_set_readonly(MemoryRegion *mr, bool readonly);
+
+/* Enable memory coalescing for the region.  MMIO ->write callbacks may be
+ * delayed until a non-coalesced MMIO is issued.
+ */
+void memory_region_set_coalescing(MemoryRegion *mr);
+
+/* Enable memory coalescing for a sub-range of the region.  MMIO ->write
+ * callbacks may be delayed until a non-coalesced MMIO is issued.
+ */
+void memory_region_add_coalescing(MemoryRegion *mr,
+                                  target_phys_addr_t offset,
+                                  uint64_t size);
+/* Disable MMIO coalescing for the region. */
+void memory_region_clear_coalescing(MemoryRegion *mr);
+
+/* Add a sub-region at @offset.  The sub-region may not overlap with other
+ * subregions (except for those explicitly marked as overlapping)
+ */
+void memory_region_add_subregion(MemoryRegion *mr,
+                                 target_phys_addr_t offset,
+                                 MemoryRegion *subregion);
+/* Add a sub-region at @offset.  The sub-region may overlap other subregions;
+ * conflicts are resolved by having a higher @priority hide a lower @priority.
+ * Subregions without priority are taken as @priority 0.
+ */
+void memory_region_add_subregion_overlap(MemoryRegion *mr,
+                                         target_phys_addr_t offset,
+                                         MemoryRegion *subregion,
+                                         unsigned priority);
+/* Remove a subregion. */
+void memory_region_del_subregion(MemoryRegion *mr,
+                                 MemoryRegion *subregion);
+
+#endif
+
+#endif
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 01/23] Hierarchical memory region API
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

The memory API separates the attributes of a memory region (its size, how
reads or writes are handled, dirty logging, and coalescing) from where it
is mapped and whether it is enabled.  This allows a device to configure
a memory region once, then hand it off to its parent bus to map it according
to the bus configuration.

Hierarchical registration also allows a device to compose a region out of
a number of sub-regions with different properties; for example some may be
RAM while others may be MMIO.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 Makefile.target |    1 +
 memory.c        |  655 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory.h        |  200 +++++++++++++++++
 3 files changed, 856 insertions(+), 0 deletions(-)
 create mode 100644 memory.c
 create mode 100644 memory.h

diff --git a/Makefile.target b/Makefile.target
index cde509b..8884a56 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -198,6 +198,7 @@ obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
 obj-y += rwhandler.o
 obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
+obj-y += memory.o
 LIBS+=-lz
 
 QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
diff --git a/memory.c b/memory.c
new file mode 100644
index 0000000..10591bf
--- /dev/null
+++ b/memory.c
@@ -0,0 +1,655 @@
+/*
+ * Physical memory management
+ *
+ * Copyright 2011 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *  Avi Kivity <avi@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "memory.h"
+#include <assert.h>
+
+typedef struct AddrRange AddrRange;
+
+struct AddrRange {
+    uint64_t start;
+    uint64_t size;
+};
+
+static AddrRange addrrange_make(uint64_t start, uint64_t size)
+{
+    return (AddrRange) { start, size };
+}
+
+static bool addrrange_equal(AddrRange r1, AddrRange r2)
+{
+    return r1.start == r2.start && r1.size == r2.size;
+}
+
+static uint64_t addrrange_end(AddrRange r)
+{
+    return r.start + r.size;
+}
+
+static AddrRange addrrange_shift(AddrRange range, int64_t delta)
+{
+    range.start += delta;
+    return range;
+}
+
+static bool addrrange_intersects(AddrRange r1, AddrRange r2)
+{
+    return (r1.start >= r2.start && r1.start < r2.start + r2.size)
+        || (r2.start >= r1.start && r2.start < r1.start + r1.size);
+}
+
+static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
+{
+    uint64_t start = MAX(r1.start, r2.start);
+    /* off-by-one arithmetic to prevent overflow */
+    uint64_t end = MIN(addrrange_end(r1) - 1, addrrange_end(r2) - 1);
+    return addrrange_make(start, end - start + 1);
+}
+
+struct CoalescedMemoryRange {
+    AddrRange addr;
+    QTAILQ_ENTRY(CoalescedMemoryRange) link;
+};
+
+typedef struct FlatRange FlatRange;
+typedef struct FlatView FlatView;
+
+/* Range of memory in the global map.  Addresses are absolute. */
+struct FlatRange {
+    MemoryRegion *mr;
+    target_phys_addr_t offset_in_region;
+    AddrRange addr;
+};
+
+/* Flattened global view of current active memory hierarchy.  Kept in sorted
+ * order.
+ */
+struct FlatView {
+    FlatRange *ranges;
+    unsigned nr;
+    unsigned nr_allocated;
+};
+
+#define FOR_EACH_FLAT_RANGE(var, view)          \
+    for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
+
+static FlatView current_memory_map;
+static MemoryRegion *root_memory_region;
+
+static bool flatrange_equal(FlatRange *a, FlatRange *b)
+{
+    return a->mr == b->mr
+        && addrrange_equal(a->addr, b->addr)
+        && a->offset_in_region == b->offset_in_region;
+}
+
+static void flatview_init(FlatView *view)
+{
+    view->ranges = NULL;
+    view->nr = 0;
+    view->nr_allocated = 0;
+}
+
+/* Insert a range into a given position.  Caller is responsible for maintaining
+ * sorting order.
+ */
+static void flatview_insert(FlatView *view, unsigned pos, FlatRange *range)
+{
+    if (view->nr == view->nr_allocated) {
+        view->nr_allocated = MAX(2 * view->nr, 10);
+        view->ranges = qemu_realloc(view->ranges,
+                                    view->nr_allocated * sizeof(*view->ranges));
+    }
+    memmove(view->ranges + pos + 1, view->ranges + pos,
+            (view->nr - pos) * sizeof(FlatRange));
+    view->ranges[pos] = *range;
+    ++view->nr;
+}
+
+static void flatview_destroy(FlatView *view)
+{
+    qemu_free(view->ranges);
+}
+
+/* Render a memory region into the global view.  Ranges in @view obscure
+ * ranges in @mr.
+ */
+static void render_memory_region(FlatView *view,
+                                 MemoryRegion *mr,
+                                 target_phys_addr_t base,
+                                 AddrRange clip)
+{
+    MemoryRegion *subregion;
+    unsigned i;
+    target_phys_addr_t offset_in_region;
+    uint64_t remain;
+    uint64_t now;
+    FlatRange fr;
+    AddrRange tmp;
+
+    base += mr->addr;
+
+    tmp = addrrange_make(base, mr->size);
+
+    if (!addrrange_intersects(tmp, clip)) {
+        return;
+    }
+
+    clip = addrrange_intersection(tmp, clip);
+
+    if (mr->alias) {
+        base -= mr->alias->addr;
+        base -= mr->alias_offset;
+        render_memory_region(view, mr->alias, base, clip);
+        return;
+    }
+
+    /* Render subregions in priority order. */
+    QTAILQ_FOREACH(subregion, &mr->subregions, subregions_link) {
+        render_memory_region(view, subregion, base, clip);
+    }
+
+    if (!mr->has_ram_addr) {
+        return;
+    }
+
+    offset_in_region = clip.start - base;
+    base = clip.start;
+    remain = clip.size;
+
+    /* Render the region itself into any gaps left by the current view. */
+    for (i = 0; i < view->nr && remain; ++i) {
+        if (base >= addrrange_end(view->ranges[i].addr)) {
+            continue;
+        }
+        if (base < view->ranges[i].addr.start) {
+            now = MIN(remain, view->ranges[i].addr.start - base);
+            fr.mr = mr;
+            fr.offset_in_region = offset_in_region;
+            fr.addr = addrrange_make(base, now);
+            flatview_insert(view, i, &fr);
+            ++i;
+            base += now;
+            offset_in_region += now;
+            remain -= now;
+        }
+        if (base == view->ranges[i].addr.start) {
+            now = MIN(remain, view->ranges[i].addr.size);
+            base += now;
+            offset_in_region += now;
+            remain -= now;
+        }
+    }
+    if (remain) {
+        fr.mr = mr;
+        fr.offset_in_region = offset_in_region;
+        fr.addr = addrrange_make(base, remain);
+        flatview_insert(view, i, &fr);
+    }
+}
+
+/* Render a memory topology into a list of disjoint absolute ranges. */
+static FlatView generate_memory_topology(MemoryRegion *mr)
+{
+    FlatView view;
+
+    flatview_init(&view);
+
+    render_memory_region(&view, mr, 0, addrrange_make(0, UINT64_MAX));
+
+    return view;
+}
+
+static void memory_region_update_topology(void)
+{
+    FlatView old_view = current_memory_map;
+    FlatView new_view = generate_memory_topology(root_memory_region);
+    unsigned iold, inew;
+    FlatRange *frold, *frnew;
+    ram_addr_t phys_offset, region_offset;
+
+    /* Generate a symmetric difference of the old and new memory maps.
+     * Kill ranges in the old map, and instantiate ranges in the new map.
+     */
+    iold = inew = 0;
+    while (iold < old_view.nr || inew < new_view.nr) {
+        if (iold < old_view.nr) {
+            frold = &old_view.ranges[iold];
+        } else {
+            frold = NULL;
+        }
+        if (inew < new_view.nr) {
+            frnew = &new_view.ranges[inew];
+        } else {
+            frnew = NULL;
+        }
+
+        if (frold
+            && (!frnew
+                || frold->addr.start < frnew->addr.start
+                || (frold->addr.start == frnew->addr.start
+                    && !flatrange_equal(frold, frnew)))) {
+            /* In old, but (not in new, or in new but attributes changed). */
+
+            cpu_register_physical_memory(frold->addr.start, frold->addr.size,
+                                         IO_MEM_UNASSIGNED);
+            ++iold;
+        } else if (frold && frnew && flatrange_equal(frold, frnew)) {
+            /* In both (logging may have changed) */
+
+            ++iold;
+            ++inew;
+            /* FIXME: dirty logging */
+        } else {
+            /* In new */
+
+            phys_offset = frnew->mr->ram_addr;
+            region_offset = frnew->offset_in_region;
+            /* cpu_register_physical_memory_log() wants region_offset for
+             * mmio, but prefers offseting phys_offset for RAM.  Humour it.
+             */
+            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
+                phys_offset += region_offset;
+                region_offset = 0;
+            }
+
+            cpu_register_physical_memory_log(frnew->addr.start,
+                                             frnew->addr.size,
+                                             phys_offset,
+                                             region_offset,
+                                             0);
+            ++inew;
+        }
+    }
+    current_memory_map = new_view;
+    flatview_destroy(&old_view);
+}
+
+void memory_region_init(MemoryRegion *mr,
+                        const char *name,
+                        uint64_t size)
+{
+    mr->ops = NULL;
+    mr->parent = NULL;
+    mr->size = size;
+    mr->addr = 0;
+    mr->offset = 0;
+    mr->has_ram_addr = false;
+    mr->priority = 0;
+    mr->may_overlap = false;
+    mr->alias = NULL;
+    QTAILQ_INIT(&mr->subregions);
+    memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
+    QTAILQ_INIT(&mr->coalesced);
+    mr->name = qemu_strdup(name);
+}
+
+static bool memory_region_access_valid(MemoryRegion *mr,
+                                       target_phys_addr_t addr,
+                                       unsigned size)
+{
+    if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
+        return false;
+    }
+
+    /* Treat zero as compatibility all valid */
+    if (!mr->ops->valid.max_access_size) {
+        return true;
+    }
+
+    if (size > mr->ops->valid.max_access_size
+        || size < mr->ops->valid.min_access_size) {
+        return false;
+    }
+    return true;
+}
+
+static uint32_t memory_region_read_thunk_n(void *_mr,
+                                           target_phys_addr_t addr,
+                                           unsigned size)
+{
+    MemoryRegion *mr = _mr;
+    unsigned access_size, access_size_min, access_size_max;
+    uint64_t access_mask;
+    uint32_t data = 0, tmp;
+    unsigned i;
+
+    if (!memory_region_access_valid(mr, addr, size)) {
+        return -1U; /* FIXME: better signalling */
+    }
+
+    /* FIXME: support unaligned access */
+
+    access_size_min = mr->ops->impl.min_access_size;
+    if (!access_size_min) {
+        access_size_min = 1;
+    }
+    access_size_max = mr->ops->impl.max_access_size;
+    if (!access_size_max) {
+        access_size_max = 4;
+    }
+    access_size = MAX(MIN(size, access_size_max), access_size_min);
+    access_mask = -1ULL >> (64 - access_size * 8);
+    addr += mr->offset;
+    for (i = 0; i < size; i += access_size) {
+        /* FIXME: big-endian support */
+        tmp = mr->ops->read(mr->opaque, addr + i, access_size);
+        data |= (tmp & access_mask) << (i * 8);
+    }
+
+    return data;
+}
+
+static void memory_region_write_thunk_n(void *_mr,
+                                        target_phys_addr_t addr,
+                                        unsigned size,
+                                        uint64_t data)
+{
+    MemoryRegion *mr = _mr;
+    unsigned access_size, access_size_min, access_size_max;
+    uint64_t access_mask;
+    unsigned i;
+
+    if (!memory_region_access_valid(mr, addr, size)) {
+        return; /* FIXME: better signalling */
+    }
+
+    /* FIXME: support unaligned access */
+
+    access_size_min = mr->ops->impl.min_access_size;
+    if (!access_size_min) {
+        access_size_min = 1;
+    }
+    access_size_max = mr->ops->impl.max_access_size;
+    if (!access_size_max) {
+        access_size_max = 4;
+    }
+    access_size = MAX(MIN(size, access_size_max), access_size_min);
+    access_mask = -1ULL >> (64 - access_size * 8);
+    addr += mr->offset;
+    for (i = 0; i < size; i += access_size) {
+        /* FIXME: big-endian support */
+        mr->ops->write(mr->opaque, addr + i, (data >> (i * 8)) & access_mask,
+                       access_size);
+    }
+}
+
+static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr)
+{
+    return memory_region_read_thunk_n(mr, addr, 1);
+}
+
+static uint32_t memory_region_read_thunk_w(void *mr, target_phys_addr_t addr)
+{
+    return memory_region_read_thunk_n(mr, addr, 2);
+}
+
+static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr)
+{
+    return memory_region_read_thunk_n(mr, addr, 4);
+}
+
+static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
+                                        uint32_t data)
+{
+    memory_region_write_thunk_n(mr, addr, 1, data);
+}
+
+static void memory_region_write_thunk_w(void *mr, target_phys_addr_t addr,
+                                        uint32_t data)
+{
+    memory_region_write_thunk_n(mr, addr, 2, data);
+}
+
+static void memory_region_write_thunk_l(void *mr, target_phys_addr_t addr,
+                                        uint32_t data)
+{
+    memory_region_write_thunk_n(mr, addr, 4, data);
+}
+
+static CPUReadMemoryFunc * const memory_region_read_thunk[] = {
+    memory_region_read_thunk_b,
+    memory_region_read_thunk_w,
+    memory_region_read_thunk_l,
+};
+
+static CPUWriteMemoryFunc * const memory_region_write_thunk[] = {
+    memory_region_write_thunk_b,
+    memory_region_write_thunk_w,
+    memory_region_write_thunk_l,
+};
+
+void memory_region_init_io(MemoryRegion *mr,
+                           const MemoryRegionOps *ops,
+                           void *opaque,
+                           const char *name,
+                           uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->ops = ops;
+    mr->opaque = opaque;
+    mr->has_ram_addr = true;
+    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
+                                          memory_region_write_thunk,
+                                          mr,
+                                          mr->ops->endianness);
+}
+
+void memory_region_init_ram(MemoryRegion *mr,
+                            DeviceState *dev,
+                            const char *name,
+                            uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->has_ram_addr = true;
+    mr->ram_addr = qemu_ram_alloc(dev, name, size);
+}
+
+void memory_region_init_ram_ptr(MemoryRegion *mr,
+                                DeviceState *dev,
+                                const char *name,
+                                uint64_t size,
+                                void *ptr)
+{
+    memory_region_init(mr, name, size);
+    mr->has_ram_addr = true;
+    mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
+}
+
+void memory_region_init_alias(MemoryRegion *mr,
+                              const char *name,
+                              MemoryRegion *orig,
+                              target_phys_addr_t offset,
+                              uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->alias = orig;
+    mr->alias_offset = offset;
+}
+
+void memory_region_destroy(MemoryRegion *mr)
+{
+    assert(QTAILQ_EMPTY(&mr->subregions));
+    memory_region_clear_coalescing(mr);
+    qemu_free((char *)mr->name);
+}
+
+target_phys_addr_t memory_region_size(MemoryRegion *mr)
+{
+    return mr->size;
+}
+
+void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
+{
+    mr->offset = offset;
+}
+
+void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
+{
+    /* FIXME */
+}
+
+bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned client)
+{
+    /* FIXME */
+    return true;
+}
+
+void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
+{
+    /* FIXME */
+}
+
+void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
+{
+    /* FIXME */
+}
+
+void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
+{
+    /* FIXME */
+}
+
+void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                               target_phys_addr_t size, unsigned client)
+{
+    /* FIXME */
+}
+
+void *memory_region_get_ram_ptr(MemoryRegion *mr)
+{
+    if (mr->alias) {
+        return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
+    }
+
+    if (!mr->has_ram_addr) {
+        abort();
+    }
+
+    return qemu_get_ram_ptr(mr->ram_addr);
+}
+
+static void memory_region_update_coalesced_range(MemoryRegion *mr)
+{
+    FlatRange *fr;
+    CoalescedMemoryRange *cmr;
+    AddrRange tmp;
+
+    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+        if (fr->mr == mr) {
+            qemu_unregister_coalesced_mmio(fr->addr.start, fr->addr.size);
+            QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
+                tmp = addrrange_shift(cmr->addr,
+                                      fr->addr.start - fr->offset_in_region);
+                if (!addrrange_intersects(tmp, fr->addr)) {
+                    continue;
+                }
+                tmp = addrrange_intersection(tmp, fr->addr);
+                qemu_register_coalesced_mmio(tmp.start, tmp.size);
+            }
+        }
+    }
+}
+
+void memory_region_set_coalescing(MemoryRegion *mr)
+{
+    memory_region_clear_coalescing(mr);
+    memory_region_add_coalescing(mr, 0, mr->size);
+}
+
+void memory_region_add_coalescing(MemoryRegion *mr,
+                                  target_phys_addr_t offset,
+                                  uint64_t size)
+{
+    CoalescedMemoryRange *cmr = qemu_malloc(sizeof(*cmr));
+
+    cmr->addr = addrrange_make(offset, size);
+    QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
+    memory_region_update_coalesced_range(mr);
+}
+
+void memory_region_clear_coalescing(MemoryRegion *mr)
+{
+    CoalescedMemoryRange *cmr;
+
+    while (!QTAILQ_EMPTY(&mr->coalesced)) {
+        cmr = QTAILQ_FIRST(&mr->coalesced);
+        QTAILQ_REMOVE(&mr->coalesced, cmr, link);
+        qemu_free(cmr);
+    }
+    memory_region_update_coalesced_range(mr);
+}
+
+static void memory_region_add_subregion_common(MemoryRegion *mr,
+                                               target_phys_addr_t offset,
+                                               MemoryRegion *subregion)
+{
+    MemoryRegion *other;
+
+    assert(!subregion->parent);
+    subregion->parent = mr;
+    subregion->addr = offset;
+    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
+        if (subregion->may_overlap || other->may_overlap) {
+            continue;
+        }
+        if (offset >= other->offset + other->size
+            || offset + subregion->size <= other->offset) {
+            continue;
+        }
+        printf("warning: subregion collision %llx/%llx vs %llx/%llx\n",
+               (unsigned long long)offset,
+               (unsigned long long)subregion->size,
+               (unsigned long long)other->offset,
+               (unsigned long long)other->size);
+    }
+    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
+        if (subregion->priority >= other->priority) {
+            QTAILQ_INSERT_BEFORE(other, subregion, subregions_link);
+            goto done;
+        }
+    }
+    QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
+done:
+    memory_region_update_topology();
+}
+
+
+void memory_region_add_subregion(MemoryRegion *mr,
+                                 target_phys_addr_t offset,
+                                 MemoryRegion *subregion)
+{
+    subregion->may_overlap = false;
+    subregion->priority = 0;
+    memory_region_add_subregion_common(mr, offset, subregion);
+}
+
+void memory_region_add_subregion_overlap(MemoryRegion *mr,
+                                         target_phys_addr_t offset,
+                                         MemoryRegion *subregion,
+                                         unsigned priority)
+{
+    subregion->may_overlap = true;
+    subregion->priority = priority;
+    memory_region_add_subregion_common(mr, offset, subregion);
+}
+
+void memory_region_del_subregion(MemoryRegion *mr,
+                                 MemoryRegion *subregion)
+{
+    assert(subregion->parent == mr);
+    subregion->parent = NULL;
+    QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
+    memory_region_update_topology();
+}
diff --git a/memory.h b/memory.h
new file mode 100644
index 0000000..95270aa
--- /dev/null
+++ b/memory.h
@@ -0,0 +1,200 @@
+#ifndef MEMORY_H
+#define MEMORY_H
+
+#ifndef CONFIG_USER_ONLY
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "qemu-common.h"
+#include "cpu-common.h"
+#include "targphys.h"
+#include "qemu-queue.h"
+
+typedef struct MemoryRegionOps MemoryRegionOps;
+typedef struct MemoryRegion MemoryRegion;
+
+/* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
+ * registration.
+ */
+#define DIRTY_MEMORY_VGA       0
+#define DIRTY_MEMORY_CODE      1
+#define DIRTY_MEMORY_MIGRATION 3
+
+/*
+ * Memory region callbacks
+ */
+struct MemoryRegionOps {
+    /* Read from the memory region. @addr is relative to @mr; @size is
+     * in bytes. */
+    uint64_t (*read)(void *opaque,
+                     target_phys_addr_t addr,
+                     unsigned size);
+    /* Write to the memory region. @addr is relative to @mr; @size is
+     * in bytes. */
+    void (*write)(void *opaque,
+                  target_phys_addr_t addr,
+                  uint64_t data,
+                  unsigned size);
+
+    enum device_endian endianness;
+    /* Guest-visible constraints: */
+    struct {
+        /* If nonzero, specify bounds on access sizes beyond which a machine
+         * check is thrown.
+         */
+        unsigned min_access_size;
+        unsigned max_access_size;
+        /* If true, unaligned accesses are supported.  Otherwise unaligned
+         * accesses throw machine checks.
+         */
+         bool unaligned;
+    } valid;
+    /* Internal implementation constraints: */
+    struct {
+        /* If nonzero, specifies the minimum size implemented.  Smaller sizes
+         * will be rounded upwards and a partial result will be returned.
+         */
+        unsigned min_access_size;
+        /* If nonzero, specifies the maximum size implemented.  Larger sizes
+         * will be done as a series of accesses with smaller sizes.
+         */
+        unsigned max_access_size;
+        /* If true, unaligned accesses are supported.  Otherwise all accesses
+         * are converted to (possibly multiple) naturally aligned accesses.
+         */
+         bool unaligned;
+    } impl;
+};
+
+typedef struct CoalescedMemoryRange CoalescedMemoryRange;
+
+struct MemoryRegion {
+    /* All fields are private - violators will be prosecuted */
+    const MemoryRegionOps *ops;
+    void *opaque;
+    MemoryRegion *parent;
+    uint64_t size;
+    target_phys_addr_t addr;
+    target_phys_addr_t offset;
+    ram_addr_t ram_addr;
+    bool has_ram_addr;
+    MemoryRegion *alias;
+    target_phys_addr_t alias_offset;
+    unsigned priority;
+    bool may_overlap;
+    QTAILQ_HEAD(subregions, MemoryRegion) subregions;
+    QTAILQ_ENTRY(MemoryRegion) subregions_link;
+    QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
+    const char *name;
+};
+
+/* Initialize a memory region
+ *
+ * The region typically acts as a container for other memory regions.
+ */
+void memory_region_init(MemoryRegion *mr,
+                        const char *name,
+                        uint64_t size);
+/* Initialize an I/O memory region.  Accesses into the region will be
+ * cause the callbacks in @ops to be called.
+ *
+ * if @size is nonzero, subregions will be clipped to @size.
+ */
+void memory_region_init_io(MemoryRegion *mr,
+                           const MemoryRegionOps *ops,
+                           void *opaque,
+                           const char *name,
+                           uint64_t size);
+/* Initialize an I/O memory region.  Accesses into the region will be
+ * modify memory directly.
+ */
+void memory_region_init_ram(MemoryRegion *mr,
+                            DeviceState *dev, /* FIXME: layering violation */
+                            const char *name,
+                            uint64_t size);
+/* Initialize a RAM memory region.  Accesses into the region will be
+ * modify memory in @ptr directly.
+ */
+void memory_region_init_ram_ptr(MemoryRegion *mr,
+                                DeviceState *dev, /* FIXME: layering violation */
+                                const char *name,
+                                uint64_t size,
+                                void *ptr);
+/* Initializes a memory region which aliases a section of another memory
+ * region.
+ */
+void memory_region_init_alias(MemoryRegion *mr,
+                              const char *name,
+                              MemoryRegion *orig,
+                              target_phys_addr_t offset,
+                              uint64_t size);
+
+/* Destroy a memory region.  The memory becomes inaccessible. */
+void memory_region_destroy(MemoryRegion *mr);
+
+target_phys_addr_t memory_region_size(MemoryRegion *mr);
+
+/* Get a pointer into a RAM memory region; use with care */
+void *memory_region_get_ram_ptr(MemoryRegion *mr);
+
+/* Sets an offset to be added to MemoryRegionOps callbacks.  This function
+ * is deprecated and should not be used in new code. */
+void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset);
+
+/* Turn logging on or off for specified client (display, migration) */
+void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client);
+
+/* Check whether a page is dirty for a specified client. */
+bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned client);
+
+/* Mark a page as dirty in a memory region, after it has been dirtied outside
+ * guest code
+ */
+void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr);
+
+/* Synchronize a region's dirty bitmap with any external TLBs (e.g. kvm) */
+void memory_region_sync_dirty_bitmap(MemoryRegion *mr);
+
+/* Mark a range of pages as not dirty, for a specified client. */
+void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
+                               target_phys_addr_t size, unsigned client);
+
+/* Turn a memory region read-only (or read-write) */
+void memory_region_set_readonly(MemoryRegion *mr, bool readonly);
+
+/* Enable memory coalescing for the region.  MMIO ->write callbacks may be
+ * delayed until a non-coalesced MMIO is issued.
+ */
+void memory_region_set_coalescing(MemoryRegion *mr);
+
+/* Enable memory coalescing for a sub-range of the region.  MMIO ->write
+ * callbacks may be delayed until a non-coalesced MMIO is issued.
+ */
+void memory_region_add_coalescing(MemoryRegion *mr,
+                                  target_phys_addr_t offset,
+                                  uint64_t size);
+/* Disable MMIO coalescing for the region. */
+void memory_region_clear_coalescing(MemoryRegion *mr);
+
+/* Add a sub-region at @offset.  The sub-region may not overlap with other
+ * subregions (except for those explicitly marked as overlapping)
+ */
+void memory_region_add_subregion(MemoryRegion *mr,
+                                 target_phys_addr_t offset,
+                                 MemoryRegion *subregion);
+/* Add a sub-region at @offset.  The sub-region may overlap other subregions;
+ * conflicts are resolved by having a higher @priority hide a lower @priority.
+ * Subregions without priority are taken as @priority 0.
+ */
+void memory_region_add_subregion_overlap(MemoryRegion *mr,
+                                         target_phys_addr_t offset,
+                                         MemoryRegion *subregion,
+                                         unsigned priority);
+/* Remove a subregion. */
+void memory_region_del_subregion(MemoryRegion *mr,
+                                 MemoryRegion *subregion);
+
+#endif
+
+#endif
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 02/23] memory: implement dirty tracking
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Currently dirty tracking is implemented by passing through
all calls to the underlying cpu_physical_memory_*() calls.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   39 +++++++++++++++++++++++++++++++--------
 memory.h |    1 +
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/memory.c b/memory.c
index 10591bf..a569666 100644
--- a/memory.c
+++ b/memory.c
@@ -69,6 +69,7 @@ struct FlatRange {
     MemoryRegion *mr;
     target_phys_addr_t offset_in_region;
     AddrRange addr;
+    uint8_t dirty_log_mask;
 };
 
 /* Flattened global view of current active memory hierarchy.  Kept in sorted
@@ -177,6 +178,7 @@ static void render_memory_region(FlatView *view,
             fr.mr = mr;
             fr.offset_in_region = offset_in_region;
             fr.addr = addrrange_make(base, now);
+            fr.dirty_log_mask = mr->dirty_log_mask;
             flatview_insert(view, i, &fr);
             ++i;
             base += now;
@@ -194,6 +196,7 @@ static void render_memory_region(FlatView *view,
         fr.mr = mr;
         fr.offset_in_region = offset_in_region;
         fr.addr = addrrange_make(base, remain);
+        fr.dirty_log_mask = mr->dirty_log_mask;
         flatview_insert(view, i, &fr);
     }
 }
@@ -247,9 +250,14 @@ static void memory_region_update_topology(void)
         } else if (frold && frnew && flatrange_equal(frold, frnew)) {
             /* In both (logging may have changed) */
 
+            if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
+                cpu_physical_log_stop(frnew->addr.start, frnew->addr.size);
+            } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
+                cpu_physical_log_start(frnew->addr.start, frnew->addr.size);
+            }
+
             ++iold;
             ++inew;
-            /* FIXME: dirty logging */
         } else {
             /* In new */
 
@@ -267,7 +275,7 @@ static void memory_region_update_topology(void)
                                              frnew->addr.size,
                                              phys_offset,
                                              region_offset,
-                                             0);
+                                             frnew->dirty_log_mask);
             ++inew;
         }
     }
@@ -292,6 +300,7 @@ void memory_region_init(MemoryRegion *mr,
     memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
     QTAILQ_INIT(&mr->coalesced);
     mr->name = qemu_strdup(name);
+    mr->dirty_log_mask = 0;
 }
 
 static bool memory_region_access_valid(MemoryRegion *mr,
@@ -496,24 +505,35 @@ void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
 
 void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 {
-    /* FIXME */
+    uint8_t mask = 1 << client;
+
+    mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
+    memory_region_update_topology();
 }
 
 bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                              unsigned client)
 {
-    /* FIXME */
-    return true;
+    assert(mr->has_ram_addr);
+    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
 }
 
 void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
 {
-    /* FIXME */
+    assert(mr->has_ram_addr);
+    return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
 }
 
 void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 {
-    /* FIXME */
+    FlatRange *fr;
+
+    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+        if (fr->mr == mr) {
+            cpu_physical_sync_dirty_bitmap(fr->addr.start,
+                                           fr->addr.start + fr->addr.size);
+        }
+    }
 }
 
 void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
@@ -524,7 +544,10 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
 void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                                target_phys_addr_t size, unsigned client)
 {
-    /* FIXME */
+    assert(mr->has_ram_addr);
+    cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
+                                    mr->ram_addr + addr + size,
+                                    1 << client);
 }
 
 void *memory_region_get_ram_ptr(MemoryRegion *mr)
diff --git a/memory.h b/memory.h
index 95270aa..8873f75 100644
--- a/memory.h
+++ b/memory.h
@@ -86,6 +86,7 @@ struct MemoryRegion {
     QTAILQ_ENTRY(MemoryRegion) subregions_link;
     QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
     const char *name;
+    uint8_t dirty_log_mask;
 };
 
 /* Initialize a memory region
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 02/23] memory: implement dirty tracking
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Currently dirty tracking is implemented by passing through
all calls to the underlying cpu_physical_memory_*() calls.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   39 +++++++++++++++++++++++++++++++--------
 memory.h |    1 +
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/memory.c b/memory.c
index 10591bf..a569666 100644
--- a/memory.c
+++ b/memory.c
@@ -69,6 +69,7 @@ struct FlatRange {
     MemoryRegion *mr;
     target_phys_addr_t offset_in_region;
     AddrRange addr;
+    uint8_t dirty_log_mask;
 };
 
 /* Flattened global view of current active memory hierarchy.  Kept in sorted
@@ -177,6 +178,7 @@ static void render_memory_region(FlatView *view,
             fr.mr = mr;
             fr.offset_in_region = offset_in_region;
             fr.addr = addrrange_make(base, now);
+            fr.dirty_log_mask = mr->dirty_log_mask;
             flatview_insert(view, i, &fr);
             ++i;
             base += now;
@@ -194,6 +196,7 @@ static void render_memory_region(FlatView *view,
         fr.mr = mr;
         fr.offset_in_region = offset_in_region;
         fr.addr = addrrange_make(base, remain);
+        fr.dirty_log_mask = mr->dirty_log_mask;
         flatview_insert(view, i, &fr);
     }
 }
@@ -247,9 +250,14 @@ static void memory_region_update_topology(void)
         } else if (frold && frnew && flatrange_equal(frold, frnew)) {
             /* In both (logging may have changed) */
 
+            if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
+                cpu_physical_log_stop(frnew->addr.start, frnew->addr.size);
+            } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
+                cpu_physical_log_start(frnew->addr.start, frnew->addr.size);
+            }
+
             ++iold;
             ++inew;
-            /* FIXME: dirty logging */
         } else {
             /* In new */
 
@@ -267,7 +275,7 @@ static void memory_region_update_topology(void)
                                              frnew->addr.size,
                                              phys_offset,
                                              region_offset,
-                                             0);
+                                             frnew->dirty_log_mask);
             ++inew;
         }
     }
@@ -292,6 +300,7 @@ void memory_region_init(MemoryRegion *mr,
     memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
     QTAILQ_INIT(&mr->coalesced);
     mr->name = qemu_strdup(name);
+    mr->dirty_log_mask = 0;
 }
 
 static bool memory_region_access_valid(MemoryRegion *mr,
@@ -496,24 +505,35 @@ void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
 
 void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 {
-    /* FIXME */
+    uint8_t mask = 1 << client;
+
+    mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
+    memory_region_update_topology();
 }
 
 bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                              unsigned client)
 {
-    /* FIXME */
-    return true;
+    assert(mr->has_ram_addr);
+    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
 }
 
 void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
 {
-    /* FIXME */
+    assert(mr->has_ram_addr);
+    return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
 }
 
 void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 {
-    /* FIXME */
+    FlatRange *fr;
+
+    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+        if (fr->mr == mr) {
+            cpu_physical_sync_dirty_bitmap(fr->addr.start,
+                                           fr->addr.start + fr->addr.size);
+        }
+    }
 }
 
 void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
@@ -524,7 +544,10 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
 void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                                target_phys_addr_t size, unsigned client)
 {
-    /* FIXME */
+    assert(mr->has_ram_addr);
+    cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
+                                    mr->ram_addr + addr + size,
+                                    1 << client);
 }
 
 void *memory_region_get_ram_ptr(MemoryRegion *mr)
diff --git a/memory.h b/memory.h
index 95270aa..8873f75 100644
--- a/memory.h
+++ b/memory.h
@@ -86,6 +86,7 @@ struct MemoryRegion {
     QTAILQ_ENTRY(MemoryRegion) subregions_link;
     QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
     const char *name;
+    uint8_t dirty_log_mask;
 };
 
 /* Initialize a memory region
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 03/23] memory: merge adjacent segments of a single memory region
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Simple implementations of memory routers, for example the Cirrus VGA memory banks
or the 440FX PAM registers can generate adjacent memory regions which are contiguous.
Detect these and merge them; this saves kvm memory slots and shortens lookup times.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index a569666..339bea3 100644
--- a/memory.c
+++ b/memory.c
@@ -122,6 +122,27 @@ static void flatview_destroy(FlatView *view)
     qemu_free(view->ranges);
 }
 
+/* Attempt to simplify a view by merging ajacent ranges */
+static void flatview_simplify(FlatView *view)
+{
+    unsigned i;
+    FlatRange *r1, *r2;
+
+    for (i = 0; i + 1 < view->nr; ++i) {
+        r1 = &view->ranges[i];
+        r2 = &view->ranges[i+1];
+        if (addrrange_end(r1->addr) == r2->addr.start
+            && r1->mr == r2->mr
+            && r1->offset_in_region + r1->addr.size == r2->offset_in_region
+            && r1->dirty_log_mask == r2->dirty_log_mask) {
+            r1->addr.size += r2->addr.size;
+            memmove(r2, r2 + 1, (view->nr - (i + 2)) * sizeof(*r2));
+            --view->nr;
+            --i;
+        }
+    }
+}
+
 /* Render a memory region into the global view.  Ranges in @view obscure
  * ranges in @mr.
  */
@@ -209,6 +230,7 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
     flatview_init(&view);
 
     render_memory_region(&view, mr, 0, addrrange_make(0, UINT64_MAX));
+    flatview_simplify(&view);
 
     return view;
 }
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 03/23] memory: merge adjacent segments of a single memory region
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Simple implementations of memory routers, for example the Cirrus VGA memory banks
or the 440FX PAM registers can generate adjacent memory regions which are contiguous.
Detect these and merge them; this saves kvm memory slots and shortens lookup times.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index a569666..339bea3 100644
--- a/memory.c
+++ b/memory.c
@@ -122,6 +122,27 @@ static void flatview_destroy(FlatView *view)
     qemu_free(view->ranges);
 }
 
+/* Attempt to simplify a view by merging ajacent ranges */
+static void flatview_simplify(FlatView *view)
+{
+    unsigned i;
+    FlatRange *r1, *r2;
+
+    for (i = 0; i + 1 < view->nr; ++i) {
+        r1 = &view->ranges[i];
+        r2 = &view->ranges[i+1];
+        if (addrrange_end(r1->addr) == r2->addr.start
+            && r1->mr == r2->mr
+            && r1->offset_in_region + r1->addr.size == r2->offset_in_region
+            && r1->dirty_log_mask == r2->dirty_log_mask) {
+            r1->addr.size += r2->addr.size;
+            memmove(r2, r2 + 1, (view->nr - (i + 2)) * sizeof(*r2));
+            --view->nr;
+            --i;
+        }
+    }
+}
+
 /* Render a memory region into the global view.  Ranges in @view obscure
  * ranges in @mr.
  */
@@ -209,6 +230,7 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
     flatview_init(&view);
 
     render_memory_region(&view, mr, 0, addrrange_make(0, UINT64_MAX));
+    flatview_simplify(&view);
 
     return view;
 }
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 04/23] Internal interfaces for memory API
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

get_system_memory() provides the root of the memory hierarchy.

This interface is intended to be private between memory.c and exec.c.
If this file is included elsewhere, it should be regarded as a bug (or
TODO item).  However, it will be temporarily needed for the conversion
to hierarchical memory routing.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 exec-memory.h |   23 +++++++++++++++++++++++
 memory.c      |    7 +++++++
 2 files changed, 30 insertions(+), 0 deletions(-)
 create mode 100644 exec-memory.h

diff --git a/exec-memory.h b/exec-memory.h
new file mode 100644
index 0000000..7eb9085
--- /dev/null
+++ b/exec-memory.h
@@ -0,0 +1,23 @@
+#ifndef EXEC_MEMORY_H
+#define EXEC_MEMORY_H
+
+/*
+ * Internal interfaces between memory.c/exec.c/vl.c.  Do not #include unless
+ * you're one of them.
+ */
+
+#include "memory.h"
+
+#ifndef CONFIG_USER_ONLY
+
+/* Get the root memory region.  This interface should only be used temporarily
+ * until a proper bus interface is available.
+ */
+MemoryRegion *get_system_memory(void);
+
+/* Set the root memory region.  This region is the system memory map. */
+void set_system_memory_map(MemoryRegion *mr);
+
+#endif
+
+#endif
diff --git a/memory.c b/memory.c
index 339bea3..48470d2 100644
--- a/memory.c
+++ b/memory.c
@@ -12,6 +12,7 @@
  */
 
 #include "memory.h"
+#include "exec-memory.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -698,3 +699,9 @@ void memory_region_del_subregion(MemoryRegion *mr,
     QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
     memory_region_update_topology();
 }
+
+void set_system_memory_map(MemoryRegion *mr)
+{
+    root_memory_region = mr;
+    memory_region_update_topology();
+}
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 04/23] Internal interfaces for memory API
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

get_system_memory() provides the root of the memory hierarchy.

This interface is intended to be private between memory.c and exec.c.
If this file is included elsewhere, it should be regarded as a bug (or
TODO item).  However, it will be temporarily needed for the conversion
to hierarchical memory routing.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 exec-memory.h |   23 +++++++++++++++++++++++
 memory.c      |    7 +++++++
 2 files changed, 30 insertions(+), 0 deletions(-)
 create mode 100644 exec-memory.h

diff --git a/exec-memory.h b/exec-memory.h
new file mode 100644
index 0000000..7eb9085
--- /dev/null
+++ b/exec-memory.h
@@ -0,0 +1,23 @@
+#ifndef EXEC_MEMORY_H
+#define EXEC_MEMORY_H
+
+/*
+ * Internal interfaces between memory.c/exec.c/vl.c.  Do not #include unless
+ * you're one of them.
+ */
+
+#include "memory.h"
+
+#ifndef CONFIG_USER_ONLY
+
+/* Get the root memory region.  This interface should only be used temporarily
+ * until a proper bus interface is available.
+ */
+MemoryRegion *get_system_memory(void);
+
+/* Set the root memory region.  This region is the system memory map. */
+void set_system_memory_map(MemoryRegion *mr);
+
+#endif
+
+#endif
diff --git a/memory.c b/memory.c
index 339bea3..48470d2 100644
--- a/memory.c
+++ b/memory.c
@@ -12,6 +12,7 @@
  */
 
 #include "memory.h"
+#include "exec-memory.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -698,3 +699,9 @@ void memory_region_del_subregion(MemoryRegion *mr,
     QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
     memory_region_update_topology();
 }
+
+void set_system_memory_map(MemoryRegion *mr)
+{
+    root_memory_region = mr;
+    memory_region_update_topology();
+}
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 05/23] memory: abstract address space operations
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Prepare for multiple address space support by abstracting away the details
of registering a memory range with qemu's flat representation into an
AddressSpace object.

Note operations which are memory specific are not abstracted, since they will
never be called on I/O address spaces anyway.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |  111 +++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 81 insertions(+), 30 deletions(-)

diff --git a/memory.c b/memory.c
index 48470d2..7187223 100644
--- a/memory.c
+++ b/memory.c
@@ -82,12 +82,26 @@ struct FlatView {
     unsigned nr_allocated;
 };
 
+typedef struct AddressSpace AddressSpace;
+typedef struct AddressSpaceOps AddressSpaceOps;
+
+/* A system address space - I/O, memory, etc. */
+struct AddressSpace {
+    const AddressSpaceOps *ops;
+    MemoryRegion *root;
+    FlatView current_map;
+};
+
+struct AddressSpaceOps {
+    void (*range_add)(AddressSpace *as, FlatRange *fr);
+    void (*range_del)(AddressSpace *as, FlatRange *fr);
+    void (*log_start)(AddressSpace *as, FlatRange *fr);
+    void (*log_stop)(AddressSpace *as, FlatRange *fr);
+};
+
 #define FOR_EACH_FLAT_RANGE(var, view)          \
     for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
 
-static FlatView current_memory_map;
-static MemoryRegion *root_memory_region;
-
 static bool flatrange_equal(FlatRange *a, FlatRange *b)
 {
     return a->mr == b->mr
@@ -144,6 +158,54 @@ static void flatview_simplify(FlatView *view)
     }
 }
 
+static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
+{
+    ram_addr_t phys_offset, region_offset;
+
+    phys_offset = fr->mr->ram_addr;
+    region_offset = fr->offset_in_region;
+    /* cpu_register_physical_memory_log() wants region_offset for
+     * mmio, but prefers offseting phys_offset for RAM.  Humour it.
+     */
+    if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
+        phys_offset += region_offset;
+        region_offset = 0;
+    }
+
+    cpu_register_physical_memory_log(fr->addr.start,
+                                     fr->addr.size,
+                                     phys_offset,
+                                     region_offset,
+                                     fr->dirty_log_mask);
+}
+
+static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
+{
+    cpu_register_physical_memory(fr->addr.start, fr->addr.size,
+                                 IO_MEM_UNASSIGNED);
+}
+
+static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
+{
+    cpu_physical_log_start(fr->addr.start, fr->addr.size);
+}
+
+static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
+{
+    cpu_physical_log_stop(fr->addr.start, fr->addr.size);
+}
+
+static const AddressSpaceOps address_space_ops_memory = {
+    .range_add = as_memory_range_add,
+    .range_del = as_memory_range_del,
+    .log_start = as_memory_log_start,
+    .log_stop = as_memory_log_stop,
+};
+
+static AddressSpace address_space_memory = {
+    .ops = &address_space_ops_memory,
+};
+
 /* Render a memory region into the global view.  Ranges in @view obscure
  * ranges in @mr.
  */
@@ -236,13 +298,12 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
     return view;
 }
 
-static void memory_region_update_topology(void)
+static void address_space_update_topology(AddressSpace *as)
 {
-    FlatView old_view = current_memory_map;
-    FlatView new_view = generate_memory_topology(root_memory_region);
+    FlatView old_view = as->current_map;
+    FlatView new_view = generate_memory_topology(as->root);
     unsigned iold, inew;
     FlatRange *frold, *frnew;
-    ram_addr_t phys_offset, region_offset;
 
     /* Generate a symmetric difference of the old and new memory maps.
      * Kill ranges in the old map, and instantiate ranges in the new map.
@@ -267,16 +328,15 @@ static void memory_region_update_topology(void)
                     && !flatrange_equal(frold, frnew)))) {
             /* In old, but (not in new, or in new but attributes changed). */
 
-            cpu_register_physical_memory(frold->addr.start, frold->addr.size,
-                                         IO_MEM_UNASSIGNED);
+            as->ops->range_del(as, frold);
             ++iold;
         } else if (frold && frnew && flatrange_equal(frold, frnew)) {
             /* In both (logging may have changed) */
 
             if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
-                cpu_physical_log_stop(frnew->addr.start, frnew->addr.size);
+                as->ops->log_stop(as, frnew);
             } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
-                cpu_physical_log_start(frnew->addr.start, frnew->addr.size);
+                as->ops->log_start(as, frnew);
             }
 
             ++iold;
@@ -284,28 +344,19 @@ static void memory_region_update_topology(void)
         } else {
             /* In new */
 
-            phys_offset = frnew->mr->ram_addr;
-            region_offset = frnew->offset_in_region;
-            /* cpu_register_physical_memory_log() wants region_offset for
-             * mmio, but prefers offseting phys_offset for RAM.  Humour it.
-             */
-            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
-                phys_offset += region_offset;
-                region_offset = 0;
-            }
-
-            cpu_register_physical_memory_log(frnew->addr.start,
-                                             frnew->addr.size,
-                                             phys_offset,
-                                             region_offset,
-                                             frnew->dirty_log_mask);
+            as->ops->range_add(as, frnew);
             ++inew;
         }
     }
-    current_memory_map = new_view;
+    as->current_map = new_view;
     flatview_destroy(&old_view);
 }
 
+static void memory_region_update_topology(void)
+{
+    address_space_update_topology(&address_space_memory);
+}
+
 void memory_region_init(MemoryRegion *mr,
                         const char *name,
                         uint64_t size)
@@ -551,7 +602,7 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 {
     FlatRange *fr;
 
-    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+    FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
         if (fr->mr == mr) {
             cpu_physical_sync_dirty_bitmap(fr->addr.start,
                                            fr->addr.start + fr->addr.size);
@@ -592,7 +643,7 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr)
     CoalescedMemoryRange *cmr;
     AddrRange tmp;
 
-    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+    FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
         if (fr->mr == mr) {
             qemu_unregister_coalesced_mmio(fr->addr.start, fr->addr.size);
             QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
@@ -702,6 +753,6 @@ void memory_region_del_subregion(MemoryRegion *mr,
 
 void set_system_memory_map(MemoryRegion *mr)
 {
-    root_memory_region = mr;
+    address_space_memory.root = mr;
     memory_region_update_topology();
 }
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 05/23] memory: abstract address space operations
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Prepare for multiple address space support by abstracting away the details
of registering a memory range with qemu's flat representation into an
AddressSpace object.

Note operations which are memory specific are not abstracted, since they will
never be called on I/O address spaces anyway.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |  111 +++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 81 insertions(+), 30 deletions(-)

diff --git a/memory.c b/memory.c
index 48470d2..7187223 100644
--- a/memory.c
+++ b/memory.c
@@ -82,12 +82,26 @@ struct FlatView {
     unsigned nr_allocated;
 };
 
+typedef struct AddressSpace AddressSpace;
+typedef struct AddressSpaceOps AddressSpaceOps;
+
+/* A system address space - I/O, memory, etc. */
+struct AddressSpace {
+    const AddressSpaceOps *ops;
+    MemoryRegion *root;
+    FlatView current_map;
+};
+
+struct AddressSpaceOps {
+    void (*range_add)(AddressSpace *as, FlatRange *fr);
+    void (*range_del)(AddressSpace *as, FlatRange *fr);
+    void (*log_start)(AddressSpace *as, FlatRange *fr);
+    void (*log_stop)(AddressSpace *as, FlatRange *fr);
+};
+
 #define FOR_EACH_FLAT_RANGE(var, view)          \
     for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
 
-static FlatView current_memory_map;
-static MemoryRegion *root_memory_region;
-
 static bool flatrange_equal(FlatRange *a, FlatRange *b)
 {
     return a->mr == b->mr
@@ -144,6 +158,54 @@ static void flatview_simplify(FlatView *view)
     }
 }
 
+static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
+{
+    ram_addr_t phys_offset, region_offset;
+
+    phys_offset = fr->mr->ram_addr;
+    region_offset = fr->offset_in_region;
+    /* cpu_register_physical_memory_log() wants region_offset for
+     * mmio, but prefers offseting phys_offset for RAM.  Humour it.
+     */
+    if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
+        phys_offset += region_offset;
+        region_offset = 0;
+    }
+
+    cpu_register_physical_memory_log(fr->addr.start,
+                                     fr->addr.size,
+                                     phys_offset,
+                                     region_offset,
+                                     fr->dirty_log_mask);
+}
+
+static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
+{
+    cpu_register_physical_memory(fr->addr.start, fr->addr.size,
+                                 IO_MEM_UNASSIGNED);
+}
+
+static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
+{
+    cpu_physical_log_start(fr->addr.start, fr->addr.size);
+}
+
+static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
+{
+    cpu_physical_log_stop(fr->addr.start, fr->addr.size);
+}
+
+static const AddressSpaceOps address_space_ops_memory = {
+    .range_add = as_memory_range_add,
+    .range_del = as_memory_range_del,
+    .log_start = as_memory_log_start,
+    .log_stop = as_memory_log_stop,
+};
+
+static AddressSpace address_space_memory = {
+    .ops = &address_space_ops_memory,
+};
+
 /* Render a memory region into the global view.  Ranges in @view obscure
  * ranges in @mr.
  */
@@ -236,13 +298,12 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
     return view;
 }
 
-static void memory_region_update_topology(void)
+static void address_space_update_topology(AddressSpace *as)
 {
-    FlatView old_view = current_memory_map;
-    FlatView new_view = generate_memory_topology(root_memory_region);
+    FlatView old_view = as->current_map;
+    FlatView new_view = generate_memory_topology(as->root);
     unsigned iold, inew;
     FlatRange *frold, *frnew;
-    ram_addr_t phys_offset, region_offset;
 
     /* Generate a symmetric difference of the old and new memory maps.
      * Kill ranges in the old map, and instantiate ranges in the new map.
@@ -267,16 +328,15 @@ static void memory_region_update_topology(void)
                     && !flatrange_equal(frold, frnew)))) {
             /* In old, but (not in new, or in new but attributes changed). */
 
-            cpu_register_physical_memory(frold->addr.start, frold->addr.size,
-                                         IO_MEM_UNASSIGNED);
+            as->ops->range_del(as, frold);
             ++iold;
         } else if (frold && frnew && flatrange_equal(frold, frnew)) {
             /* In both (logging may have changed) */
 
             if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
-                cpu_physical_log_stop(frnew->addr.start, frnew->addr.size);
+                as->ops->log_stop(as, frnew);
             } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
-                cpu_physical_log_start(frnew->addr.start, frnew->addr.size);
+                as->ops->log_start(as, frnew);
             }
 
             ++iold;
@@ -284,28 +344,19 @@ static void memory_region_update_topology(void)
         } else {
             /* In new */
 
-            phys_offset = frnew->mr->ram_addr;
-            region_offset = frnew->offset_in_region;
-            /* cpu_register_physical_memory_log() wants region_offset for
-             * mmio, but prefers offseting phys_offset for RAM.  Humour it.
-             */
-            if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
-                phys_offset += region_offset;
-                region_offset = 0;
-            }
-
-            cpu_register_physical_memory_log(frnew->addr.start,
-                                             frnew->addr.size,
-                                             phys_offset,
-                                             region_offset,
-                                             frnew->dirty_log_mask);
+            as->ops->range_add(as, frnew);
             ++inew;
         }
     }
-    current_memory_map = new_view;
+    as->current_map = new_view;
     flatview_destroy(&old_view);
 }
 
+static void memory_region_update_topology(void)
+{
+    address_space_update_topology(&address_space_memory);
+}
+
 void memory_region_init(MemoryRegion *mr,
                         const char *name,
                         uint64_t size)
@@ -551,7 +602,7 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 {
     FlatRange *fr;
 
-    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+    FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
         if (fr->mr == mr) {
             cpu_physical_sync_dirty_bitmap(fr->addr.start,
                                            fr->addr.start + fr->addr.size);
@@ -592,7 +643,7 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr)
     CoalescedMemoryRange *cmr;
     AddrRange tmp;
 
-    FOR_EACH_FLAT_RANGE(fr, &current_memory_map) {
+    FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
         if (fr->mr == mr) {
             qemu_unregister_coalesced_mmio(fr->addr.start, fr->addr.size);
             QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
@@ -702,6 +753,6 @@ void memory_region_del_subregion(MemoryRegion *mr,
 
 void set_system_memory_map(MemoryRegion *mr)
 {
-    root_memory_region = mr;
+    address_space_memory.root = mr;
     memory_region_update_topology();
 }
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 06/23] memory: rename MemoryRegion::has_ram_addr to ::terminates
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

I/O regions will not have ram_addrs, so this is a better name.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   18 +++++++++---------
 memory.h |    2 +-
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/memory.c b/memory.c
index 7187223..5fda4a0 100644
--- a/memory.c
+++ b/memory.c
@@ -244,7 +244,7 @@ static void render_memory_region(FlatView *view,
         render_memory_region(view, subregion, base, clip);
     }
 
-    if (!mr->has_ram_addr) {
+    if (!mr->terminates) {
         return;
     }
 
@@ -366,7 +366,7 @@ void memory_region_init(MemoryRegion *mr,
     mr->size = size;
     mr->addr = 0;
     mr->offset = 0;
-    mr->has_ram_addr = false;
+    mr->terminates = false;
     mr->priority = 0;
     mr->may_overlap = false;
     mr->alias = NULL;
@@ -521,7 +521,7 @@ void memory_region_init_io(MemoryRegion *mr,
     memory_region_init(mr, name, size);
     mr->ops = ops;
     mr->opaque = opaque;
-    mr->has_ram_addr = true;
+    mr->terminates = true;
     mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
                                           memory_region_write_thunk,
                                           mr,
@@ -534,7 +534,7 @@ void memory_region_init_ram(MemoryRegion *mr,
                             uint64_t size)
 {
     memory_region_init(mr, name, size);
-    mr->has_ram_addr = true;
+    mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc(dev, name, size);
 }
 
@@ -545,7 +545,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
                                 void *ptr)
 {
     memory_region_init(mr, name, size);
-    mr->has_ram_addr = true;
+    mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
 }
 
@@ -588,13 +588,13 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                              unsigned client)
 {
-    assert(mr->has_ram_addr);
+    assert(mr->terminates);
     return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
 }
 
 void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
 {
-    assert(mr->has_ram_addr);
+    assert(mr->terminates);
     return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
 }
 
@@ -618,7 +618,7 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
 void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                                target_phys_addr_t size, unsigned client)
 {
-    assert(mr->has_ram_addr);
+    assert(mr->terminates);
     cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
                                     mr->ram_addr + addr + size,
                                     1 << client);
@@ -630,7 +630,7 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr)
         return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
     }
 
-    if (!mr->has_ram_addr) {
+    if (!mr->terminates) {
         abort();
     }
 
diff --git a/memory.h b/memory.h
index 8873f75..2ad7202 100644
--- a/memory.h
+++ b/memory.h
@@ -77,7 +77,7 @@ struct MemoryRegion {
     target_phys_addr_t addr;
     target_phys_addr_t offset;
     ram_addr_t ram_addr;
-    bool has_ram_addr;
+    bool terminates;
     MemoryRegion *alias;
     target_phys_addr_t alias_offset;
     unsigned priority;
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 06/23] memory: rename MemoryRegion::has_ram_addr to ::terminates
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

I/O regions will not have ram_addrs, so this is a better name.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   18 +++++++++---------
 memory.h |    2 +-
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/memory.c b/memory.c
index 7187223..5fda4a0 100644
--- a/memory.c
+++ b/memory.c
@@ -244,7 +244,7 @@ static void render_memory_region(FlatView *view,
         render_memory_region(view, subregion, base, clip);
     }
 
-    if (!mr->has_ram_addr) {
+    if (!mr->terminates) {
         return;
     }
 
@@ -366,7 +366,7 @@ void memory_region_init(MemoryRegion *mr,
     mr->size = size;
     mr->addr = 0;
     mr->offset = 0;
-    mr->has_ram_addr = false;
+    mr->terminates = false;
     mr->priority = 0;
     mr->may_overlap = false;
     mr->alias = NULL;
@@ -521,7 +521,7 @@ void memory_region_init_io(MemoryRegion *mr,
     memory_region_init(mr, name, size);
     mr->ops = ops;
     mr->opaque = opaque;
-    mr->has_ram_addr = true;
+    mr->terminates = true;
     mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
                                           memory_region_write_thunk,
                                           mr,
@@ -534,7 +534,7 @@ void memory_region_init_ram(MemoryRegion *mr,
                             uint64_t size)
 {
     memory_region_init(mr, name, size);
-    mr->has_ram_addr = true;
+    mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc(dev, name, size);
 }
 
@@ -545,7 +545,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
                                 void *ptr)
 {
     memory_region_init(mr, name, size);
-    mr->has_ram_addr = true;
+    mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
 }
 
@@ -588,13 +588,13 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
 bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                              unsigned client)
 {
-    assert(mr->has_ram_addr);
+    assert(mr->terminates);
     return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
 }
 
 void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
 {
-    assert(mr->has_ram_addr);
+    assert(mr->terminates);
     return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
 }
 
@@ -618,7 +618,7 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
 void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
                                target_phys_addr_t size, unsigned client)
 {
-    assert(mr->has_ram_addr);
+    assert(mr->terminates);
     cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
                                     mr->ram_addr + addr + size,
                                     1 << client);
@@ -630,7 +630,7 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr)
         return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
     }
 
-    if (!mr->has_ram_addr) {
+    if (!mr->terminates) {
         abort();
     }
 
diff --git a/memory.h b/memory.h
index 8873f75..2ad7202 100644
--- a/memory.h
+++ b/memory.h
@@ -77,7 +77,7 @@ struct MemoryRegion {
     target_phys_addr_t addr;
     target_phys_addr_t offset;
     ram_addr_t ram_addr;
-    bool has_ram_addr;
+    bool terminates;
     MemoryRegion *alias;
     target_phys_addr_t alias_offset;
     unsigned priority;
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 07/23] memory: late initialization of ram_addr
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

For non-RAM memory regions, we cannot tell whether this is an I/O region
or an MMIO region.  Since the qemu backing registration is different for
the two, we have to defer initialization until we know which address
space we are in.

These shenanigans will be removed once the backing registration is unified
with the memory API.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   24 ++++++++++++++++++++----
 memory.h |    1 +
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/memory.c b/memory.c
index 5fda4a0..bc8bfa2 100644
--- a/memory.c
+++ b/memory.c
@@ -158,10 +158,14 @@ static void flatview_simplify(FlatView *view)
     }
 }
 
+static void memory_region_prepare_ram_addr(MemoryRegion *mr);
+
 static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
 {
     ram_addr_t phys_offset, region_offset;
 
+    memory_region_prepare_ram_addr(fr->mr);
+
     phys_offset = fr->mr->ram_addr;
     region_offset = fr->offset_in_region;
     /* cpu_register_physical_memory_log() wants region_offset for
@@ -512,6 +516,19 @@ static CPUWriteMemoryFunc * const memory_region_write_thunk[] = {
     memory_region_write_thunk_l,
 };
 
+static void memory_region_prepare_ram_addr(MemoryRegion *mr)
+{
+    if (mr->backend_registered) {
+        return;
+    }
+
+    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
+                                          memory_region_write_thunk,
+                                          mr,
+                                          mr->ops->endianness);
+    mr->backend_registered = true;
+}
+
 void memory_region_init_io(MemoryRegion *mr,
                            const MemoryRegionOps *ops,
                            void *opaque,
@@ -522,10 +539,7 @@ void memory_region_init_io(MemoryRegion *mr,
     mr->ops = ops;
     mr->opaque = opaque;
     mr->terminates = true;
-    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
-                                          memory_region_write_thunk,
-                                          mr,
-                                          mr->ops->endianness);
+    mr->backend_registered = false;
 }
 
 void memory_region_init_ram(MemoryRegion *mr,
@@ -536,6 +550,7 @@ void memory_region_init_ram(MemoryRegion *mr,
     memory_region_init(mr, name, size);
     mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc(dev, name, size);
+    mr->backend_registered = true;
 }
 
 void memory_region_init_ram_ptr(MemoryRegion *mr,
@@ -547,6 +562,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
     memory_region_init(mr, name, size);
     mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
+    mr->backend_registered = true;
 }
 
 void memory_region_init_alias(MemoryRegion *mr,
diff --git a/memory.h b/memory.h
index 2ad7202..0994b18 100644
--- a/memory.h
+++ b/memory.h
@@ -76,6 +76,7 @@ struct MemoryRegion {
     uint64_t size;
     target_phys_addr_t addr;
     target_phys_addr_t offset;
+    bool backend_registered;
     ram_addr_t ram_addr;
     bool terminates;
     MemoryRegion *alias;
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 07/23] memory: late initialization of ram_addr
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

For non-RAM memory regions, we cannot tell whether this is an I/O region
or an MMIO region.  Since the qemu backing registration is different for
the two, we have to defer initialization until we know which address
space we are in.

These shenanigans will be removed once the backing registration is unified
with the memory API.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   24 ++++++++++++++++++++----
 memory.h |    1 +
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/memory.c b/memory.c
index 5fda4a0..bc8bfa2 100644
--- a/memory.c
+++ b/memory.c
@@ -158,10 +158,14 @@ static void flatview_simplify(FlatView *view)
     }
 }
 
+static void memory_region_prepare_ram_addr(MemoryRegion *mr);
+
 static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
 {
     ram_addr_t phys_offset, region_offset;
 
+    memory_region_prepare_ram_addr(fr->mr);
+
     phys_offset = fr->mr->ram_addr;
     region_offset = fr->offset_in_region;
     /* cpu_register_physical_memory_log() wants region_offset for
@@ -512,6 +516,19 @@ static CPUWriteMemoryFunc * const memory_region_write_thunk[] = {
     memory_region_write_thunk_l,
 };
 
+static void memory_region_prepare_ram_addr(MemoryRegion *mr)
+{
+    if (mr->backend_registered) {
+        return;
+    }
+
+    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
+                                          memory_region_write_thunk,
+                                          mr,
+                                          mr->ops->endianness);
+    mr->backend_registered = true;
+}
+
 void memory_region_init_io(MemoryRegion *mr,
                            const MemoryRegionOps *ops,
                            void *opaque,
@@ -522,10 +539,7 @@ void memory_region_init_io(MemoryRegion *mr,
     mr->ops = ops;
     mr->opaque = opaque;
     mr->terminates = true;
-    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
-                                          memory_region_write_thunk,
-                                          mr,
-                                          mr->ops->endianness);
+    mr->backend_registered = false;
 }
 
 void memory_region_init_ram(MemoryRegion *mr,
@@ -536,6 +550,7 @@ void memory_region_init_ram(MemoryRegion *mr,
     memory_region_init(mr, name, size);
     mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc(dev, name, size);
+    mr->backend_registered = true;
 }
 
 void memory_region_init_ram_ptr(MemoryRegion *mr,
@@ -547,6 +562,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
     memory_region_init(mr, name, size);
     mr->terminates = true;
     mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
+    mr->backend_registered = true;
 }
 
 void memory_region_init_alias(MemoryRegion *mr,
diff --git a/memory.h b/memory.h
index 2ad7202..0994b18 100644
--- a/memory.h
+++ b/memory.h
@@ -76,6 +76,7 @@ struct MemoryRegion {
     uint64_t size;
     target_phys_addr_t addr;
     target_phys_addr_t offset;
+    bool backend_registered;
     ram_addr_t ram_addr;
     bool terminates;
     MemoryRegion *alias;
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 08/23] memory:  I/O address space support
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Allow registering I/O ports via the same mechanism as mmio ranges.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 exec-memory.h |    3 ++
 memory.c      |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 memory.h      |    2 +
 3 files changed, 64 insertions(+), 1 deletions(-)

diff --git a/exec-memory.h b/exec-memory.h
index 7eb9085..aad21b5 100644
--- a/exec-memory.h
+++ b/exec-memory.h
@@ -18,6 +18,9 @@ MemoryRegion *get_system_memory(void);
 /* Set the root memory region.  This region is the system memory map. */
 void set_system_memory_map(MemoryRegion *mr);
 
+/* Set the I/O memory region.  This region is the I/O memory map. */
+void set_system_io_map(MemoryRegion *mr);
+
 #endif
 
 #endif
diff --git a/memory.c b/memory.c
index bc8bfa2..62bd60b 100644
--- a/memory.c
+++ b/memory.c
@@ -13,6 +13,7 @@
 
 #include "memory.h"
 #include "exec-memory.h"
+#include "ioport.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -210,6 +211,52 @@ static AddressSpace address_space_memory = {
     .ops = &address_space_ops_memory,
 };
 
+static void memory_region_iorange_read(IORange *iorange,
+                                       uint64_t offset,
+                                       unsigned width,
+                                       uint64_t *data)
+{
+    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+
+    *data = mr->ops->read(mr->opaque, offset, width);
+}
+
+static void memory_region_iorange_write(IORange *iorange,
+                                        uint64_t offset,
+                                        unsigned width,
+                                        uint64_t data)
+{
+    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+
+    mr->ops->write(mr->opaque, offset, data, width);
+}
+
+static const IORangeOps memory_region_iorange_ops = {
+    .read = memory_region_iorange_read,
+    .write = memory_region_iorange_write,
+};
+
+static void as_io_range_add(AddressSpace *as, FlatRange *fr)
+{
+    iorange_init(&fr->mr->iorange, &memory_region_iorange_ops,
+                 fr->addr.start,fr->addr.size);
+    ioport_register(&fr->mr->iorange);
+}
+
+static void as_io_range_del(AddressSpace *as, FlatRange *fr)
+{
+    isa_unassign_ioport(fr->addr.start, fr->addr.size);
+}
+
+static const AddressSpaceOps address_space_ops_io = {
+    .range_add = as_io_range_add,
+    .range_del = as_io_range_del,
+};
+
+static AddressSpace address_space_io = {
+    .ops = &address_space_ops_io,
+};
+
 /* Render a memory region into the global view.  Ranges in @view obscure
  * ranges in @mr.
  */
@@ -358,7 +405,12 @@ static void address_space_update_topology(AddressSpace *as)
 
 static void memory_region_update_topology(void)
 {
-    address_space_update_topology(&address_space_memory);
+    if (address_space_memory.root) {
+        address_space_update_topology(&address_space_memory);
+    }
+    if (address_space_io.root) {
+        address_space_update_topology(&address_space_io);
+    }
 }
 
 void memory_region_init(MemoryRegion *mr,
@@ -772,3 +824,9 @@ void set_system_memory_map(MemoryRegion *mr)
     address_space_memory.root = mr;
     memory_region_update_topology();
 }
+
+void set_system_io_map(MemoryRegion *mr)
+{
+    address_space_io.root = mr;
+    memory_region_update_topology();
+}
diff --git a/memory.h b/memory.h
index 0994b18..2afbf13 100644
--- a/memory.h
+++ b/memory.h
@@ -9,6 +9,7 @@
 #include "cpu-common.h"
 #include "targphys.h"
 #include "qemu-queue.h"
+#include "iorange.h"
 
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegion MemoryRegion;
@@ -78,6 +79,7 @@ struct MemoryRegion {
     target_phys_addr_t offset;
     bool backend_registered;
     ram_addr_t ram_addr;
+    IORange iorange;
     bool terminates;
     MemoryRegion *alias;
     target_phys_addr_t alias_offset;
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 08/23] memory:  I/O address space support
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Allow registering I/O ports via the same mechanism as mmio ranges.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 exec-memory.h |    3 ++
 memory.c      |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 memory.h      |    2 +
 3 files changed, 64 insertions(+), 1 deletions(-)

diff --git a/exec-memory.h b/exec-memory.h
index 7eb9085..aad21b5 100644
--- a/exec-memory.h
+++ b/exec-memory.h
@@ -18,6 +18,9 @@ MemoryRegion *get_system_memory(void);
 /* Set the root memory region.  This region is the system memory map. */
 void set_system_memory_map(MemoryRegion *mr);
 
+/* Set the I/O memory region.  This region is the I/O memory map. */
+void set_system_io_map(MemoryRegion *mr);
+
 #endif
 
 #endif
diff --git a/memory.c b/memory.c
index bc8bfa2..62bd60b 100644
--- a/memory.c
+++ b/memory.c
@@ -13,6 +13,7 @@
 
 #include "memory.h"
 #include "exec-memory.h"
+#include "ioport.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -210,6 +211,52 @@ static AddressSpace address_space_memory = {
     .ops = &address_space_ops_memory,
 };
 
+static void memory_region_iorange_read(IORange *iorange,
+                                       uint64_t offset,
+                                       unsigned width,
+                                       uint64_t *data)
+{
+    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+
+    *data = mr->ops->read(mr->opaque, offset, width);
+}
+
+static void memory_region_iorange_write(IORange *iorange,
+                                        uint64_t offset,
+                                        unsigned width,
+                                        uint64_t data)
+{
+    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
+
+    mr->ops->write(mr->opaque, offset, data, width);
+}
+
+static const IORangeOps memory_region_iorange_ops = {
+    .read = memory_region_iorange_read,
+    .write = memory_region_iorange_write,
+};
+
+static void as_io_range_add(AddressSpace *as, FlatRange *fr)
+{
+    iorange_init(&fr->mr->iorange, &memory_region_iorange_ops,
+                 fr->addr.start,fr->addr.size);
+    ioport_register(&fr->mr->iorange);
+}
+
+static void as_io_range_del(AddressSpace *as, FlatRange *fr)
+{
+    isa_unassign_ioport(fr->addr.start, fr->addr.size);
+}
+
+static const AddressSpaceOps address_space_ops_io = {
+    .range_add = as_io_range_add,
+    .range_del = as_io_range_del,
+};
+
+static AddressSpace address_space_io = {
+    .ops = &address_space_ops_io,
+};
+
 /* Render a memory region into the global view.  Ranges in @view obscure
  * ranges in @mr.
  */
@@ -358,7 +405,12 @@ static void address_space_update_topology(AddressSpace *as)
 
 static void memory_region_update_topology(void)
 {
-    address_space_update_topology(&address_space_memory);
+    if (address_space_memory.root) {
+        address_space_update_topology(&address_space_memory);
+    }
+    if (address_space_io.root) {
+        address_space_update_topology(&address_space_io);
+    }
 }
 
 void memory_region_init(MemoryRegion *mr,
@@ -772,3 +824,9 @@ void set_system_memory_map(MemoryRegion *mr)
     address_space_memory.root = mr;
     memory_region_update_topology();
 }
+
+void set_system_io_map(MemoryRegion *mr)
+{
+    address_space_io.root = mr;
+    memory_region_update_topology();
+}
diff --git a/memory.h b/memory.h
index 0994b18..2afbf13 100644
--- a/memory.h
+++ b/memory.h
@@ -9,6 +9,7 @@
 #include "cpu-common.h"
 #include "targphys.h"
 #include "qemu-queue.h"
+#include "iorange.h"
 
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegion MemoryRegion;
@@ -78,6 +79,7 @@ struct MemoryRegion {
     target_phys_addr_t offset;
     bool backend_registered;
     ram_addr_t ram_addr;
+    IORange iorange;
     bool terminates;
     MemoryRegion *alias;
     target_phys_addr_t alias_offset;
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 09/23] memory: add backward compatibility for old portio registration
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   32 ++++++++++++++++++++++++++++++++
 memory.h |   17 +++++++++++++++++
 2 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index 62bd60b..bb04952 100644
--- a/memory.c
+++ b/memory.c
@@ -211,6 +211,21 @@ static AddressSpace address_space_memory = {
     .ops = &address_space_ops_memory,
 };
 
+static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset,
+                                             unsigned width, bool write)
+{
+    const MemoryRegionPortio *mrp;
+
+    for (mrp = mr->ops->old_portio; mrp->size; ++mrp) {
+        if (offset >= mrp->offset && offset < mrp->offset + mrp->len
+            && width == mrp->size
+            && (write ? (bool)mrp->write : (bool)mrp->read)) {
+            return mrp;
+        }
+    }
+    return NULL;
+}
+
 static void memory_region_iorange_read(IORange *iorange,
                                        uint64_t offset,
                                        unsigned width,
@@ -218,6 +233,15 @@ static void memory_region_iorange_read(IORange *iorange,
 {
     MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
 
+    if (mr->ops->old_portio) {
+        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, false);
+
+        *data = ((uint64_t)1 << (width * 8)) - 1;
+        if (mrp) {
+            *data = mrp->read(mr->opaque, offset - mrp->offset);
+        }
+        return;
+    }
     *data = mr->ops->read(mr->opaque, offset, width);
 }
 
@@ -228,6 +252,14 @@ static void memory_region_iorange_write(IORange *iorange,
 {
     MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
 
+    if (mr->ops->old_portio) {
+        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true);
+
+        if (mrp) {
+            mrp->write(mr->opaque, offset - mrp->offset, data);
+        }
+        return;
+    }
     mr->ops->write(mr->opaque, offset, data, width);
 }
 
diff --git a/memory.h b/memory.h
index 2afbf13..f026eae 100644
--- a/memory.h
+++ b/memory.h
@@ -10,9 +10,11 @@
 #include "targphys.h"
 #include "qemu-queue.h"
 #include "iorange.h"
+#include "ioport.h"
 
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegion MemoryRegion;
+typedef struct MemoryRegionPortio MemoryRegionPortio;
 
 /* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
  * registration.
@@ -65,6 +67,11 @@ struct MemoryRegionOps {
          */
          bool unaligned;
     } impl;
+
+    /* If .read and .write are not present, old_portio may be used for
+     * backwards compatibility with old portio registration
+     */
+    const MemoryRegionPortio *old_portio;
 };
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
@@ -92,6 +99,16 @@ struct MemoryRegion {
     uint8_t dirty_log_mask;
 };
 
+struct MemoryRegionPortio {
+    uint32_t offset;
+    uint32_t len;
+    unsigned size;
+    IOPortReadFunc *read;
+    IOPortWriteFunc *write;
+};
+
+#define PORTIO_END { }
+
 /* Initialize a memory region
  *
  * The region typically acts as a container for other memory regions.
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 09/23] memory: add backward compatibility for old portio registration
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   32 ++++++++++++++++++++++++++++++++
 memory.h |   17 +++++++++++++++++
 2 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index 62bd60b..bb04952 100644
--- a/memory.c
+++ b/memory.c
@@ -211,6 +211,21 @@ static AddressSpace address_space_memory = {
     .ops = &address_space_ops_memory,
 };
 
+static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset,
+                                             unsigned width, bool write)
+{
+    const MemoryRegionPortio *mrp;
+
+    for (mrp = mr->ops->old_portio; mrp->size; ++mrp) {
+        if (offset >= mrp->offset && offset < mrp->offset + mrp->len
+            && width == mrp->size
+            && (write ? (bool)mrp->write : (bool)mrp->read)) {
+            return mrp;
+        }
+    }
+    return NULL;
+}
+
 static void memory_region_iorange_read(IORange *iorange,
                                        uint64_t offset,
                                        unsigned width,
@@ -218,6 +233,15 @@ static void memory_region_iorange_read(IORange *iorange,
 {
     MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
 
+    if (mr->ops->old_portio) {
+        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, false);
+
+        *data = ((uint64_t)1 << (width * 8)) - 1;
+        if (mrp) {
+            *data = mrp->read(mr->opaque, offset - mrp->offset);
+        }
+        return;
+    }
     *data = mr->ops->read(mr->opaque, offset, width);
 }
 
@@ -228,6 +252,14 @@ static void memory_region_iorange_write(IORange *iorange,
 {
     MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
 
+    if (mr->ops->old_portio) {
+        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true);
+
+        if (mrp) {
+            mrp->write(mr->opaque, offset - mrp->offset, data);
+        }
+        return;
+    }
     mr->ops->write(mr->opaque, offset, data, width);
 }
 
diff --git a/memory.h b/memory.h
index 2afbf13..f026eae 100644
--- a/memory.h
+++ b/memory.h
@@ -10,9 +10,11 @@
 #include "targphys.h"
 #include "qemu-queue.h"
 #include "iorange.h"
+#include "ioport.h"
 
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegion MemoryRegion;
+typedef struct MemoryRegionPortio MemoryRegionPortio;
 
 /* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
  * registration.
@@ -65,6 +67,11 @@ struct MemoryRegionOps {
          */
          bool unaligned;
     } impl;
+
+    /* If .read and .write are not present, old_portio may be used for
+     * backwards compatibility with old portio registration
+     */
+    const MemoryRegionPortio *old_portio;
 };
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
@@ -92,6 +99,16 @@ struct MemoryRegion {
     uint8_t dirty_log_mask;
 };
 
+struct MemoryRegionPortio {
+    uint32_t offset;
+    uint32_t len;
+    unsigned size;
+    IOPortReadFunc *read;
+    IOPortWriteFunc *write;
+};
+
+#define PORTIO_END { }
+
 /* Initialize a memory region
  *
  * The region typically acts as a container for other memory regions.
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 10/23] memory: add backward compatibility for old mmio registration
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

This eases the transition to the new API.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   10 ++++++++++
 memory.h |   10 ++++++++++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index bb04952..e4446a0 100644
--- a/memory.c
+++ b/memory.c
@@ -14,6 +14,7 @@
 #include "memory.h"
 #include "exec-memory.h"
 #include "ioport.h"
+#include "bitops.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -499,6 +500,10 @@ static uint32_t memory_region_read_thunk_n(void *_mr,
         return -1U; /* FIXME: better signalling */
     }
 
+    if (!mr->ops->read) {
+        return mr->ops->old_mmio.read[bitops_ffsl(size)](mr->opaque, addr);
+    }
+
     /* FIXME: support unaligned access */
 
     access_size_min = mr->ops->impl.min_access_size;
@@ -535,6 +540,11 @@ static void memory_region_write_thunk_n(void *_mr,
         return; /* FIXME: better signalling */
     }
 
+    if (!mr->ops->write) {
+        mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data);
+        return;
+    }
+
     /* FIXME: support unaligned access */
 
     access_size_min = mr->ops->impl.min_access_size;
diff --git a/memory.h b/memory.h
index f026eae..4624946 100644
--- a/memory.h
+++ b/memory.h
@@ -15,6 +15,7 @@
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegion MemoryRegion;
 typedef struct MemoryRegionPortio MemoryRegionPortio;
+typedef struct MemoryRegionMmio MemoryRegionMmio;
 
 /* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
  * registration.
@@ -23,6 +24,11 @@ typedef struct MemoryRegionPortio MemoryRegionPortio;
 #define DIRTY_MEMORY_CODE      1
 #define DIRTY_MEMORY_MIGRATION 3
 
+struct MemoryRegionMmio {
+    CPUReadMemoryFunc *read[3];
+    CPUWriteMemoryFunc *write[3];
+};
+
 /*
  * Memory region callbacks
  */
@@ -72,6 +78,10 @@ struct MemoryRegionOps {
      * backwards compatibility with old portio registration
      */
     const MemoryRegionPortio *old_portio;
+    /* If .read and .write are not present, old_mmio may be used for
+     * backwards compatibility with old mmio registration
+     */
+    const MemoryRegionMmio old_mmio;
 };
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 10/23] memory: add backward compatibility for old mmio registration
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

This eases the transition to the new API.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   10 ++++++++++
 memory.h |   10 ++++++++++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index bb04952..e4446a0 100644
--- a/memory.c
+++ b/memory.c
@@ -14,6 +14,7 @@
 #include "memory.h"
 #include "exec-memory.h"
 #include "ioport.h"
+#include "bitops.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -499,6 +500,10 @@ static uint32_t memory_region_read_thunk_n(void *_mr,
         return -1U; /* FIXME: better signalling */
     }
 
+    if (!mr->ops->read) {
+        return mr->ops->old_mmio.read[bitops_ffsl(size)](mr->opaque, addr);
+    }
+
     /* FIXME: support unaligned access */
 
     access_size_min = mr->ops->impl.min_access_size;
@@ -535,6 +540,11 @@ static void memory_region_write_thunk_n(void *_mr,
         return; /* FIXME: better signalling */
     }
 
+    if (!mr->ops->write) {
+        mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data);
+        return;
+    }
+
     /* FIXME: support unaligned access */
 
     access_size_min = mr->ops->impl.min_access_size;
diff --git a/memory.h b/memory.h
index f026eae..4624946 100644
--- a/memory.h
+++ b/memory.h
@@ -15,6 +15,7 @@
 typedef struct MemoryRegionOps MemoryRegionOps;
 typedef struct MemoryRegion MemoryRegion;
 typedef struct MemoryRegionPortio MemoryRegionPortio;
+typedef struct MemoryRegionMmio MemoryRegionMmio;
 
 /* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
  * registration.
@@ -23,6 +24,11 @@ typedef struct MemoryRegionPortio MemoryRegionPortio;
 #define DIRTY_MEMORY_CODE      1
 #define DIRTY_MEMORY_MIGRATION 3
 
+struct MemoryRegionMmio {
+    CPUReadMemoryFunc *read[3];
+    CPUWriteMemoryFunc *write[3];
+};
+
 /*
  * Memory region callbacks
  */
@@ -72,6 +78,10 @@ struct MemoryRegionOps {
      * backwards compatibility with old portio registration
      */
     const MemoryRegionPortio *old_portio;
+    /* If .read and .write are not present, old_mmio may be used for
+     * backwards compatibility with old mmio registration
+     */
+    const MemoryRegionMmio old_mmio;
 };
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 11/23] memory: add ioeventfd support
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

As with the rest of the memory API, the caller associates an eventfd
with an address, and the memory API takes care of registering or
unregistering when the address is made visible or invisible to the
guest.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |  230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory.h |   20 ++++++
 2 files changed, 250 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index e4446a0..a5cde0c 100644
--- a/memory.c
+++ b/memory.c
@@ -15,6 +15,7 @@
 #include "exec-memory.h"
 #include "ioport.h"
 #include "bitops.h"
+#include "kvm.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -64,6 +65,50 @@ struct CoalescedMemoryRange {
     QTAILQ_ENTRY(CoalescedMemoryRange) link;
 };
 
+struct MemoryRegionIoeventfd {
+    AddrRange addr;
+    bool match_data;
+    uint64_t data;
+    int fd;
+};
+
+static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
+                                           MemoryRegionIoeventfd b)
+{
+    if (a.addr.start < b.addr.start) {
+        return true;
+    } else if (a.addr.start > b.addr.start) {
+        return false;
+    } else if (a.addr.size < b.addr.size) {
+        return true;
+    } else if (a.addr.size > b.addr.size) {
+        return false;
+    } else if (a.match_data < b.match_data) {
+        return true;
+    } else  if (a.match_data > b.match_data) {
+        return false;
+    } else if (a.match_data) {
+        if (a.data < b.data) {
+            return true;
+        } else if (a.data > b.data) {
+            return false;
+        }
+    }
+    if (a.fd < b.fd) {
+        return true;
+    } else if (a.fd > b.fd) {
+        return false;
+    }
+    return false;
+}
+
+static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a,
+                                          MemoryRegionIoeventfd b)
+{
+    return !memory_region_ioeventfd_before(a, b)
+        && !memory_region_ioeventfd_before(b, a);
+}
+
 typedef struct FlatRange FlatRange;
 typedef struct FlatView FlatView;
 
@@ -92,6 +137,8 @@ struct AddressSpace {
     const AddressSpaceOps *ops;
     MemoryRegion *root;
     FlatView current_map;
+    int ioeventfd_nb;
+    MemoryRegionIoeventfd *ioeventfds;
 };
 
 struct AddressSpaceOps {
@@ -99,6 +146,8 @@ struct AddressSpaceOps {
     void (*range_del)(AddressSpace *as, FlatRange *fr);
     void (*log_start)(AddressSpace *as, FlatRange *fr);
     void (*log_stop)(AddressSpace *as, FlatRange *fr);
+    void (*ioeventfd_add)(AddressSpace *as, MemoryRegionIoeventfd *fd);
+    void (*ioeventfd_del)(AddressSpace *as, MemoryRegionIoeventfd *fd);
 };
 
 #define FOR_EACH_FLAT_RANGE(var, view)          \
@@ -201,11 +250,37 @@ static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
     cpu_physical_log_stop(fr->addr.start, fr->addr.size);
 }
 
+static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    if (!fd->match_data || fd->addr.size != 4) {
+        abort();
+    }
+
+    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, true);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void as_memory_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, false);
+    if (r < 0) {
+        abort();
+    }
+}
+
 static const AddressSpaceOps address_space_ops_memory = {
     .range_add = as_memory_range_add,
     .range_del = as_memory_range_del,
     .log_start = as_memory_log_start,
     .log_stop = as_memory_log_stop,
+    .ioeventfd_add = as_memory_ioeventfd_add,
+    .ioeventfd_del = as_memory_ioeventfd_del,
 };
 
 static AddressSpace address_space_memory = {
@@ -281,9 +356,35 @@ static void as_io_range_del(AddressSpace *as, FlatRange *fr)
     isa_unassign_ioport(fr->addr.start, fr->addr.size);
 }
 
+static void as_io_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    if (!fd->match_data || fd->addr.size != 2) {
+        abort();
+    }
+
+    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, true);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void as_io_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, false);
+    if (r < 0) {
+        abort();
+    }
+}
+
 static const AddressSpaceOps address_space_ops_io = {
     .range_add = as_io_range_add,
     .range_del = as_io_range_del,
+    .ioeventfd_add = as_io_ioeventfd_add,
+    .ioeventfd_del = as_io_ioeventfd_del,
 };
 
 static AddressSpace address_space_io = {
@@ -382,6 +483,69 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
     return view;
 }
 
+static void address_space_add_del_ioeventfds(AddressSpace *as,
+                                             MemoryRegionIoeventfd *fds_new,
+                                             unsigned fds_new_nb,
+                                             MemoryRegionIoeventfd *fds_old,
+                                             unsigned fds_old_nb)
+{
+    unsigned iold, inew;
+
+    /* Generate a symmetric difference of the old and new fd sets, adding
+     * and deleting as necessary.
+     */
+
+    iold = inew = 0;
+    while (iold < fds_old_nb || inew < fds_new_nb) {
+        if (iold < fds_old_nb
+            && (inew == fds_new_nb
+                || memory_region_ioeventfd_before(fds_old[iold],
+                                                  fds_new[inew]))) {
+            as->ops->ioeventfd_del(as, &fds_old[iold]);
+            ++iold;
+        } else if (inew < fds_new_nb
+                   && (iold == fds_old_nb
+                       || memory_region_ioeventfd_before(fds_new[inew],
+                                                         fds_old[iold]))) {
+            as->ops->ioeventfd_add(as, &fds_new[inew]);
+            ++inew;
+        } else {
+            ++iold;
+            ++inew;
+        }
+    }
+}
+
+static void address_space_update_ioeventfds(AddressSpace *as)
+{
+    FlatRange *fr;
+    unsigned ioeventfd_nb = 0;
+    MemoryRegionIoeventfd *ioeventfds = NULL;
+    AddrRange tmp;
+    unsigned i;
+
+    FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
+        for (i = 0; i < fr->mr->ioeventfd_nb; ++i) {
+            tmp = addrrange_shift(fr->mr->ioeventfds[i].addr,
+                                  fr->addr.start - fr->offset_in_region);
+            if (addrrange_intersects(fr->addr, tmp)) {
+                ++ioeventfd_nb;
+                ioeventfds = qemu_realloc(ioeventfds,
+                                          ioeventfd_nb * sizeof(*ioeventfds));
+                ioeventfds[ioeventfd_nb-1] = fr->mr->ioeventfds[i];
+                ioeventfds[ioeventfd_nb-1].addr = tmp;
+            }
+        }
+    }
+
+    address_space_add_del_ioeventfds(as, ioeventfds, ioeventfd_nb,
+                                     as->ioeventfds, as->ioeventfd_nb);
+
+    qemu_free(as->ioeventfds);
+    as->ioeventfds = ioeventfds;
+    as->ioeventfd_nb = ioeventfd_nb;
+}
+
 static void address_space_update_topology(AddressSpace *as)
 {
     FlatView old_view = as->current_map;
@@ -434,6 +598,7 @@ static void address_space_update_topology(AddressSpace *as)
     }
     as->current_map = new_view;
     flatview_destroy(&old_view);
+    address_space_update_ioeventfds(as);
 }
 
 static void memory_region_update_topology(void)
@@ -464,6 +629,8 @@ void memory_region_init(MemoryRegion *mr,
     QTAILQ_INIT(&mr->coalesced);
     mr->name = qemu_strdup(name);
     mr->dirty_log_mask = 0;
+    mr->ioeventfd_nb = 0;
+    mr->ioeventfds = NULL;
 }
 
 static bool memory_region_access_valid(MemoryRegion *mr,
@@ -675,6 +842,7 @@ void memory_region_destroy(MemoryRegion *mr)
     assert(QTAILQ_EMPTY(&mr->subregions));
     memory_region_clear_coalescing(mr);
     qemu_free((char *)mr->name);
+    qemu_free(mr->ioeventfds);
 }
 
 target_phys_addr_t memory_region_size(MemoryRegion *mr)
@@ -798,6 +966,68 @@ void memory_region_clear_coalescing(MemoryRegion *mr)
     memory_region_update_coalesced_range(mr);
 }
 
+void memory_region_add_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd)
+{
+    MemoryRegionIoeventfd mrfd = {
+        .addr.start = addr,
+        .addr.size = size,
+        .match_data = match_data,
+        .data = data,
+        .fd = fd,
+    };
+    unsigned i;
+
+    for (i = 0; i < mr->ioeventfd_nb; ++i) {
+        if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) {
+            break;
+        }
+    }
+    ++mr->ioeventfd_nb;
+    mr->ioeventfds = qemu_realloc(mr->ioeventfds,
+                                  sizeof(*mr->ioeventfds) * mr->ioeventfd_nb);
+    memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
+            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
+    mr->ioeventfds[i] = mrfd;
+    memory_region_update_topology();
+}
+
+void memory_region_del_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd)
+{
+    MemoryRegionIoeventfd mrfd = {
+        .addr.start = addr,
+        .addr.size = size,
+        .match_data = match_data,
+        .data = data,
+        .fd = fd,
+    };
+    unsigned i;
+
+    for (i = 0; i < mr->ioeventfd_nb; ++i) {
+        if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) {
+            break;
+        }
+    }
+    if (i == mr->ioeventfd_nb) {
+        abort();
+    }
+    memmove(&mr->ioeventfds[i], &mr->ioeventfds[i+1],
+            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb - (i+1)));
+    --mr->ioeventfd_nb;
+    mr->ioeventfds = qemu_realloc(mr->ioeventfds,
+                                  sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
+    memory_region_update_topology();
+}
+
 static void memory_region_add_subregion_common(MemoryRegion *mr,
                                                target_phys_addr_t offset,
                                                MemoryRegion *subregion)
diff --git a/memory.h b/memory.h
index 4624946..e4c0ad1 100644
--- a/memory.h
+++ b/memory.h
@@ -85,6 +85,7 @@ struct MemoryRegionOps {
 };
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
+typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
 
 struct MemoryRegion {
     /* All fields are private - violators will be prosecuted */
@@ -107,6 +108,8 @@ struct MemoryRegion {
     QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
     const char *name;
     uint8_t dirty_log_mask;
+    unsigned ioeventfd_nb;
+    MemoryRegionIoeventfd *ioeventfds;
 };
 
 struct MemoryRegionPortio {
@@ -208,6 +211,23 @@ void memory_region_add_coalescing(MemoryRegion *mr,
 /* Disable MMIO coalescing for the region. */
 void memory_region_clear_coalescing(MemoryRegion *mr);
 
+
+/* Request an eventfd to be triggered when a word is written to a location */
+void memory_region_add_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd);
+
+/* Cancel an existing eventfd  */
+void memory_region_del_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd);
+
 /* Add a sub-region at @offset.  The sub-region may not overlap with other
  * subregions (except for those explicitly marked as overlapping)
  */
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

As with the rest of the memory API, the caller associates an eventfd
with an address, and the memory API takes care of registering or
unregistering when the address is made visible or invisible to the
guest.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |  230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory.h |   20 ++++++
 2 files changed, 250 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index e4446a0..a5cde0c 100644
--- a/memory.c
+++ b/memory.c
@@ -15,6 +15,7 @@
 #include "exec-memory.h"
 #include "ioport.h"
 #include "bitops.h"
+#include "kvm.h"
 #include <assert.h>
 
 typedef struct AddrRange AddrRange;
@@ -64,6 +65,50 @@ struct CoalescedMemoryRange {
     QTAILQ_ENTRY(CoalescedMemoryRange) link;
 };
 
+struct MemoryRegionIoeventfd {
+    AddrRange addr;
+    bool match_data;
+    uint64_t data;
+    int fd;
+};
+
+static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
+                                           MemoryRegionIoeventfd b)
+{
+    if (a.addr.start < b.addr.start) {
+        return true;
+    } else if (a.addr.start > b.addr.start) {
+        return false;
+    } else if (a.addr.size < b.addr.size) {
+        return true;
+    } else if (a.addr.size > b.addr.size) {
+        return false;
+    } else if (a.match_data < b.match_data) {
+        return true;
+    } else  if (a.match_data > b.match_data) {
+        return false;
+    } else if (a.match_data) {
+        if (a.data < b.data) {
+            return true;
+        } else if (a.data > b.data) {
+            return false;
+        }
+    }
+    if (a.fd < b.fd) {
+        return true;
+    } else if (a.fd > b.fd) {
+        return false;
+    }
+    return false;
+}
+
+static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a,
+                                          MemoryRegionIoeventfd b)
+{
+    return !memory_region_ioeventfd_before(a, b)
+        && !memory_region_ioeventfd_before(b, a);
+}
+
 typedef struct FlatRange FlatRange;
 typedef struct FlatView FlatView;
 
@@ -92,6 +137,8 @@ struct AddressSpace {
     const AddressSpaceOps *ops;
     MemoryRegion *root;
     FlatView current_map;
+    int ioeventfd_nb;
+    MemoryRegionIoeventfd *ioeventfds;
 };
 
 struct AddressSpaceOps {
@@ -99,6 +146,8 @@ struct AddressSpaceOps {
     void (*range_del)(AddressSpace *as, FlatRange *fr);
     void (*log_start)(AddressSpace *as, FlatRange *fr);
     void (*log_stop)(AddressSpace *as, FlatRange *fr);
+    void (*ioeventfd_add)(AddressSpace *as, MemoryRegionIoeventfd *fd);
+    void (*ioeventfd_del)(AddressSpace *as, MemoryRegionIoeventfd *fd);
 };
 
 #define FOR_EACH_FLAT_RANGE(var, view)          \
@@ -201,11 +250,37 @@ static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
     cpu_physical_log_stop(fr->addr.start, fr->addr.size);
 }
 
+static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    if (!fd->match_data || fd->addr.size != 4) {
+        abort();
+    }
+
+    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, true);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void as_memory_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, false);
+    if (r < 0) {
+        abort();
+    }
+}
+
 static const AddressSpaceOps address_space_ops_memory = {
     .range_add = as_memory_range_add,
     .range_del = as_memory_range_del,
     .log_start = as_memory_log_start,
     .log_stop = as_memory_log_stop,
+    .ioeventfd_add = as_memory_ioeventfd_add,
+    .ioeventfd_del = as_memory_ioeventfd_del,
 };
 
 static AddressSpace address_space_memory = {
@@ -281,9 +356,35 @@ static void as_io_range_del(AddressSpace *as, FlatRange *fr)
     isa_unassign_ioport(fr->addr.start, fr->addr.size);
 }
 
+static void as_io_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    if (!fd->match_data || fd->addr.size != 2) {
+        abort();
+    }
+
+    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, true);
+    if (r < 0) {
+        abort();
+    }
+}
+
+static void as_io_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+    int r;
+
+    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, false);
+    if (r < 0) {
+        abort();
+    }
+}
+
 static const AddressSpaceOps address_space_ops_io = {
     .range_add = as_io_range_add,
     .range_del = as_io_range_del,
+    .ioeventfd_add = as_io_ioeventfd_add,
+    .ioeventfd_del = as_io_ioeventfd_del,
 };
 
 static AddressSpace address_space_io = {
@@ -382,6 +483,69 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
     return view;
 }
 
+static void address_space_add_del_ioeventfds(AddressSpace *as,
+                                             MemoryRegionIoeventfd *fds_new,
+                                             unsigned fds_new_nb,
+                                             MemoryRegionIoeventfd *fds_old,
+                                             unsigned fds_old_nb)
+{
+    unsigned iold, inew;
+
+    /* Generate a symmetric difference of the old and new fd sets, adding
+     * and deleting as necessary.
+     */
+
+    iold = inew = 0;
+    while (iold < fds_old_nb || inew < fds_new_nb) {
+        if (iold < fds_old_nb
+            && (inew == fds_new_nb
+                || memory_region_ioeventfd_before(fds_old[iold],
+                                                  fds_new[inew]))) {
+            as->ops->ioeventfd_del(as, &fds_old[iold]);
+            ++iold;
+        } else if (inew < fds_new_nb
+                   && (iold == fds_old_nb
+                       || memory_region_ioeventfd_before(fds_new[inew],
+                                                         fds_old[iold]))) {
+            as->ops->ioeventfd_add(as, &fds_new[inew]);
+            ++inew;
+        } else {
+            ++iold;
+            ++inew;
+        }
+    }
+}
+
+static void address_space_update_ioeventfds(AddressSpace *as)
+{
+    FlatRange *fr;
+    unsigned ioeventfd_nb = 0;
+    MemoryRegionIoeventfd *ioeventfds = NULL;
+    AddrRange tmp;
+    unsigned i;
+
+    FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
+        for (i = 0; i < fr->mr->ioeventfd_nb; ++i) {
+            tmp = addrrange_shift(fr->mr->ioeventfds[i].addr,
+                                  fr->addr.start - fr->offset_in_region);
+            if (addrrange_intersects(fr->addr, tmp)) {
+                ++ioeventfd_nb;
+                ioeventfds = qemu_realloc(ioeventfds,
+                                          ioeventfd_nb * sizeof(*ioeventfds));
+                ioeventfds[ioeventfd_nb-1] = fr->mr->ioeventfds[i];
+                ioeventfds[ioeventfd_nb-1].addr = tmp;
+            }
+        }
+    }
+
+    address_space_add_del_ioeventfds(as, ioeventfds, ioeventfd_nb,
+                                     as->ioeventfds, as->ioeventfd_nb);
+
+    qemu_free(as->ioeventfds);
+    as->ioeventfds = ioeventfds;
+    as->ioeventfd_nb = ioeventfd_nb;
+}
+
 static void address_space_update_topology(AddressSpace *as)
 {
     FlatView old_view = as->current_map;
@@ -434,6 +598,7 @@ static void address_space_update_topology(AddressSpace *as)
     }
     as->current_map = new_view;
     flatview_destroy(&old_view);
+    address_space_update_ioeventfds(as);
 }
 
 static void memory_region_update_topology(void)
@@ -464,6 +629,8 @@ void memory_region_init(MemoryRegion *mr,
     QTAILQ_INIT(&mr->coalesced);
     mr->name = qemu_strdup(name);
     mr->dirty_log_mask = 0;
+    mr->ioeventfd_nb = 0;
+    mr->ioeventfds = NULL;
 }
 
 static bool memory_region_access_valid(MemoryRegion *mr,
@@ -675,6 +842,7 @@ void memory_region_destroy(MemoryRegion *mr)
     assert(QTAILQ_EMPTY(&mr->subregions));
     memory_region_clear_coalescing(mr);
     qemu_free((char *)mr->name);
+    qemu_free(mr->ioeventfds);
 }
 
 target_phys_addr_t memory_region_size(MemoryRegion *mr)
@@ -798,6 +966,68 @@ void memory_region_clear_coalescing(MemoryRegion *mr)
     memory_region_update_coalesced_range(mr);
 }
 
+void memory_region_add_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd)
+{
+    MemoryRegionIoeventfd mrfd = {
+        .addr.start = addr,
+        .addr.size = size,
+        .match_data = match_data,
+        .data = data,
+        .fd = fd,
+    };
+    unsigned i;
+
+    for (i = 0; i < mr->ioeventfd_nb; ++i) {
+        if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) {
+            break;
+        }
+    }
+    ++mr->ioeventfd_nb;
+    mr->ioeventfds = qemu_realloc(mr->ioeventfds,
+                                  sizeof(*mr->ioeventfds) * mr->ioeventfd_nb);
+    memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
+            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
+    mr->ioeventfds[i] = mrfd;
+    memory_region_update_topology();
+}
+
+void memory_region_del_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd)
+{
+    MemoryRegionIoeventfd mrfd = {
+        .addr.start = addr,
+        .addr.size = size,
+        .match_data = match_data,
+        .data = data,
+        .fd = fd,
+    };
+    unsigned i;
+
+    for (i = 0; i < mr->ioeventfd_nb; ++i) {
+        if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) {
+            break;
+        }
+    }
+    if (i == mr->ioeventfd_nb) {
+        abort();
+    }
+    memmove(&mr->ioeventfds[i], &mr->ioeventfds[i+1],
+            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb - (i+1)));
+    --mr->ioeventfd_nb;
+    mr->ioeventfds = qemu_realloc(mr->ioeventfds,
+                                  sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
+    memory_region_update_topology();
+}
+
 static void memory_region_add_subregion_common(MemoryRegion *mr,
                                                target_phys_addr_t offset,
                                                MemoryRegion *subregion)
diff --git a/memory.h b/memory.h
index 4624946..e4c0ad1 100644
--- a/memory.h
+++ b/memory.h
@@ -85,6 +85,7 @@ struct MemoryRegionOps {
 };
 
 typedef struct CoalescedMemoryRange CoalescedMemoryRange;
+typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
 
 struct MemoryRegion {
     /* All fields are private - violators will be prosecuted */
@@ -107,6 +108,8 @@ struct MemoryRegion {
     QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
     const char *name;
     uint8_t dirty_log_mask;
+    unsigned ioeventfd_nb;
+    MemoryRegionIoeventfd *ioeventfds;
 };
 
 struct MemoryRegionPortio {
@@ -208,6 +211,23 @@ void memory_region_add_coalescing(MemoryRegion *mr,
 /* Disable MMIO coalescing for the region. */
 void memory_region_clear_coalescing(MemoryRegion *mr);
 
+
+/* Request an eventfd to be triggered when a word is written to a location */
+void memory_region_add_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd);
+
+/* Cancel an existing eventfd  */
+void memory_region_del_eventfd(MemoryRegion *mr,
+                               target_phys_addr_t addr,
+                               unsigned size,
+                               bool match_data,
+                               uint64_t data,
+                               int fd);
+
 /* Add a sub-region at @offset.  The sub-region may not overlap with other
  * subregions (except for those explicitly marked as overlapping)
  */
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 12/23] memory: separate building the final memory map into two steps
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Instead of adding and deleting regions in one pass, do a delete
pass followed by an add pass.  This fixes the following case:

from:
  0x0000-0x0fff ram  (a1)
  0x1000-0x1fff mmio (a2)
  0x2000-0x2fff ram  (a3)

to:
  0x0000-0x2fff ram  (b1)

The single pass algorithm removed a1, added b2, then removed a2 and a2,
which caused the wrong memory map to be built.  The two pass algorithm
removes a1, a2, and a3, then adds b1.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   38 +++++++++++++++++++++++++++++---------
 1 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/memory.c b/memory.c
index a5cde0c..009ad33 100644
--- a/memory.c
+++ b/memory.c
@@ -546,10 +546,11 @@ static void address_space_update_ioeventfds(AddressSpace *as)
     as->ioeventfd_nb = ioeventfd_nb;
 }
 
-static void address_space_update_topology(AddressSpace *as)
+static void address_space_update_topology_pass(AddressSpace *as,
+                                               FlatView old_view,
+                                               FlatView new_view,
+                                               bool adding)
 {
-    FlatView old_view = as->current_map;
-    FlatView new_view = generate_memory_topology(as->root);
     unsigned iold, inew;
     FlatRange *frold, *frnew;
 
@@ -576,15 +577,20 @@ static void address_space_update_topology(AddressSpace *as)
                     && !flatrange_equal(frold, frnew)))) {
             /* In old, but (not in new, or in new but attributes changed). */
 
-            as->ops->range_del(as, frold);
+            if (!adding) {
+                as->ops->range_del(as, frold);
+            }
+
             ++iold;
         } else if (frold && frnew && flatrange_equal(frold, frnew)) {
             /* In both (logging may have changed) */
 
-            if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
-                as->ops->log_stop(as, frnew);
-            } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
-                as->ops->log_start(as, frnew);
+            if (adding) {
+                if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
+                    as->ops->log_stop(as, frnew);
+                } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
+                    as->ops->log_start(as, frnew);
+                }
             }
 
             ++iold;
@@ -592,10 +598,24 @@ static void address_space_update_topology(AddressSpace *as)
         } else {
             /* In new */
 
-            as->ops->range_add(as, frnew);
+            if (adding) {
+                as->ops->range_add(as, frnew);
+            }
+
             ++inew;
         }
     }
+}
+
+
+static void address_space_update_topology(AddressSpace *as)
+{
+    FlatView old_view = as->current_map;
+    FlatView new_view = generate_memory_topology(as->root);
+
+    address_space_update_topology_pass(as, old_view, new_view, false);
+    address_space_update_topology_pass(as, old_view, new_view, true);
+
     as->current_map = new_view;
     flatview_destroy(&old_view);
     address_space_update_ioeventfds(as);
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 12/23] memory: separate building the final memory map into two steps
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Instead of adding and deleting regions in one pass, do a delete
pass followed by an add pass.  This fixes the following case:

from:
  0x0000-0x0fff ram  (a1)
  0x1000-0x1fff mmio (a2)
  0x2000-0x2fff ram  (a3)

to:
  0x0000-0x2fff ram  (b1)

The single pass algorithm removed a1, added b2, then removed a2 and a2,
which caused the wrong memory map to be built.  The two pass algorithm
removes a1, a2, and a3, then adds b1.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   38 +++++++++++++++++++++++++++++---------
 1 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/memory.c b/memory.c
index a5cde0c..009ad33 100644
--- a/memory.c
+++ b/memory.c
@@ -546,10 +546,11 @@ static void address_space_update_ioeventfds(AddressSpace *as)
     as->ioeventfd_nb = ioeventfd_nb;
 }
 
-static void address_space_update_topology(AddressSpace *as)
+static void address_space_update_topology_pass(AddressSpace *as,
+                                               FlatView old_view,
+                                               FlatView new_view,
+                                               bool adding)
 {
-    FlatView old_view = as->current_map;
-    FlatView new_view = generate_memory_topology(as->root);
     unsigned iold, inew;
     FlatRange *frold, *frnew;
 
@@ -576,15 +577,20 @@ static void address_space_update_topology(AddressSpace *as)
                     && !flatrange_equal(frold, frnew)))) {
             /* In old, but (not in new, or in new but attributes changed). */
 
-            as->ops->range_del(as, frold);
+            if (!adding) {
+                as->ops->range_del(as, frold);
+            }
+
             ++iold;
         } else if (frold && frnew && flatrange_equal(frold, frnew)) {
             /* In both (logging may have changed) */
 
-            if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
-                as->ops->log_stop(as, frnew);
-            } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
-                as->ops->log_start(as, frnew);
+            if (adding) {
+                if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
+                    as->ops->log_stop(as, frnew);
+                } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
+                    as->ops->log_start(as, frnew);
+                }
             }
 
             ++iold;
@@ -592,10 +598,24 @@ static void address_space_update_topology(AddressSpace *as)
         } else {
             /* In new */
 
-            as->ops->range_add(as, frnew);
+            if (adding) {
+                as->ops->range_add(as, frnew);
+            }
+
             ++inew;
         }
     }
+}
+
+
+static void address_space_update_topology(AddressSpace *as)
+{
+    FlatView old_view = as->current_map;
+    FlatView new_view = generate_memory_topology(as->root);
+
+    address_space_update_topology_pass(as, old_view, new_view, false);
+    address_space_update_topology_pass(as, old_view, new_view, true);
+
     as->current_map = new_view;
     flatview_destroy(&old_view);
     address_space_update_ioeventfds(as);
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 13/23] memory: document the memory API
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 docs/memory.txt |  172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 172 insertions(+), 0 deletions(-)
 create mode 100644 docs/memory.txt

diff --git a/docs/memory.txt b/docs/memory.txt
new file mode 100644
index 0000000..4460c06
--- /dev/null
+++ b/docs/memory.txt
@@ -0,0 +1,172 @@
+The memory API
+==============
+
+The memory API models the memory and I/O buses and controllers of a QEMU
+machine.  It attempts to allow modelling of:
+
+ - ordinary RAM
+ - memory-mapped I/O (MMIO)
+ - memory controllers that can dynamically reroute physical memory regions
+  to different destinations
+
+The memory model provides support for
+
+ - tracking RAM changes by the guest
+ - setting up coalesced memory for kvm
+ - setting up ioeventfd regions for kvm
+
+Memory is modelled as an tree (really acyclic graph) of MemoryRegion objects.
+The root of the tree is memory as seen from the CPU's viewpoint (the system
+bus).  Nodes in the tree represent other buses, memory controllers, and
+memory regions that have been rerouted.  Leaves are RAM and MMIO regions.
+
+Types of regions
+----------------
+
+There are four types of memory regions (all represented by a single C type
+MemoryRegion):
+
+- RAM: a RAM region is simply a range of host memory that can be made available
+  to the guest.
+
+- MMIO: a range of guest memory that is implemented by host callbacks;
+  each read or write causes a callback to be called on the host.
+
+- container: a container simply includes other memory regions, each at
+  a different offset.  Containers are useful for grouping several regions
+  into one unit.  For example, a PCI BAR may be composed of a RAM region
+  and an MMIO region.
+
+  A container's subregions are usually non-overlapping.  In some cases it is
+  useful to have overlapping regions; for example a memory controller that
+  can overlay a subregion of RAM with MMIO or ROM, or a PCI controller
+  that does not prevent card from claiming overlapping BARs.
+
+- alias: a subsection of another region.  Aliases allow a region to be
+  split apart into discontiguous regions.  Examples of uses are memory banks
+  used when the guest address space is smaller than the amount of RAM
+  addressed, or a memory controller that splits main memory to expose a "PCI
+  hole".  Aliases may point to any type of region, including other aliases,
+  but an alias may not point back to itself, directly or indirectly.
+
+
+Region names
+------------
+
+Regions are assigned names by the constructor.  For most regions these are
+only used for debugging purposes, but RAM regions also use the name to identify
+live migration sections.  This means that RAM region names need to have ABI
+stability.
+
+Region lifecycle
+----------------
+
+A region is created by one of the constructor functions (memory_region_init*())
+and destroyed by the destructor (memory_region_destroy()).  In between,
+a region can be added to an address space by using memory_region_add_subregion()
+and removed using memory_region_del_subregion().  Region attributes may be
+changed at any point; they take effect once the region becomes exposed to the
+guest.
+
+Overlapping regions and priority
+--------------------------------
+Usually, regions may not overlap each other; a memory address decodes into
+exactly one target.  In some cases it is useful to allow regions to overlap,
+and sometimes to control which of an overlapping regions is visible to the
+guest.  This is done with memory_region_add_subregion_overlap(), which
+allows the region to overlap any other region in the same container, and
+specifies a priority that allows the core to decide which of two regions at
+the same address are visible (highest wins).
+
+Visibility
+----------
+The memory core uses the following rules to select a memory region when the
+guest accesses an address:
+
+- all direct subregions of the root region are matched against the address, in
+  descending priority order
+  - if the address lies outside the region offset/size, the subregion is
+    discarded
+  - if the subregion is a leaf (RAM or MMIO), the seach terminates
+  - if the subregion is a container, the same algorithm is used within the
+    subregion (after the address is adjusted by the subregion offset)
+  - if the subregion is an alias, the search is continues at the alias target
+    (after the address is adjusted by the subregion offset and alias offset)
+
+Example memory map
+------------------
+
+system_memory: container@0-2^48-1
+ |
+ +---- lomem: alias@0-0xdfffffff ---> #ram (0-0xdfffffff)
+ |
+ +---- himem: alias@0x100000000-0x11fffffff ---> #ram (0xe0000000-0xffffffff)
+ |
+ +---- vga-window: alias@0xa0000-0xbfffff ---> #pci (0xa0000-0xbffff)
+ |      (prio 1)
+ |
+ +---- pci-hole: alias@0xe0000000-0xffffffff ---> #pci (0xe0000000-0xffffffff)
+
+pci (0-2^32-1)
+ |
+ +--- vga-area: container@0xa0000-0xbffff
+ |      |
+ |      +--- alias@0x00000-0x7fff  ---> #vram (0x010000-0x017fff)
+ |      |
+ |      +--- alias@0x08000-0xffff  ---> #vram (0x020000-0x027fff)
+ |
+ +---- vram: ram@0xe1000000-0xe1ffffff
+ |
+ +---- vga-mmio: mmio@0xe2000000-0xe200ffff
+
+ram: ram@0x00000000-0xffffffff
+
+The is a (simplified) PC memory map. The 4GB RAM block is mapped into the
+system address space via two aliases: "lomem" is a 1:1 mapping of the first
+3.5GB; "himem" maps the last 0.5GB at address 4GB.  This leaves 0.5GB for the
+so-called PCI hole, that allows a 32-bit PCI bus to exist in a system with
+4GB of memory.
+
+The memory controller diverts addresses in the range 640K-768K to the PCI
+address space.  This is modeled using the "vga-window" alias, mapped at a
+higher priority so it obscures the RAM at the same addresses.  The vga window
+can be removed by programming the memory controller; this is modelled by
+removing the alias and exposing the RAM underneath.
+
+The pci address space is not a direct child of the system address space, since
+we only want parts of it to be visible (we accomplish this using aliases).
+It has two subregions: vga-area models the legacy vga window and is occupied
+by two 32K memory banks pointing at two sections of the framebuffer.
+In addition the vram is mapped as a BAR at address e1000000, and an additional
+BAR containing MMIO registers is mapped after it.
+
+Note that if the guest maps a BAR outside the PCI hole, it would not be
+visible as the pci-hole alias clips it to a 0.5GB range.
+
+Attributes
+----------
+
+Various region attributes (read-only, dirty logging, coalesced mmio, ioeventfd)
+can be changed during the region lifecycle.  They take effect once the region
+is made visible (which can be immediately, later, or never).
+
+MMIO Operations
+---------------
+
+MMIO regions are provided with ->read() and ->write() callbacks; in addition
+various constraints can be supplied to control how these callbacks are called:
+
+ - .valid.min_access_size, .valid.max_access_size define the access sizes
+   (in bytes) which the device accepts; accesses outside this range will
+   have device and bus specific behaviour (ignored, or machine check)
+ - .valid.aligned specifies that the device only accepts naturally aligned
+   accesses.  Unaligned accesses invoke device and bus specific behaviour.
+ - .impl.min_access_size, .impl.max_access_size define the access sizes
+   (in bytes) supported by the *implementation*; other access sizes will be
+   emulated using the ones available.  For example a 4-byte write will be
+   emulated using four 1-byte write, is .impl.max_access_size = 1.
+ - .impl.valid specifies that the *implementation* only supports unaligned
+   accesses; unaligned accesses will be emulated by two aligned accesses.
+ - .old_portio and .old_mmio can be used to ease porting from code using
+   cpu_register_io_memory() and register_ioport().  They should not be used
+   in new code.
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 13/23] memory: document the memory API
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 docs/memory.txt |  172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 172 insertions(+), 0 deletions(-)
 create mode 100644 docs/memory.txt

diff --git a/docs/memory.txt b/docs/memory.txt
new file mode 100644
index 0000000..4460c06
--- /dev/null
+++ b/docs/memory.txt
@@ -0,0 +1,172 @@
+The memory API
+==============
+
+The memory API models the memory and I/O buses and controllers of a QEMU
+machine.  It attempts to allow modelling of:
+
+ - ordinary RAM
+ - memory-mapped I/O (MMIO)
+ - memory controllers that can dynamically reroute physical memory regions
+  to different destinations
+
+The memory model provides support for
+
+ - tracking RAM changes by the guest
+ - setting up coalesced memory for kvm
+ - setting up ioeventfd regions for kvm
+
+Memory is modelled as an tree (really acyclic graph) of MemoryRegion objects.
+The root of the tree is memory as seen from the CPU's viewpoint (the system
+bus).  Nodes in the tree represent other buses, memory controllers, and
+memory regions that have been rerouted.  Leaves are RAM and MMIO regions.
+
+Types of regions
+----------------
+
+There are four types of memory regions (all represented by a single C type
+MemoryRegion):
+
+- RAM: a RAM region is simply a range of host memory that can be made available
+  to the guest.
+
+- MMIO: a range of guest memory that is implemented by host callbacks;
+  each read or write causes a callback to be called on the host.
+
+- container: a container simply includes other memory regions, each at
+  a different offset.  Containers are useful for grouping several regions
+  into one unit.  For example, a PCI BAR may be composed of a RAM region
+  and an MMIO region.
+
+  A container's subregions are usually non-overlapping.  In some cases it is
+  useful to have overlapping regions; for example a memory controller that
+  can overlay a subregion of RAM with MMIO or ROM, or a PCI controller
+  that does not prevent card from claiming overlapping BARs.
+
+- alias: a subsection of another region.  Aliases allow a region to be
+  split apart into discontiguous regions.  Examples of uses are memory banks
+  used when the guest address space is smaller than the amount of RAM
+  addressed, or a memory controller that splits main memory to expose a "PCI
+  hole".  Aliases may point to any type of region, including other aliases,
+  but an alias may not point back to itself, directly or indirectly.
+
+
+Region names
+------------
+
+Regions are assigned names by the constructor.  For most regions these are
+only used for debugging purposes, but RAM regions also use the name to identify
+live migration sections.  This means that RAM region names need to have ABI
+stability.
+
+Region lifecycle
+----------------
+
+A region is created by one of the constructor functions (memory_region_init*())
+and destroyed by the destructor (memory_region_destroy()).  In between,
+a region can be added to an address space by using memory_region_add_subregion()
+and removed using memory_region_del_subregion().  Region attributes may be
+changed at any point; they take effect once the region becomes exposed to the
+guest.
+
+Overlapping regions and priority
+--------------------------------
+Usually, regions may not overlap each other; a memory address decodes into
+exactly one target.  In some cases it is useful to allow regions to overlap,
+and sometimes to control which of an overlapping regions is visible to the
+guest.  This is done with memory_region_add_subregion_overlap(), which
+allows the region to overlap any other region in the same container, and
+specifies a priority that allows the core to decide which of two regions at
+the same address are visible (highest wins).
+
+Visibility
+----------
+The memory core uses the following rules to select a memory region when the
+guest accesses an address:
+
+- all direct subregions of the root region are matched against the address, in
+  descending priority order
+  - if the address lies outside the region offset/size, the subregion is
+    discarded
+  - if the subregion is a leaf (RAM or MMIO), the seach terminates
+  - if the subregion is a container, the same algorithm is used within the
+    subregion (after the address is adjusted by the subregion offset)
+  - if the subregion is an alias, the search is continues at the alias target
+    (after the address is adjusted by the subregion offset and alias offset)
+
+Example memory map
+------------------
+
+system_memory: container@0-2^48-1
+ |
+ +---- lomem: alias@0-0xdfffffff ---> #ram (0-0xdfffffff)
+ |
+ +---- himem: alias@0x100000000-0x11fffffff ---> #ram (0xe0000000-0xffffffff)
+ |
+ +---- vga-window: alias@0xa0000-0xbfffff ---> #pci (0xa0000-0xbffff)
+ |      (prio 1)
+ |
+ +---- pci-hole: alias@0xe0000000-0xffffffff ---> #pci (0xe0000000-0xffffffff)
+
+pci (0-2^32-1)
+ |
+ +--- vga-area: container@0xa0000-0xbffff
+ |      |
+ |      +--- alias@0x00000-0x7fff  ---> #vram (0x010000-0x017fff)
+ |      |
+ |      +--- alias@0x08000-0xffff  ---> #vram (0x020000-0x027fff)
+ |
+ +---- vram: ram@0xe1000000-0xe1ffffff
+ |
+ +---- vga-mmio: mmio@0xe2000000-0xe200ffff
+
+ram: ram@0x00000000-0xffffffff
+
+The is a (simplified) PC memory map. The 4GB RAM block is mapped into the
+system address space via two aliases: "lomem" is a 1:1 mapping of the first
+3.5GB; "himem" maps the last 0.5GB at address 4GB.  This leaves 0.5GB for the
+so-called PCI hole, that allows a 32-bit PCI bus to exist in a system with
+4GB of memory.
+
+The memory controller diverts addresses in the range 640K-768K to the PCI
+address space.  This is modeled using the "vga-window" alias, mapped at a
+higher priority so it obscures the RAM at the same addresses.  The vga window
+can be removed by programming the memory controller; this is modelled by
+removing the alias and exposing the RAM underneath.
+
+The pci address space is not a direct child of the system address space, since
+we only want parts of it to be visible (we accomplish this using aliases).
+It has two subregions: vga-area models the legacy vga window and is occupied
+by two 32K memory banks pointing at two sections of the framebuffer.
+In addition the vram is mapped as a BAR at address e1000000, and an additional
+BAR containing MMIO registers is mapped after it.
+
+Note that if the guest maps a BAR outside the PCI hole, it would not be
+visible as the pci-hole alias clips it to a 0.5GB range.
+
+Attributes
+----------
+
+Various region attributes (read-only, dirty logging, coalesced mmio, ioeventfd)
+can be changed during the region lifecycle.  They take effect once the region
+is made visible (which can be immediately, later, or never).
+
+MMIO Operations
+---------------
+
+MMIO regions are provided with ->read() and ->write() callbacks; in addition
+various constraints can be supplied to control how these callbacks are called:
+
+ - .valid.min_access_size, .valid.max_access_size define the access sizes
+   (in bytes) which the device accepts; accesses outside this range will
+   have device and bus specific behaviour (ignored, or machine check)
+ - .valid.aligned specifies that the device only accepts naturally aligned
+   accesses.  Unaligned accesses invoke device and bus specific behaviour.
+ - .impl.min_access_size, .impl.max_access_size define the access sizes
+   (in bytes) supported by the *implementation*; other access sizes will be
+   emulated using the ones available.  For example a 4-byte write will be
+   emulated using four 1-byte write, is .impl.max_access_size = 1.
+ - .impl.valid specifies that the *implementation* only supports unaligned
+   accesses; unaligned accesses will be emulated by two aligned accesses.
+ - .old_portio and .old_mmio can be used to ease porting from code using
+   cpu_register_io_memory() and register_ioport().  They should not be used
+   in new code.
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 14/23] memory: transaction API
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Allow changes to the memory hierarchy to be accumulated and
made visible all at once.  This reduces computational effort,
especially when an accelerator (e.g. kvm) is involved.

Useful when a single register update causes multiple changes
to an address space.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   20 ++++++++++++++++++++
 memory.h |    8 ++++++++
 2 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index 009ad33..370e189 100644
--- a/memory.c
+++ b/memory.c
@@ -18,6 +18,8 @@
 #include "kvm.h"
 #include <assert.h>
 
+unsigned memory_region_transaction_depth = 0;
+
 typedef struct AddrRange AddrRange;
 
 struct AddrRange {
@@ -623,6 +625,10 @@ static void address_space_update_topology(AddressSpace *as)
 
 static void memory_region_update_topology(void)
 {
+    if (memory_region_transaction_depth) {
+        return;
+    }
+
     if (address_space_memory.root) {
         address_space_update_topology(&address_space_memory);
     }
@@ -631,6 +637,20 @@ static void memory_region_update_topology(void)
     }
 }
 
+void memory_region_transaction_begin(void)
+{
+    ++memory_region_transaction_depth;
+}
+
+void memory_region_transaction_commit(void)
+{
+    if (!memory_region_transaction_depth) {
+        abort();
+    }
+    --memory_region_transaction_depth;
+    memory_region_update_topology();
+}
+
 void memory_region_init(MemoryRegion *mr,
                         const char *name,
                         uint64_t size)
diff --git a/memory.h b/memory.h
index e4c0ad1..cb3a9b6 100644
--- a/memory.h
+++ b/memory.h
@@ -246,6 +246,14 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
 void memory_region_del_subregion(MemoryRegion *mr,
                                  MemoryRegion *subregion);
 
+/* Start a transaction; changes will be accumulated and made visible only
+ * when the transaction ends.
+ */
+void memory_region_transaction_begin(void);
+/* Commit a transaction and make changes visible to the guest.
+ */
+void memory_region_transaction_commit(void);
+
 #endif
 
 #endif
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 14/23] memory: transaction API
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Allow changes to the memory hierarchy to be accumulated and
made visible all at once.  This reduces computational effort,
especially when an accelerator (e.g. kvm) is involved.

Useful when a single register update causes multiple changes
to an address space.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 memory.c |   20 ++++++++++++++++++++
 memory.h |    8 ++++++++
 2 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index 009ad33..370e189 100644
--- a/memory.c
+++ b/memory.c
@@ -18,6 +18,8 @@
 #include "kvm.h"
 #include <assert.h>
 
+unsigned memory_region_transaction_depth = 0;
+
 typedef struct AddrRange AddrRange;
 
 struct AddrRange {
@@ -623,6 +625,10 @@ static void address_space_update_topology(AddressSpace *as)
 
 static void memory_region_update_topology(void)
 {
+    if (memory_region_transaction_depth) {
+        return;
+    }
+
     if (address_space_memory.root) {
         address_space_update_topology(&address_space_memory);
     }
@@ -631,6 +637,20 @@ static void memory_region_update_topology(void)
     }
 }
 
+void memory_region_transaction_begin(void)
+{
+    ++memory_region_transaction_depth;
+}
+
+void memory_region_transaction_commit(void)
+{
+    if (!memory_region_transaction_depth) {
+        abort();
+    }
+    --memory_region_transaction_depth;
+    memory_region_update_topology();
+}
+
 void memory_region_init(MemoryRegion *mr,
                         const char *name,
                         uint64_t size)
diff --git a/memory.h b/memory.h
index e4c0ad1..cb3a9b6 100644
--- a/memory.h
+++ b/memory.h
@@ -246,6 +246,14 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
 void memory_region_del_subregion(MemoryRegion *mr,
                                  MemoryRegion *subregion);
 
+/* Start a transaction; changes will be accumulated and made visible only
+ * when the transaction ends.
+ */
+void memory_region_transaction_begin(void);
+/* Commit a transaction and make changes visible to the guest.
+ */
+void memory_region_transaction_commit(void);
+
 #endif
 
 #endif
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 15/23] exec.c: initialize memory map
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Allocate the root memory region and initialize it.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 exec.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/exec.c b/exec.c
index 2160ded..d51502f 100644
--- a/exec.c
+++ b/exec.c
@@ -33,6 +33,8 @@
 #include "kvm.h"
 #include "hw/xen.h"
 #include "qemu-timer.h"
+#include "memory.h"
+#include "exec-memory.h"
 #if defined(CONFIG_USER_ONLY)
 #include <qemu.h>
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -109,6 +111,9 @@ int phys_ram_fd;
 static int in_migration;
 
 RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list) };
+
+static MemoryRegion *system_memory;
+
 #endif
 
 CPUState *first_cpu;
@@ -197,6 +202,7 @@ typedef struct PhysPageDesc {
 static void *l1_phys_map[P_L1_SIZE];
 
 static void io_mem_init(void);
+static void memory_map_init(void);
 
 /* io memory support */
 CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
@@ -571,6 +577,7 @@ void cpu_exec_init_all(unsigned long tb_size)
     code_gen_ptr = code_gen_buffer;
     page_init();
 #if !defined(CONFIG_USER_ONLY)
+    memory_map_init();
     io_mem_init();
 #endif
 #if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
@@ -3807,6 +3814,18 @@ static void io_mem_init(void)
                                           DEVICE_NATIVE_ENDIAN);
 }
 
+static void memory_map_init(void)
+{
+    system_memory = qemu_malloc(sizeof(*system_memory));
+    memory_region_init(system_memory, "system", UINT64_MAX);
+    set_system_memory_map(system_memory);
+}
+
+MemoryRegion *get_system_memory(void)
+{
+    return system_memory;
+}
+
 #endif /* !defined(CONFIG_USER_ONLY) */
 
 /* physical memory access (slow version, mainly for debug) */
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 15/23] exec.c: initialize memory map
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Allocate the root memory region and initialize it.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 exec.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/exec.c b/exec.c
index 2160ded..d51502f 100644
--- a/exec.c
+++ b/exec.c
@@ -33,6 +33,8 @@
 #include "kvm.h"
 #include "hw/xen.h"
 #include "qemu-timer.h"
+#include "memory.h"
+#include "exec-memory.h"
 #if defined(CONFIG_USER_ONLY)
 #include <qemu.h>
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -109,6 +111,9 @@ int phys_ram_fd;
 static int in_migration;
 
 RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list) };
+
+static MemoryRegion *system_memory;
+
 #endif
 
 CPUState *first_cpu;
@@ -197,6 +202,7 @@ typedef struct PhysPageDesc {
 static void *l1_phys_map[P_L1_SIZE];
 
 static void io_mem_init(void);
+static void memory_map_init(void);
 
 /* io memory support */
 CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
@@ -571,6 +577,7 @@ void cpu_exec_init_all(unsigned long tb_size)
     code_gen_ptr = code_gen_buffer;
     page_init();
 #if !defined(CONFIG_USER_ONLY)
+    memory_map_init();
     io_mem_init();
 #endif
 #if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
@@ -3807,6 +3814,18 @@ static void io_mem_init(void)
                                           DEVICE_NATIVE_ENDIAN);
 }
 
+static void memory_map_init(void)
+{
+    system_memory = qemu_malloc(sizeof(*system_memory));
+    memory_region_init(system_memory, "system", UINT64_MAX);
+    set_system_memory_map(system_memory);
+}
+
+MemoryRegion *get_system_memory(void)
+{
+    return system_memory;
+}
+
 #endif /* !defined(CONFIG_USER_ONLY) */
 
 /* physical memory access (slow version, mainly for debug) */
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 16/23] ioport: register ranges by byte aligned addresses always
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

The I/O port space is byte addressable, even for word and long accesses.

An example is the VMware svga card, which has long ports on offsets 0,
1, and 2.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 ioport.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/ioport.c b/ioport.c
index 0d2611d..a32483b 100644
--- a/ioport.c
+++ b/ioport.c
@@ -146,7 +146,7 @@ int register_ioport_read(pio_addr_t start, int length, int size,
         hw_error("register_ioport_read: invalid size");
         return -1;
     }
-    for(i = start; i < start + length; i += size) {
+    for(i = start; i < start + length; ++i) {
         ioport_read_table[bsize][i] = func;
         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
             hw_error("register_ioport_read: invalid opaque for address 0x%x",
@@ -166,7 +166,7 @@ int register_ioport_write(pio_addr_t start, int length, int size,
         hw_error("register_ioport_write: invalid size");
         return -1;
     }
-    for(i = start; i < start + length; i += size) {
+    for(i = start; i < start + length; ++i) {
         ioport_write_table[bsize][i] = func;
         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
             hw_error("register_ioport_write: invalid opaque for address 0x%x",
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 16/23] ioport: register ranges by byte aligned addresses always
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

The I/O port space is byte addressable, even for word and long accesses.

An example is the VMware svga card, which has long ports on offsets 0,
1, and 2.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 ioport.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/ioport.c b/ioport.c
index 0d2611d..a32483b 100644
--- a/ioport.c
+++ b/ioport.c
@@ -146,7 +146,7 @@ int register_ioport_read(pio_addr_t start, int length, int size,
         hw_error("register_ioport_read: invalid size");
         return -1;
     }
-    for(i = start; i < start + length; i += size) {
+    for(i = start; i < start + length; ++i) {
         ioport_read_table[bsize][i] = func;
         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
             hw_error("register_ioport_read: invalid opaque for address 0x%x",
@@ -166,7 +166,7 @@ int register_ioport_write(pio_addr_t start, int length, int size,
         hw_error("register_ioport_write: invalid size");
         return -1;
     }
-    for(i = start; i < start + length; i += size) {
+    for(i = start; i < start + length; ++i) {
         ioport_write_table[bsize][i] = func;
         if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
             hw_error("register_ioport_write: invalid opaque for address 0x%x",
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 17/23] pc: grab system_memory
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

While eventually this should come from the machine initialization function,
take a short cut to avoid converting all machines now.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/pc.c      |    3 ++-
 hw/pc.h      |    4 +++-
 hw/pc_piix.c |    8 +++++++-
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index a3e8539..369566a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -957,7 +957,8 @@ void pc_cpus_init(const char *cpu_model)
     }
 }
 
-void pc_memory_init(const char *kernel_filename,
+void pc_memory_init(MemoryRegion *system_memory,
+                    const char *kernel_filename,
                     const char *kernel_cmdline,
                     const char *initrd_filename,
                     ram_addr_t below_4g_mem_size,
diff --git a/hw/pc.h b/hw/pc.h
index 6d5730b..fa57583 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -6,6 +6,7 @@
 #include "isa.h"
 #include "fdc.h"
 #include "net.h"
+#include "memory.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -129,7 +130,8 @@ void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
 void pc_cpus_init(const char *cpu_model);
-void pc_memory_init(const char *kernel_filename,
+void pc_memory_init(MemoryRegion *system_memory,
+                    const char *kernel_filename,
                     const char *kernel_cmdline,
                     const char *initrd_filename,
                     ram_addr_t below_4g_mem_size,
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index c5c16b4..d83854c 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -39,6 +39,8 @@
 #include "blockdev.h"
 #include "smbus.h"
 #include "xen.h"
+#include "memory.h"
+#include "exec-memory.h"
 #ifdef CONFIG_XEN
 #  include <xen/hvm/hvm_info_table.h>
 #endif
@@ -89,6 +91,9 @@ static void pc_init1(ram_addr_t ram_size,
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BusState *idebus[MAX_IDE_BUS];
     ISADevice *rtc_state;
+    MemoryRegion *system_memory;
+
+    system_memory = get_system_memory();
 
     pc_cpus_init(cpu_model);
 
@@ -106,7 +111,8 @@ static void pc_init1(ram_addr_t ram_size,
 
     /* allocate ram and load rom/bios */
     if (!xen_enabled()) {
-        pc_memory_init(kernel_filename, kernel_cmdline, initrd_filename,
+        pc_memory_init(system_memory,
+                       kernel_filename, kernel_cmdline, initrd_filename,
                        below_4g_mem_size, above_4g_mem_size);
     }
 
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 17/23] pc: grab system_memory
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

While eventually this should come from the machine initialization function,
take a short cut to avoid converting all machines now.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/pc.c      |    3 ++-
 hw/pc.h      |    4 +++-
 hw/pc_piix.c |    8 +++++++-
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index a3e8539..369566a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -957,7 +957,8 @@ void pc_cpus_init(const char *cpu_model)
     }
 }
 
-void pc_memory_init(const char *kernel_filename,
+void pc_memory_init(MemoryRegion *system_memory,
+                    const char *kernel_filename,
                     const char *kernel_cmdline,
                     const char *initrd_filename,
                     ram_addr_t below_4g_mem_size,
diff --git a/hw/pc.h b/hw/pc.h
index 6d5730b..fa57583 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -6,6 +6,7 @@
 #include "isa.h"
 #include "fdc.h"
 #include "net.h"
+#include "memory.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -129,7 +130,8 @@ void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
 void pc_cpus_init(const char *cpu_model);
-void pc_memory_init(const char *kernel_filename,
+void pc_memory_init(MemoryRegion *system_memory,
+                    const char *kernel_filename,
                     const char *kernel_cmdline,
                     const char *initrd_filename,
                     ram_addr_t below_4g_mem_size,
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index c5c16b4..d83854c 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -39,6 +39,8 @@
 #include "blockdev.h"
 #include "smbus.h"
 #include "xen.h"
+#include "memory.h"
+#include "exec-memory.h"
 #ifdef CONFIG_XEN
 #  include <xen/hvm/hvm_info_table.h>
 #endif
@@ -89,6 +91,9 @@ static void pc_init1(ram_addr_t ram_size,
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BusState *idebus[MAX_IDE_BUS];
     ISADevice *rtc_state;
+    MemoryRegion *system_memory;
+
+    system_memory = get_system_memory();
 
     pc_cpus_init(cpu_model);
 
@@ -106,7 +111,8 @@ static void pc_init1(ram_addr_t ram_size,
 
     /* allocate ram and load rom/bios */
     if (!xen_enabled()) {
-        pc_memory_init(kernel_filename, kernel_cmdline, initrd_filename,
+        pc_memory_init(system_memory,
+                       kernel_filename, kernel_cmdline, initrd_filename,
                        below_4g_mem_size, above_4g_mem_size);
     }
 
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 18/23] pc: convert pc_memory_init() to memory API
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:02   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/pc.c |   59 ++++++++++++++++++++++++++++++++++++++++-------------------
 hw/pc.h |    1 +
 2 files changed, 41 insertions(+), 19 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 369566a..1c9d89a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -41,6 +41,7 @@
 #include "sysemu.h"
 #include "blockdev.h"
 #include "ui/qemu-spice.h"
+#include "memory.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -966,22 +967,30 @@ void pc_memory_init(MemoryRegion *system_memory,
 {
     char *filename;
     int ret, linux_boot, i;
-    ram_addr_t ram_addr, bios_offset, option_rom_offset;
+    MemoryRegion *ram, *bios, *isa_bios, *option_rom_mr;
+    MemoryRegion *ram_below_4g, *ram_above_4g;
     int bios_size, isa_bios_size;
     void *fw_cfg;
 
     linux_boot = (kernel_filename != NULL);
 
-    /* allocate RAM */
-    ram_addr = qemu_ram_alloc(NULL, "pc.ram",
-                              below_4g_mem_size + above_4g_mem_size);
-    cpu_register_physical_memory(0, 0xa0000, ram_addr);
-    cpu_register_physical_memory(0x100000,
-                 below_4g_mem_size - 0x100000,
-                 ram_addr + 0x100000);
+    /* Allocate RAM.  We allocate it as a single memory region and use
+     * aliases to address portions of it, mostly for backwards compatiblity
+     * with older qemus that used qemu_ram_alloc().
+     */
+    ram = qemu_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, NULL, "pc.ram",
+                           below_4g_mem_size + above_4g_mem_size);
+    ram_below_4g = qemu_malloc(sizeof(*ram_below_4g));
+    memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
+                             0, below_4g_mem_size);
+    memory_region_add_subregion(system_memory, 0, ram_below_4g);
     if (above_4g_mem_size > 0) {
-        cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
-                                     ram_addr + below_4g_mem_size);
+        ram_above_4g = qemu_malloc(sizeof(*ram_above_4g));
+        memory_region_init_alias(ram_above_4g, "ram-above-4g", ram,
+                                 below_4g_mem_size, above_4g_mem_size);
+        memory_region_add_subregion(system_memory, 0x100000000ULL,
+                                    ram_above_4g);
     }
 
     /* BIOS load */
@@ -997,7 +1006,9 @@ void pc_memory_init(MemoryRegion *system_memory,
         (bios_size % 65536) != 0) {
         goto bios_error;
     }
-    bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size);
+    bios = qemu_malloc(sizeof(*bios));
+    memory_region_init_ram(bios, NULL, "pc.bios", bios_size);
+    memory_region_set_readonly(bios, true);
     ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
     if (ret != 0) {
     bios_error:
@@ -1011,16 +1022,26 @@ void pc_memory_init(MemoryRegion *system_memory,
     isa_bios_size = bios_size;
     if (isa_bios_size > (128 * 1024))
         isa_bios_size = 128 * 1024;
-    cpu_register_physical_memory(0x100000 - isa_bios_size,
-                                 isa_bios_size,
-                                 (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
-
-    option_rom_offset = qemu_ram_alloc(NULL, "pc.rom", PC_ROM_SIZE);
-    cpu_register_physical_memory(PC_ROM_MIN_VGA, PC_ROM_SIZE, option_rom_offset);
+    isa_bios = qemu_malloc(sizeof(*isa_bios));
+    memory_region_init_alias(isa_bios, "isa-bios", bios,
+                             bios_size - isa_bios_size, isa_bios_size);
+    memory_region_add_subregion_overlap(system_memory,
+                                        0x100000 - isa_bios_size,
+                                        isa_bios,
+                                        1);
+    memory_region_set_readonly(isa_bios, true);
+
+    option_rom_mr = qemu_malloc(sizeof(*option_rom_mr));
+    memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE);
+    memory_region_add_subregion_overlap(system_memory,
+                                        PC_ROM_MIN_VGA,
+                                        option_rom_mr,
+                                        1);
 
     /* map all the bios at the top of memory */
-    cpu_register_physical_memory((uint32_t)(-bios_size),
-                                 bios_size, bios_offset | IO_MEM_ROM);
+    memory_region_add_subregion(system_memory,
+                                (uint32_t)(-bios_size),
+                                bios);
 
     fw_cfg = bochs_bios_init();
     rom_set_fw(fw_cfg);
diff --git a/hw/pc.h b/hw/pc.h
index fa57583..40684f4 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -2,6 +2,7 @@
 #define HW_PC_H
 
 #include "qemu-common.h"
+#include "memory.h"
 #include "ioport.h"
 #include "isa.h"
 #include "fdc.h"
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 18/23] pc: convert pc_memory_init() to memory API
@ 2011-07-25 14:02   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/pc.c |   59 ++++++++++++++++++++++++++++++++++++++++-------------------
 hw/pc.h |    1 +
 2 files changed, 41 insertions(+), 19 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index 369566a..1c9d89a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -41,6 +41,7 @@
 #include "sysemu.h"
 #include "blockdev.h"
 #include "ui/qemu-spice.h"
+#include "memory.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -966,22 +967,30 @@ void pc_memory_init(MemoryRegion *system_memory,
 {
     char *filename;
     int ret, linux_boot, i;
-    ram_addr_t ram_addr, bios_offset, option_rom_offset;
+    MemoryRegion *ram, *bios, *isa_bios, *option_rom_mr;
+    MemoryRegion *ram_below_4g, *ram_above_4g;
     int bios_size, isa_bios_size;
     void *fw_cfg;
 
     linux_boot = (kernel_filename != NULL);
 
-    /* allocate RAM */
-    ram_addr = qemu_ram_alloc(NULL, "pc.ram",
-                              below_4g_mem_size + above_4g_mem_size);
-    cpu_register_physical_memory(0, 0xa0000, ram_addr);
-    cpu_register_physical_memory(0x100000,
-                 below_4g_mem_size - 0x100000,
-                 ram_addr + 0x100000);
+    /* Allocate RAM.  We allocate it as a single memory region and use
+     * aliases to address portions of it, mostly for backwards compatiblity
+     * with older qemus that used qemu_ram_alloc().
+     */
+    ram = qemu_malloc(sizeof(*ram));
+    memory_region_init_ram(ram, NULL, "pc.ram",
+                           below_4g_mem_size + above_4g_mem_size);
+    ram_below_4g = qemu_malloc(sizeof(*ram_below_4g));
+    memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
+                             0, below_4g_mem_size);
+    memory_region_add_subregion(system_memory, 0, ram_below_4g);
     if (above_4g_mem_size > 0) {
-        cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
-                                     ram_addr + below_4g_mem_size);
+        ram_above_4g = qemu_malloc(sizeof(*ram_above_4g));
+        memory_region_init_alias(ram_above_4g, "ram-above-4g", ram,
+                                 below_4g_mem_size, above_4g_mem_size);
+        memory_region_add_subregion(system_memory, 0x100000000ULL,
+                                    ram_above_4g);
     }
 
     /* BIOS load */
@@ -997,7 +1006,9 @@ void pc_memory_init(MemoryRegion *system_memory,
         (bios_size % 65536) != 0) {
         goto bios_error;
     }
-    bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size);
+    bios = qemu_malloc(sizeof(*bios));
+    memory_region_init_ram(bios, NULL, "pc.bios", bios_size);
+    memory_region_set_readonly(bios, true);
     ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
     if (ret != 0) {
     bios_error:
@@ -1011,16 +1022,26 @@ void pc_memory_init(MemoryRegion *system_memory,
     isa_bios_size = bios_size;
     if (isa_bios_size > (128 * 1024))
         isa_bios_size = 128 * 1024;
-    cpu_register_physical_memory(0x100000 - isa_bios_size,
-                                 isa_bios_size,
-                                 (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
-
-    option_rom_offset = qemu_ram_alloc(NULL, "pc.rom", PC_ROM_SIZE);
-    cpu_register_physical_memory(PC_ROM_MIN_VGA, PC_ROM_SIZE, option_rom_offset);
+    isa_bios = qemu_malloc(sizeof(*isa_bios));
+    memory_region_init_alias(isa_bios, "isa-bios", bios,
+                             bios_size - isa_bios_size, isa_bios_size);
+    memory_region_add_subregion_overlap(system_memory,
+                                        0x100000 - isa_bios_size,
+                                        isa_bios,
+                                        1);
+    memory_region_set_readonly(isa_bios, true);
+
+    option_rom_mr = qemu_malloc(sizeof(*option_rom_mr));
+    memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE);
+    memory_region_add_subregion_overlap(system_memory,
+                                        PC_ROM_MIN_VGA,
+                                        option_rom_mr,
+                                        1);
 
     /* map all the bios at the top of memory */
-    cpu_register_physical_memory((uint32_t)(-bios_size),
-                                 bios_size, bios_offset | IO_MEM_ROM);
+    memory_region_add_subregion(system_memory,
+                                (uint32_t)(-bios_size),
+                                bios);
 
     fw_cfg = bochs_bios_init();
     rom_set_fw(fw_cfg);
diff --git a/hw/pc.h b/hw/pc.h
index fa57583..40684f4 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -2,6 +2,7 @@
 #define HW_PC_H
 
 #include "qemu-common.h"
+#include "memory.h"
 #include "ioport.h"
 #include "isa.h"
 #include "fdc.h"
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 19/23] pc: move global memory map out of pc_init1() and into its callers
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:03   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/pc_piix.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index d83854c..f2d0476 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -68,7 +68,8 @@ static void ioapic_init(IsaIrqState *isa_irq_state)
 }
 
 /* PC hardware initialisation */
-static void pc_init1(ram_addr_t ram_size,
+static void pc_init1(MemoryRegion *system_memory,
+                     ram_addr_t ram_size,
                      const char *boot_device,
                      const char *kernel_filename,
                      const char *kernel_cmdline,
@@ -91,9 +92,6 @@ static void pc_init1(ram_addr_t ram_size,
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BusState *idebus[MAX_IDE_BUS];
     ISADevice *rtc_state;
-    MemoryRegion *system_memory;
-
-    system_memory = get_system_memory();
 
     pc_cpus_init(cpu_model);
 
@@ -214,7 +212,8 @@ static void pc_init_pci(ram_addr_t ram_size,
                         const char *initrd_filename,
                         const char *cpu_model)
 {
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 1, 1);
 }
@@ -226,7 +225,8 @@ static void pc_init_pci_no_kvmclock(ram_addr_t ram_size,
                                     const char *initrd_filename,
                                     const char *cpu_model)
 {
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 1, 0);
 }
@@ -240,7 +240,8 @@ static void pc_init_isa(ram_addr_t ram_size,
 {
     if (cpu_model == NULL)
         cpu_model = "486";
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 0, 1);
 }
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 19/23] pc: move global memory map out of pc_init1() and into its callers
@ 2011-07-25 14:03   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/pc_piix.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index d83854c..f2d0476 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -68,7 +68,8 @@ static void ioapic_init(IsaIrqState *isa_irq_state)
 }
 
 /* PC hardware initialisation */
-static void pc_init1(ram_addr_t ram_size,
+static void pc_init1(MemoryRegion *system_memory,
+                     ram_addr_t ram_size,
                      const char *boot_device,
                      const char *kernel_filename,
                      const char *kernel_cmdline,
@@ -91,9 +92,6 @@ static void pc_init1(ram_addr_t ram_size,
     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BusState *idebus[MAX_IDE_BUS];
     ISADevice *rtc_state;
-    MemoryRegion *system_memory;
-
-    system_memory = get_system_memory();
 
     pc_cpus_init(cpu_model);
 
@@ -214,7 +212,8 @@ static void pc_init_pci(ram_addr_t ram_size,
                         const char *initrd_filename,
                         const char *cpu_model)
 {
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 1, 1);
 }
@@ -226,7 +225,8 @@ static void pc_init_pci_no_kvmclock(ram_addr_t ram_size,
                                     const char *initrd_filename,
                                     const char *cpu_model)
 {
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 1, 0);
 }
@@ -240,7 +240,8 @@ static void pc_init_isa(ram_addr_t ram_size,
 {
     if (cpu_model == NULL)
         cpu_model = "486";
-    pc_init1(ram_size, boot_device,
+    pc_init1(get_system_memory(),
+             ram_size, boot_device,
              kernel_filename, kernel_cmdline,
              initrd_filename, cpu_model, 0, 1);
 }
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 20/23] pci: pass address space to pci bus when created
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:03   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

This is now done sloppily, via get_system_memory().  Eventually callers
will be converted to stop using that.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/apb_pci.c       |    2 ++
 hw/bonito.c        |    4 +++-
 hw/grackle_pci.c   |    5 +++--
 hw/gt64xxx.c       |    4 +++-
 hw/pc.h            |    4 +++-
 hw/pc_piix.c       |    3 ++-
 hw/pci.c           |   16 +++++++++++-----
 hw/pci.h           |   12 +++++++++---
 hw/pci_host.h      |    1 +
 hw/pci_internals.h |    1 +
 hw/piix_pci.c      |   13 +++++++++----
 hw/ppc4xx_pci.c    |    5 ++++-
 hw/ppc_mac.h       |    9 ++++++---
 hw/ppc_newworld.c  |    5 +++--
 hw/ppc_oldworld.c  |    3 ++-
 hw/ppc_prep.c      |    3 ++-
 hw/ppce500_pci.c   |    6 +++++-
 hw/prep_pci.c      |    5 +++--
 hw/prep_pci.h      |    3 ++-
 hw/sh_pci.c        |    4 +++-
 hw/unin_pci.c      |   10 ++++++----
 hw/versatile_pci.c |    2 ++
 22 files changed, 85 insertions(+), 35 deletions(-)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 974c87a..8b9939c 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -34,6 +34,7 @@
 #include "rwhandler.h"
 #include "apb_pci.h"
 #include "sysemu.h"
+#include "exec-memory.h"
 
 /* debug APB */
 //#define DEBUG_APB
@@ -346,6 +347,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
 
     d->bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_apb_set_irq, pci_pbm_map_irq, d,
+                                         get_system_memory(),
                                          0, 32);
     pci_bus_set_mem_base(d->bus, mem_base);
 
diff --git a/hw/bonito.c b/hw/bonito.c
index e8c57a3..5f62dda 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -42,6 +42,7 @@
 #include "mips.h"
 #include "pci_host.h"
 #include "sysemu.h"
+#include "exec-memory.h"
 
 //#define DEBUG_BONITO
 
@@ -773,7 +774,8 @@ PCIBus *bonito_init(qemu_irq *pic)
     dev = qdev_create(NULL, "Bonito-pcihost");
     pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev));
     b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq,
-                         pci_bonito_map_irq, pic, 0x28, 32);
+                         pci_bonito_map_irq, pic, get_system_memory(),
+                         0x28, 32);
     pcihost->bus = b;
     qdev_init_nofail(dev);
 
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index cee07e0..da67cf9 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -61,7 +61,8 @@ static void pci_grackle_reset(void *opaque)
 {
 }
 
-PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
+                         MemoryRegion *address_space)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -74,7 +75,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_grackle_set_irq,
                                          pci_grackle_map_irq,
-                                         pic, 0, 4);
+                                         pic, address_space, 0, 4);
 
     pci_create_simple(d->host_state.bus, 0, "grackle");
 
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 8e1f6a0..65e63dd 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -27,6 +27,7 @@
 #include "pci.h"
 #include "pci_host.h"
 #include "pc.h"
+#include "exec-memory.h"
 
 //#define DEBUG
 
@@ -1092,7 +1093,8 @@ PCIBus *gt64120_register(qemu_irq *pic)
     d = FROM_SYSBUS(GT64120State, s);
     d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                   gt64120_pci_set_irq, gt64120_pci_map_irq,
-                                  pic, PCI_DEVFN(18, 0), 4);
+                                  pic, get_system_memory(),
+                                  PCI_DEVFN(18, 0), 4);
     d->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, d,
                                            DEVICE_NATIVE_ENDIAN);
 
diff --git a/hw/pc.h b/hw/pc.h
index 40684f4..a2de0fe 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -178,7 +178,9 @@ int pcspk_audio_init(qemu_irq *pic);
 struct PCII440FXState;
 typedef struct PCII440FXState PCII440FXState;
 
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, ram_addr_t ram_size);
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
+                    qemu_irq *pic, MemoryRegion *address_space,
+                    ram_addr_t ram_size);
 void i440fx_init_memory_mappings(PCII440FXState *d);
 
 /* piix4.c */
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index f2d0476..2b9c2b1 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -128,7 +128,8 @@ static void pc_init1(MemoryRegion *system_memory,
     isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
 
     if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
+        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq,
+                              system_memory, ram_size);
     } else {
         pci_bus = NULL;
         i440fx_state = NULL;
diff --git a/hw/pci.c b/hw/pci.c
index b904a4e..cf16f3b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -263,11 +263,14 @@ int pci_find_domain(const PCIBus *bus)
 }
 
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, uint8_t devfn_min)
+                         const char *name,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min)
 {
     qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
     assert(PCI_FUNC(devfn_min) == 0);
     bus->devfn_min = devfn_min;
+    bus->address_space = address_space;
 
     /* host bridge */
     QLIST_INIT(&bus->child);
@@ -276,13 +279,14 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
 }
 
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min)
+PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    MemoryRegion *address_space, uint8_t devfn_min)
 {
     PCIBus *bus;
 
     bus = qemu_mallocz(sizeof(*bus));
     bus->qbus.qdev_allocated = 1;
-    pci_bus_new_inplace(bus, parent, name, devfn_min);
+    pci_bus_new_inplace(bus, parent, name, address_space, devfn_min);
     return bus;
 }
 
@@ -310,11 +314,13 @@ void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base)
 
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, uint8_t devfn_min, int nirq)
+                         void *irq_opaque,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min, int nirq)
 {
     PCIBus *bus;
 
-    bus = pci_bus_new(parent, name, devfn_min);
+    bus = pci_bus_new(parent, name, address_space, devfn_min);
     pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
     return bus;
 }
diff --git a/hw/pci.h b/hw/pci.h
index c220745..cfeb042 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -5,6 +5,7 @@
 #include "qobject.h"
 
 #include "qdev.h"
+#include "memory.h"
 
 /* PCI includes legacy ISA access.  */
 #include "isa.h"
@@ -233,15 +234,20 @@ typedef enum {
 typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
                               PCIHotplugState state);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, uint8_t devfn_min);
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
+                         const char *name,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min);
+PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    MemoryRegion *address_space, uint8_t devfn_min);
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                   void *irq_opaque, int nirq);
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, uint8_t devfn_min, int nirq);
+                         void *irq_opaque,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min, int nirq);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 0a58595..05dcb66 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -35,6 +35,7 @@ struct PCIHostState {
     SysBusDevice busdev;
     ReadWriteHandler conf_handler;
     ReadWriteHandler data_handler;
+    MemoryRegion *address_space;
     uint32_t config_reg;
     PCIBus *bus;
 };
diff --git a/hw/pci_internals.h b/hw/pci_internals.h
index fbe1866..c3a463a 100644
--- a/hw/pci_internals.h
+++ b/hw/pci_internals.h
@@ -25,6 +25,7 @@ struct PCIBus {
     PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
     PCIDevice *parent_dev;
     target_phys_addr_t mem_base;
+    MemoryRegion *address_space;
 
     QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
     QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index d08b31a..80d6665 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -241,7 +241,9 @@ static int i440fx_initfn(PCIDevice *dev)
 static PCIBus *i440fx_common_init(const char *device_name,
                                   PCII440FXState **pi440fx_state,
                                   int *piix3_devfn,
-                                  qemu_irq *pic, ram_addr_t ram_size)
+                                  qemu_irq *pic,
+                                  MemoryRegion *address_space,
+                                  ram_addr_t ram_size)
 {
     DeviceState *dev;
     PCIBus *b;
@@ -251,7 +253,8 @@ static PCIBus *i440fx_common_init(const char *device_name,
 
     dev = qdev_create(NULL, "i440FX-pcihost");
     s = FROM_SYSBUS(I440FXState, sysbus_from_qdev(dev));
-    b = pci_bus_new(&s->busdev.qdev, NULL, 0);
+    s->address_space = address_space;
+    b = pci_bus_new(&s->busdev.qdev, NULL, s->address_space, 0);
     s->bus = b;
     qdev_init_nofail(dev);
 
@@ -288,11 +291,13 @@ static PCIBus *i440fx_common_init(const char *device_name,
 }
 
 PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
-                    qemu_irq *pic, ram_addr_t ram_size)
+                    qemu_irq *pic, MemoryRegion *address_space,
+                    ram_addr_t ram_size)
 {
     PCIBus *b;
 
-    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic, ram_size);
+    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic,
+                           address_space, ram_size);
     return b;
 }
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 299473c..15c24f6 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -24,6 +24,7 @@
 #include "ppc4xx.h"
 #include "pci.h"
 #include "pci_host.h"
+#include "exec-memory.h"
 
 #undef DEBUG
 #ifdef DEBUG
@@ -345,7 +346,9 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     controller->pci_state.bus = pci_register_bus(NULL, "pci",
                                                  ppc4xx_pci_set_irq,
                                                  ppc4xx_pci_map_irq,
-                                                 pci_irqs, 0, 4);
+                                                 pci_irqs,
+                                                 get_system_memory(),
+                                                 0, 4);
 
     controller->pci_dev = pci_register_device(controller->pci_state.bus,
                                               "host bridge", sizeof(PCIDevice),
diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
index 68dade7..6fad20a 100644
--- a/hw/ppc_mac.h
+++ b/hw/ppc_mac.h
@@ -25,6 +25,8 @@
 #if !defined(__PPC_MAC_H__)
 #define __PPC_MAC_H__
 
+#include "memory.h"
+
 /* SMP is not enabled, for now */
 #define MAX_CPUS 1
 
@@ -52,11 +54,12 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
                             int nb_cpus, qemu_irq **irqs);
 
 /* Grackle PCI */
-PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
+                         MemoryRegion *address_space);
 
 /* UniNorth PCI */
-PCIBus *pci_pmac_init(qemu_irq *pic);
-PCIBus *pci_pmac_u3_init(qemu_irq *pic);
+PCIBus *pci_pmac_init(qemu_irq *pic, MemoryRegion *address_space);
+PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space);
 
 /* Mac NVRAM */
 typedef struct MacIONVRAMState MacIONVRAMState;
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 5bce709..2c0fae8 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -67,6 +67,7 @@
 #include "kvm_ppc.h"
 #include "hw/usb.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define MAX_IDE_BUS 2
 #define CFG_ADDR 0xf0000510
@@ -317,10 +318,10 @@ static void ppc_core99_init (ram_addr_t ram_size,
     pic = openpic_init(NULL, &pic_mem_index, smp_cpus, openpic_irqs, NULL);
     if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
         /* 970 gets a U3 bus */
-        pci_bus = pci_pmac_u3_init(pic);
+        pci_bus = pci_pmac_u3_init(pic, get_system_memory());
         machine_arch = ARCH_MAC99_U3;
     } else {
-        pci_bus = pci_pmac_init(pic);
+        pci_bus = pci_pmac_init(pic, get_system_memory());
         machine_arch = ARCH_MAC99;
     }
     /* init basic PC hardware */
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 20cd8e1..585afd6 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -43,6 +43,7 @@
 #include "kvm.h"
 #include "kvm_ppc.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define MAX_IDE_BUS 2
 #define CFG_ADDR 0xf0000510
@@ -233,7 +234,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
         hw_error("Only 6xx bus is supported on heathrow machine\n");
     }
     pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
-    pci_bus = pci_grackle_init(0xfec00000, pic);
+    pci_bus = pci_grackle_init(0xfec00000, pic, get_system_memory());
     pci_vga_init(pci_bus);
 
     escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 0e9cfc2..91ebe07 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -38,6 +38,7 @@
 #include "loader.h"
 #include "mc146818rtc.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 //#define HARD_DEBUG_PPC_IO
 //#define DEBUG_PPC_IO
@@ -648,7 +649,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
         hw_error("Only 6xx bus is supported on PREP machine\n");
     }
     i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
-    pci_bus = pci_prep_init(i8259);
+    pci_bus = pci_prep_init(i8259, get_system_memory());
     /* Hmm, prep has no pci-isa bridge ??? */
     isa_bus_new(NULL);
     isa_bus_irqs(i8259);
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index fc11af4..1344539 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -274,12 +274,15 @@ static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
                                  s->reg);
 }
 
+#include "exec-memory.h"
+
 static int e500_pcihost_initfn(SysBusDevice *dev)
 {
     PCIHostState *h;
     PPCE500PCIState *s;
     PCIBus *b;
     int i;
+    MemoryRegion *address_space = get_system_memory();
 
     h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
     s = DO_UPCAST(PPCE500PCIState, pci_state, h);
@@ -289,7 +292,8 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
     }
 
     b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
-                         mpc85xx_pci_map_irq, s->irq, PCI_DEVFN(0x11, 0), 4);
+                         mpc85xx_pci_map_irq, s->irq, address_space,
+                         PCI_DEVFN(0x11, 0), 4);
     s->pci_state.bus = b;
 
     pci_create_simple(b, 0, "e500-host-bridge");
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index f88b825..da02f0e 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -110,7 +110,7 @@ static void prep_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(pic[(irq_num & 1) ? 11 : 9] , level);
 }
 
-PCIBus *pci_prep_init(qemu_irq *pic)
+PCIBus *pci_prep_init(qemu_irq *pic, MemoryRegion *address_space)
 {
     PREPPCIState *s;
     PCIDevice *d;
@@ -118,7 +118,8 @@ PCIBus *pci_prep_init(qemu_irq *pic)
 
     s = qemu_mallocz(sizeof(PREPPCIState));
     s->bus = pci_register_bus(NULL, "pci",
-                              prep_set_irq, prep_map_irq, pic, 0, 4);
+                              prep_set_irq, prep_map_irq, pic,
+                              address_space, 0, 4);
 
     pci_host_conf_register_ioport(0xcf8, s);
 
diff --git a/hw/prep_pci.h b/hw/prep_pci.h
index cd68512..a27368b 100644
--- a/hw/prep_pci.h
+++ b/hw/prep_pci.h
@@ -2,7 +2,8 @@
 #define QEMU_PREP_PCI_H
 
 #include "qemu-common.h"
+#include "memory.h"
 
-PCIBus *pci_prep_init(qemu_irq *pic);
+PCIBus *pci_prep_init(qemu_irq *pic, MemoryRegion *address_space);
 
 #endif
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index a076cf2..0ef93a0 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -26,6 +26,7 @@
 #include "pci.h"
 #include "pci_host.h"
 #include "bswap.h"
+#include "exec-memory.h"
 
 typedef struct SHPCIState {
     SysBusDevice busdev;
@@ -127,7 +128,8 @@ static int sh_pci_init_device(SysBusDevice *dev)
     }
     s->bus = pci_register_bus(&s->busdev.qdev, "pci",
                               sh_pci_set_irq, sh_pci_map_irq,
-                              s->irq, PCI_DEVFN(0, 0), 4);
+                              s->irq, get_system_memory(),
+                              PCI_DEVFN(0, 0), 4);
     s->memconfig = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w,
                                           s, DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio_cb(dev, 0x224, sh_pci_map);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index d364daa..b499523 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -201,7 +201,7 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
     return 0;
 }
 
-PCIBus *pci_pmac_init(qemu_irq *pic)
+PCIBus *pci_pmac_init(qemu_irq *pic, MemoryRegion *address_space)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -215,7 +215,8 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
     d = FROM_SYSBUS(UNINState, s);
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_unin_set_irq, pci_unin_map_irq,
-                                         pic, PCI_DEVFN(11, 0), 4);
+                                         pic, address_space,
+                                         PCI_DEVFN(11, 0), 4);
 
 #if 0
     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
@@ -252,7 +253,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
     return d->host_state.bus;
 }
 
-PCIBus *pci_pmac_u3_init(qemu_irq *pic)
+PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -267,7 +268,8 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic)
 
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_unin_set_irq, pci_unin_map_irq,
-                                         pic, PCI_DEVFN(11, 0), 4);
+                                         pic, address_space,
+                                         PCI_DEVFN(11, 0), 4);
 
     sysbus_mmio_map(s, 0, 0xf0800000);
     sysbus_mmio_map(s, 1, 0xf0c00000);
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 290a900..cffe387 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -10,6 +10,7 @@
 #include "sysbus.h"
 #include "pci.h"
 #include "pci_host.h"
+#include "exec-memory.h"
 
 typedef struct {
     SysBusDevice busdev;
@@ -111,6 +112,7 @@ static int pci_vpb_init(SysBusDevice *dev)
     }
     bus = pci_register_bus(&dev->qdev, "pci",
                            pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
+                           get_system_memory(),
                            PCI_DEVFN(11, 0), 4);
 
     /* ??? Register memory space.  */
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 20/23] pci: pass address space to pci bus when created
@ 2011-07-25 14:03   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

This is now done sloppily, via get_system_memory().  Eventually callers
will be converted to stop using that.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/apb_pci.c       |    2 ++
 hw/bonito.c        |    4 +++-
 hw/grackle_pci.c   |    5 +++--
 hw/gt64xxx.c       |    4 +++-
 hw/pc.h            |    4 +++-
 hw/pc_piix.c       |    3 ++-
 hw/pci.c           |   16 +++++++++++-----
 hw/pci.h           |   12 +++++++++---
 hw/pci_host.h      |    1 +
 hw/pci_internals.h |    1 +
 hw/piix_pci.c      |   13 +++++++++----
 hw/ppc4xx_pci.c    |    5 ++++-
 hw/ppc_mac.h       |    9 ++++++---
 hw/ppc_newworld.c  |    5 +++--
 hw/ppc_oldworld.c  |    3 ++-
 hw/ppc_prep.c      |    3 ++-
 hw/ppce500_pci.c   |    6 +++++-
 hw/prep_pci.c      |    5 +++--
 hw/prep_pci.h      |    3 ++-
 hw/sh_pci.c        |    4 +++-
 hw/unin_pci.c      |   10 ++++++----
 hw/versatile_pci.c |    2 ++
 22 files changed, 85 insertions(+), 35 deletions(-)

diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 974c87a..8b9939c 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -34,6 +34,7 @@
 #include "rwhandler.h"
 #include "apb_pci.h"
 #include "sysemu.h"
+#include "exec-memory.h"
 
 /* debug APB */
 //#define DEBUG_APB
@@ -346,6 +347,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
 
     d->bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_apb_set_irq, pci_pbm_map_irq, d,
+                                         get_system_memory(),
                                          0, 32);
     pci_bus_set_mem_base(d->bus, mem_base);
 
diff --git a/hw/bonito.c b/hw/bonito.c
index e8c57a3..5f62dda 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -42,6 +42,7 @@
 #include "mips.h"
 #include "pci_host.h"
 #include "sysemu.h"
+#include "exec-memory.h"
 
 //#define DEBUG_BONITO
 
@@ -773,7 +774,8 @@ PCIBus *bonito_init(qemu_irq *pic)
     dev = qdev_create(NULL, "Bonito-pcihost");
     pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev));
     b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq,
-                         pci_bonito_map_irq, pic, 0x28, 32);
+                         pci_bonito_map_irq, pic, get_system_memory(),
+                         0x28, 32);
     pcihost->bus = b;
     qdev_init_nofail(dev);
 
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index cee07e0..da67cf9 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -61,7 +61,8 @@ static void pci_grackle_reset(void *opaque)
 {
 }
 
-PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
+                         MemoryRegion *address_space)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -74,7 +75,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_grackle_set_irq,
                                          pci_grackle_map_irq,
-                                         pic, 0, 4);
+                                         pic, address_space, 0, 4);
 
     pci_create_simple(d->host_state.bus, 0, "grackle");
 
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 8e1f6a0..65e63dd 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -27,6 +27,7 @@
 #include "pci.h"
 #include "pci_host.h"
 #include "pc.h"
+#include "exec-memory.h"
 
 //#define DEBUG
 
@@ -1092,7 +1093,8 @@ PCIBus *gt64120_register(qemu_irq *pic)
     d = FROM_SYSBUS(GT64120State, s);
     d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                   gt64120_pci_set_irq, gt64120_pci_map_irq,
-                                  pic, PCI_DEVFN(18, 0), 4);
+                                  pic, get_system_memory(),
+                                  PCI_DEVFN(18, 0), 4);
     d->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, d,
                                            DEVICE_NATIVE_ENDIAN);
 
diff --git a/hw/pc.h b/hw/pc.h
index 40684f4..a2de0fe 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -178,7 +178,9 @@ int pcspk_audio_init(qemu_irq *pic);
 struct PCII440FXState;
 typedef struct PCII440FXState PCII440FXState;
 
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, ram_addr_t ram_size);
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
+                    qemu_irq *pic, MemoryRegion *address_space,
+                    ram_addr_t ram_size);
 void i440fx_init_memory_mappings(PCII440FXState *d);
 
 /* piix4.c */
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index f2d0476..2b9c2b1 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -128,7 +128,8 @@ static void pc_init1(MemoryRegion *system_memory,
     isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
 
     if (pci_enabled) {
-        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
+        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq,
+                              system_memory, ram_size);
     } else {
         pci_bus = NULL;
         i440fx_state = NULL;
diff --git a/hw/pci.c b/hw/pci.c
index b904a4e..cf16f3b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -263,11 +263,14 @@ int pci_find_domain(const PCIBus *bus)
 }
 
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, uint8_t devfn_min)
+                         const char *name,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min)
 {
     qbus_create_inplace(&bus->qbus, &pci_bus_info, parent, name);
     assert(PCI_FUNC(devfn_min) == 0);
     bus->devfn_min = devfn_min;
+    bus->address_space = address_space;
 
     /* host bridge */
     QLIST_INIT(&bus->child);
@@ -276,13 +279,14 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
 }
 
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min)
+PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    MemoryRegion *address_space, uint8_t devfn_min)
 {
     PCIBus *bus;
 
     bus = qemu_mallocz(sizeof(*bus));
     bus->qbus.qdev_allocated = 1;
-    pci_bus_new_inplace(bus, parent, name, devfn_min);
+    pci_bus_new_inplace(bus, parent, name, address_space, devfn_min);
     return bus;
 }
 
@@ -310,11 +314,13 @@ void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base)
 
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, uint8_t devfn_min, int nirq)
+                         void *irq_opaque,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min, int nirq)
 {
     PCIBus *bus;
 
-    bus = pci_bus_new(parent, name, devfn_min);
+    bus = pci_bus_new(parent, name, address_space, devfn_min);
     pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
     return bus;
 }
diff --git a/hw/pci.h b/hw/pci.h
index c220745..cfeb042 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -5,6 +5,7 @@
 #include "qobject.h"
 
 #include "qdev.h"
+#include "memory.h"
 
 /* PCI includes legacy ISA access.  */
 #include "isa.h"
@@ -233,15 +234,20 @@ typedef enum {
 typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
                               PCIHotplugState state);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
-                         const char *name, uint8_t devfn_min);
-PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
+                         const char *name,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min);
+PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    MemoryRegion *address_space, uint8_t devfn_min);
 void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                   void *irq_opaque, int nirq);
 int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
 void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
-                         void *irq_opaque, uint8_t devfn_min, int nirq);
+                         void *irq_opaque,
+                         MemoryRegion *address_space,
+                         uint8_t devfn_min, int nirq);
 void pci_device_reset(PCIDevice *dev);
 void pci_bus_reset(PCIBus *bus);
 
diff --git a/hw/pci_host.h b/hw/pci_host.h
index 0a58595..05dcb66 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -35,6 +35,7 @@ struct PCIHostState {
     SysBusDevice busdev;
     ReadWriteHandler conf_handler;
     ReadWriteHandler data_handler;
+    MemoryRegion *address_space;
     uint32_t config_reg;
     PCIBus *bus;
 };
diff --git a/hw/pci_internals.h b/hw/pci_internals.h
index fbe1866..c3a463a 100644
--- a/hw/pci_internals.h
+++ b/hw/pci_internals.h
@@ -25,6 +25,7 @@ struct PCIBus {
     PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
     PCIDevice *parent_dev;
     target_phys_addr_t mem_base;
+    MemoryRegion *address_space;
 
     QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
     QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index d08b31a..80d6665 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -241,7 +241,9 @@ static int i440fx_initfn(PCIDevice *dev)
 static PCIBus *i440fx_common_init(const char *device_name,
                                   PCII440FXState **pi440fx_state,
                                   int *piix3_devfn,
-                                  qemu_irq *pic, ram_addr_t ram_size)
+                                  qemu_irq *pic,
+                                  MemoryRegion *address_space,
+                                  ram_addr_t ram_size)
 {
     DeviceState *dev;
     PCIBus *b;
@@ -251,7 +253,8 @@ static PCIBus *i440fx_common_init(const char *device_name,
 
     dev = qdev_create(NULL, "i440FX-pcihost");
     s = FROM_SYSBUS(I440FXState, sysbus_from_qdev(dev));
-    b = pci_bus_new(&s->busdev.qdev, NULL, 0);
+    s->address_space = address_space;
+    b = pci_bus_new(&s->busdev.qdev, NULL, s->address_space, 0);
     s->bus = b;
     qdev_init_nofail(dev);
 
@@ -288,11 +291,13 @@ static PCIBus *i440fx_common_init(const char *device_name,
 }
 
 PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
-                    qemu_irq *pic, ram_addr_t ram_size)
+                    qemu_irq *pic, MemoryRegion *address_space,
+                    ram_addr_t ram_size)
 {
     PCIBus *b;
 
-    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic, ram_size);
+    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic,
+                           address_space, ram_size);
     return b;
 }
 
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index 299473c..15c24f6 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -24,6 +24,7 @@
 #include "ppc4xx.h"
 #include "pci.h"
 #include "pci_host.h"
+#include "exec-memory.h"
 
 #undef DEBUG
 #ifdef DEBUG
@@ -345,7 +346,9 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
     controller->pci_state.bus = pci_register_bus(NULL, "pci",
                                                  ppc4xx_pci_set_irq,
                                                  ppc4xx_pci_map_irq,
-                                                 pci_irqs, 0, 4);
+                                                 pci_irqs,
+                                                 get_system_memory(),
+                                                 0, 4);
 
     controller->pci_dev = pci_register_device(controller->pci_state.bus,
                                               "host bridge", sizeof(PCIDevice),
diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
index 68dade7..6fad20a 100644
--- a/hw/ppc_mac.h
+++ b/hw/ppc_mac.h
@@ -25,6 +25,8 @@
 #if !defined(__PPC_MAC_H__)
 #define __PPC_MAC_H__
 
+#include "memory.h"
+
 /* SMP is not enabled, for now */
 #define MAX_CPUS 1
 
@@ -52,11 +54,12 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
                             int nb_cpus, qemu_irq **irqs);
 
 /* Grackle PCI */
-PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
+PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
+                         MemoryRegion *address_space);
 
 /* UniNorth PCI */
-PCIBus *pci_pmac_init(qemu_irq *pic);
-PCIBus *pci_pmac_u3_init(qemu_irq *pic);
+PCIBus *pci_pmac_init(qemu_irq *pic, MemoryRegion *address_space);
+PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space);
 
 /* Mac NVRAM */
 typedef struct MacIONVRAMState MacIONVRAMState;
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 5bce709..2c0fae8 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -67,6 +67,7 @@
 #include "kvm_ppc.h"
 #include "hw/usb.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define MAX_IDE_BUS 2
 #define CFG_ADDR 0xf0000510
@@ -317,10 +318,10 @@ static void ppc_core99_init (ram_addr_t ram_size,
     pic = openpic_init(NULL, &pic_mem_index, smp_cpus, openpic_irqs, NULL);
     if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
         /* 970 gets a U3 bus */
-        pci_bus = pci_pmac_u3_init(pic);
+        pci_bus = pci_pmac_u3_init(pic, get_system_memory());
         machine_arch = ARCH_MAC99_U3;
     } else {
-        pci_bus = pci_pmac_init(pic);
+        pci_bus = pci_pmac_init(pic, get_system_memory());
         machine_arch = ARCH_MAC99;
     }
     /* init basic PC hardware */
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 20cd8e1..585afd6 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -43,6 +43,7 @@
 #include "kvm.h"
 #include "kvm_ppc.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 #define MAX_IDE_BUS 2
 #define CFG_ADDR 0xf0000510
@@ -233,7 +234,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
         hw_error("Only 6xx bus is supported on heathrow machine\n");
     }
     pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
-    pci_bus = pci_grackle_init(0xfec00000, pic);
+    pci_bus = pci_grackle_init(0xfec00000, pic, get_system_memory());
     pci_vga_init(pci_bus);
 
     escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 0e9cfc2..91ebe07 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -38,6 +38,7 @@
 #include "loader.h"
 #include "mc146818rtc.h"
 #include "blockdev.h"
+#include "exec-memory.h"
 
 //#define HARD_DEBUG_PPC_IO
 //#define DEBUG_PPC_IO
@@ -648,7 +649,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
         hw_error("Only 6xx bus is supported on PREP machine\n");
     }
     i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
-    pci_bus = pci_prep_init(i8259);
+    pci_bus = pci_prep_init(i8259, get_system_memory());
     /* Hmm, prep has no pci-isa bridge ??? */
     isa_bus_new(NULL);
     isa_bus_irqs(i8259);
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index fc11af4..1344539 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -274,12 +274,15 @@ static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
                                  s->reg);
 }
 
+#include "exec-memory.h"
+
 static int e500_pcihost_initfn(SysBusDevice *dev)
 {
     PCIHostState *h;
     PPCE500PCIState *s;
     PCIBus *b;
     int i;
+    MemoryRegion *address_space = get_system_memory();
 
     h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
     s = DO_UPCAST(PPCE500PCIState, pci_state, h);
@@ -289,7 +292,8 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
     }
 
     b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
-                         mpc85xx_pci_map_irq, s->irq, PCI_DEVFN(0x11, 0), 4);
+                         mpc85xx_pci_map_irq, s->irq, address_space,
+                         PCI_DEVFN(0x11, 0), 4);
     s->pci_state.bus = b;
 
     pci_create_simple(b, 0, "e500-host-bridge");
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index f88b825..da02f0e 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -110,7 +110,7 @@ static void prep_set_irq(void *opaque, int irq_num, int level)
     qemu_set_irq(pic[(irq_num & 1) ? 11 : 9] , level);
 }
 
-PCIBus *pci_prep_init(qemu_irq *pic)
+PCIBus *pci_prep_init(qemu_irq *pic, MemoryRegion *address_space)
 {
     PREPPCIState *s;
     PCIDevice *d;
@@ -118,7 +118,8 @@ PCIBus *pci_prep_init(qemu_irq *pic)
 
     s = qemu_mallocz(sizeof(PREPPCIState));
     s->bus = pci_register_bus(NULL, "pci",
-                              prep_set_irq, prep_map_irq, pic, 0, 4);
+                              prep_set_irq, prep_map_irq, pic,
+                              address_space, 0, 4);
 
     pci_host_conf_register_ioport(0xcf8, s);
 
diff --git a/hw/prep_pci.h b/hw/prep_pci.h
index cd68512..a27368b 100644
--- a/hw/prep_pci.h
+++ b/hw/prep_pci.h
@@ -2,7 +2,8 @@
 #define QEMU_PREP_PCI_H
 
 #include "qemu-common.h"
+#include "memory.h"
 
-PCIBus *pci_prep_init(qemu_irq *pic);
+PCIBus *pci_prep_init(qemu_irq *pic, MemoryRegion *address_space);
 
 #endif
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index a076cf2..0ef93a0 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -26,6 +26,7 @@
 #include "pci.h"
 #include "pci_host.h"
 #include "bswap.h"
+#include "exec-memory.h"
 
 typedef struct SHPCIState {
     SysBusDevice busdev;
@@ -127,7 +128,8 @@ static int sh_pci_init_device(SysBusDevice *dev)
     }
     s->bus = pci_register_bus(&s->busdev.qdev, "pci",
                               sh_pci_set_irq, sh_pci_map_irq,
-                              s->irq, PCI_DEVFN(0, 0), 4);
+                              s->irq, get_system_memory(),
+                              PCI_DEVFN(0, 0), 4);
     s->memconfig = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w,
                                           s, DEVICE_NATIVE_ENDIAN);
     sysbus_init_mmio_cb(dev, 0x224, sh_pci_map);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index d364daa..b499523 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -201,7 +201,7 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
     return 0;
 }
 
-PCIBus *pci_pmac_init(qemu_irq *pic)
+PCIBus *pci_pmac_init(qemu_irq *pic, MemoryRegion *address_space)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -215,7 +215,8 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
     d = FROM_SYSBUS(UNINState, s);
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_unin_set_irq, pci_unin_map_irq,
-                                         pic, PCI_DEVFN(11, 0), 4);
+                                         pic, address_space,
+                                         PCI_DEVFN(11, 0), 4);
 
 #if 0
     pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
@@ -252,7 +253,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
     return d->host_state.bus;
 }
 
-PCIBus *pci_pmac_u3_init(qemu_irq *pic)
+PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space)
 {
     DeviceState *dev;
     SysBusDevice *s;
@@ -267,7 +268,8 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic)
 
     d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
                                          pci_unin_set_irq, pci_unin_map_irq,
-                                         pic, PCI_DEVFN(11, 0), 4);
+                                         pic, address_space,
+                                         PCI_DEVFN(11, 0), 4);
 
     sysbus_mmio_map(s, 0, 0xf0800000);
     sysbus_mmio_map(s, 1, 0xf0c00000);
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index 290a900..cffe387 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -10,6 +10,7 @@
 #include "sysbus.h"
 #include "pci.h"
 #include "pci_host.h"
+#include "exec-memory.h"
 
 typedef struct {
     SysBusDevice busdev;
@@ -111,6 +112,7 @@ static int pci_vpb_init(SysBusDevice *dev)
     }
     bus = pci_register_bus(&dev->qdev, "pci",
                            pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
+                           get_system_memory(),
                            PCI_DEVFN(11, 0), 4);
 
     /* ??? Register memory space.  */
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 21/23] pci: add MemoryRegion based BAR management API
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:03   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Allow registering a BAR using a MemoryRegion.  Once all users are converted,
pci_register_bar() and pci_register_bar_simple() will be removed.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/pci.c |   47 +++++++++++++++++++++++++++++++++++++++--------
 hw/pci.h |    3 +++
 2 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index cf16f3b..36db58b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -844,10 +844,15 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
         if (r->type == PCI_BASE_ADDRESS_SPACE_IO) {
             isa_unassign_ioport(r->addr, r->filtered_size);
         } else {
-            cpu_register_physical_memory(pci_to_cpu_addr(pci_dev->bus,
-                                                         r->addr),
-                                         r->filtered_size,
-                                         IO_MEM_UNASSIGNED);
+            if (r->memory) {
+                memory_region_del_subregion(pci_dev->bus->address_space,
+                                            r->memory);
+            } else {
+                cpu_register_physical_memory(pci_to_cpu_addr(pci_dev->bus,
+                                                             r->addr),
+                                             r->filtered_size,
+                                             IO_MEM_UNASSIGNED);
+            }
         }
     }
 }
@@ -893,6 +898,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     r->type = type;
     r->map_func = map_func;
     r->ram_addr = IO_MEM_UNASSIGNED;
+    r->memory = NULL;
 
     wmask = ~(size - 1);
     addr = pci_bar(pci_dev, region_num);
@@ -918,6 +924,16 @@ static void pci_simple_bar_mapfunc(PCIDevice *pci_dev, int region_num,
                                  pci_dev->io_regions[region_num].ram_addr);
 }
 
+static void pci_simple_bar_mapfunc_region(PCIDevice *pci_dev, int region_num,
+                                          pcibus_t addr, pcibus_t size,
+                                          int type)
+{
+    memory_region_add_subregion_overlap(pci_dev->bus->address_space,
+                                        addr,
+                                        pci_dev->io_regions[region_num].memory,
+                                        1);
+}
+
 void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
                              pcibus_t size,  uint8_t attr, ram_addr_t ram_addr)
 {
@@ -927,6 +943,15 @@ void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
     pci_dev->io_regions[region_num].ram_addr = ram_addr;
 }
 
+void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
+                             uint8_t attr, MemoryRegion *memory)
+{
+    pci_register_bar(pci_dev, region_num, memory_region_size(memory),
+                     PCI_BASE_ADDRESS_SPACE_MEMORY | attr,
+                     pci_simple_bar_mapfunc_region);
+    pci_dev->io_regions[region_num].memory = memory;
+}
+
 static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
                               uint8_t type)
 {
@@ -1065,10 +1090,16 @@ static void pci_update_mappings(PCIDevice *d)
                     isa_unassign_ioport(r->addr, r->filtered_size);
                 }
             } else {
-                cpu_register_physical_memory(pci_to_cpu_addr(d->bus, r->addr),
-                                             r->filtered_size,
-                                             IO_MEM_UNASSIGNED);
-                qemu_unregister_coalesced_mmio(r->addr, r->filtered_size);
+                if (r->memory) {
+                    memory_region_del_subregion(d->bus->address_space,
+                                                r->memory);
+                } else {
+                    cpu_register_physical_memory(pci_to_cpu_addr(d->bus,
+                                                                 r->addr),
+                                                 r->filtered_size,
+                                                 IO_MEM_UNASSIGNED);
+                    qemu_unregister_coalesced_mmio(r->addr, r->filtered_size);
+                }
             }
         }
         r->addr = new_addr;
diff --git a/hw/pci.h b/hw/pci.h
index cfeb042..c51156d 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -94,6 +94,7 @@ typedef struct PCIIORegion {
     uint8_t type;
     PCIMapIORegionFunc *map_func;
     ram_addr_t ram_addr;
+    MemoryRegion *memory;
 } PCIIORegion;
 
 #define PCI_ROM_SLOT 6
@@ -204,6 +205,8 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
                             PCIMapIORegionFunc *map_func);
 void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
                              pcibus_t size, uint8_t attr, ram_addr_t ram_addr);
+void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
+                             uint8_t attr, MemoryRegion *memory);
 
 int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
                        uint8_t offset, uint8_t size);
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 21/23] pci: add MemoryRegion based BAR management API
@ 2011-07-25 14:03   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Allow registering a BAR using a MemoryRegion.  Once all users are converted,
pci_register_bar() and pci_register_bar_simple() will be removed.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/pci.c |   47 +++++++++++++++++++++++++++++++++++++++--------
 hw/pci.h |    3 +++
 2 files changed, 42 insertions(+), 8 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index cf16f3b..36db58b 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -844,10 +844,15 @@ static void pci_unregister_io_regions(PCIDevice *pci_dev)
         if (r->type == PCI_BASE_ADDRESS_SPACE_IO) {
             isa_unassign_ioport(r->addr, r->filtered_size);
         } else {
-            cpu_register_physical_memory(pci_to_cpu_addr(pci_dev->bus,
-                                                         r->addr),
-                                         r->filtered_size,
-                                         IO_MEM_UNASSIGNED);
+            if (r->memory) {
+                memory_region_del_subregion(pci_dev->bus->address_space,
+                                            r->memory);
+            } else {
+                cpu_register_physical_memory(pci_to_cpu_addr(pci_dev->bus,
+                                                             r->addr),
+                                             r->filtered_size,
+                                             IO_MEM_UNASSIGNED);
+            }
         }
     }
 }
@@ -893,6 +898,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
     r->type = type;
     r->map_func = map_func;
     r->ram_addr = IO_MEM_UNASSIGNED;
+    r->memory = NULL;
 
     wmask = ~(size - 1);
     addr = pci_bar(pci_dev, region_num);
@@ -918,6 +924,16 @@ static void pci_simple_bar_mapfunc(PCIDevice *pci_dev, int region_num,
                                  pci_dev->io_regions[region_num].ram_addr);
 }
 
+static void pci_simple_bar_mapfunc_region(PCIDevice *pci_dev, int region_num,
+                                          pcibus_t addr, pcibus_t size,
+                                          int type)
+{
+    memory_region_add_subregion_overlap(pci_dev->bus->address_space,
+                                        addr,
+                                        pci_dev->io_regions[region_num].memory,
+                                        1);
+}
+
 void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
                              pcibus_t size,  uint8_t attr, ram_addr_t ram_addr)
 {
@@ -927,6 +943,15 @@ void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
     pci_dev->io_regions[region_num].ram_addr = ram_addr;
 }
 
+void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
+                             uint8_t attr, MemoryRegion *memory)
+{
+    pci_register_bar(pci_dev, region_num, memory_region_size(memory),
+                     PCI_BASE_ADDRESS_SPACE_MEMORY | attr,
+                     pci_simple_bar_mapfunc_region);
+    pci_dev->io_regions[region_num].memory = memory;
+}
+
 static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
                               uint8_t type)
 {
@@ -1065,10 +1090,16 @@ static void pci_update_mappings(PCIDevice *d)
                     isa_unassign_ioport(r->addr, r->filtered_size);
                 }
             } else {
-                cpu_register_physical_memory(pci_to_cpu_addr(d->bus, r->addr),
-                                             r->filtered_size,
-                                             IO_MEM_UNASSIGNED);
-                qemu_unregister_coalesced_mmio(r->addr, r->filtered_size);
+                if (r->memory) {
+                    memory_region_del_subregion(d->bus->address_space,
+                                                r->memory);
+                } else {
+                    cpu_register_physical_memory(pci_to_cpu_addr(d->bus,
+                                                                 r->addr),
+                                                 r->filtered_size,
+                                                 IO_MEM_UNASSIGNED);
+                    qemu_unregister_coalesced_mmio(r->addr, r->filtered_size);
+                }
             }
         }
         r->addr = new_addr;
diff --git a/hw/pci.h b/hw/pci.h
index cfeb042..c51156d 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -94,6 +94,7 @@ typedef struct PCIIORegion {
     uint8_t type;
     PCIMapIORegionFunc *map_func;
     ram_addr_t ram_addr;
+    MemoryRegion *memory;
 } PCIIORegion;
 
 #define PCI_ROM_SLOT 6
@@ -204,6 +205,8 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
                             PCIMapIORegionFunc *map_func);
 void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
                              pcibus_t size, uint8_t attr, ram_addr_t ram_addr);
+void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
+                             uint8_t attr, MemoryRegion *memory);
 
 int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
                        uint8_t offset, uint8_t size);
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 22/23] sysbus: add MemoryRegion based memory management API
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:03   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Allow registering sysbus device memory using a MemoryRegion.  Once all users
are converted, sysbus_init_mmio() and sysbus_init_mmio_cb() will be removed.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/sysbus.c |   27 ++++++++++++++++++++++++---
 hw/sysbus.h |    3 +++
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/hw/sysbus.c b/hw/sysbus.c
index 2e22be7..ea442ac 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -19,6 +19,7 @@
 
 #include "sysbus.h"
 #include "monitor.h"
+#include "exec-memory.h"
 
 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
 static char *sysbus_get_fw_dev_path(DeviceState *dev);
@@ -49,11 +50,20 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
     }
     if (dev->mmio[n].addr != (target_phys_addr_t)-1) {
         /* Unregister previous mapping.  */
-        cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
-                                     IO_MEM_UNASSIGNED);
+        if (dev->mmio[n].memory) {
+            memory_region_del_subregion(get_system_memory(),
+                                        dev->mmio[n].memory);
+        } else {
+            cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
+                                         IO_MEM_UNASSIGNED);
+        }
     }
     dev->mmio[n].addr = addr;
-    if (dev->mmio[n].cb) {
+    if (dev->mmio[n].memory) {
+        memory_region_add_subregion(get_system_memory(),
+                                    addr,
+                                    dev->mmio[n].memory);
+    } else if (dev->mmio[n].cb) {
         dev->mmio[n].cb(dev, addr);
     } else {
         cpu_register_physical_memory(addr, dev->mmio[n].size,
@@ -107,6 +117,17 @@ void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
     dev->mmio[n].cb = cb;
 }
 
+void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory)
+{
+    int n;
+
+    assert(dev->num_mmio < QDEV_MAX_MMIO);
+    n = dev->num_mmio++;
+    dev->mmio[n].addr = -1;
+    dev->mmio[n].size = memory_region_size(memory);
+    dev->mmio[n].memory = memory;
+}
+
 void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
 {
     pio_addr_t i;
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 4e8cb16..5f62e2d 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -4,6 +4,7 @@
 /* Devices attached directly to the main system bus.  */
 
 #include "qdev.h"
+#include "memory.h"
 
 #define QDEV_MAX_MMIO 32
 #define QDEV_MAX_PIO 32
@@ -23,6 +24,7 @@ struct SysBusDevice {
         target_phys_addr_t size;
         mmio_mapfunc cb;
         ram_addr_t iofunc;
+        MemoryRegion *memory;
     } mmio[QDEV_MAX_MMIO];
     int num_pio;
     pio_addr_t pio[QDEV_MAX_PIO];
@@ -46,6 +48,7 @@ void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size,
                       ram_addr_t iofunc);
 void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
                             mmio_mapfunc cb);
+void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory);
 void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
 void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target);
 void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 22/23] sysbus: add MemoryRegion based memory management API
@ 2011-07-25 14:03   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Allow registering sysbus device memory using a MemoryRegion.  Once all users
are converted, sysbus_init_mmio() and sysbus_init_mmio_cb() will be removed.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/sysbus.c |   27 ++++++++++++++++++++++++---
 hw/sysbus.h |    3 +++
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/hw/sysbus.c b/hw/sysbus.c
index 2e22be7..ea442ac 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -19,6 +19,7 @@
 
 #include "sysbus.h"
 #include "monitor.h"
+#include "exec-memory.h"
 
 static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
 static char *sysbus_get_fw_dev_path(DeviceState *dev);
@@ -49,11 +50,20 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
     }
     if (dev->mmio[n].addr != (target_phys_addr_t)-1) {
         /* Unregister previous mapping.  */
-        cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
-                                     IO_MEM_UNASSIGNED);
+        if (dev->mmio[n].memory) {
+            memory_region_del_subregion(get_system_memory(),
+                                        dev->mmio[n].memory);
+        } else {
+            cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
+                                         IO_MEM_UNASSIGNED);
+        }
     }
     dev->mmio[n].addr = addr;
-    if (dev->mmio[n].cb) {
+    if (dev->mmio[n].memory) {
+        memory_region_add_subregion(get_system_memory(),
+                                    addr,
+                                    dev->mmio[n].memory);
+    } else if (dev->mmio[n].cb) {
         dev->mmio[n].cb(dev, addr);
     } else {
         cpu_register_physical_memory(addr, dev->mmio[n].size,
@@ -107,6 +117,17 @@ void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
     dev->mmio[n].cb = cb;
 }
 
+void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory)
+{
+    int n;
+
+    assert(dev->num_mmio < QDEV_MAX_MMIO);
+    n = dev->num_mmio++;
+    dev->mmio[n].addr = -1;
+    dev->mmio[n].size = memory_region_size(memory);
+    dev->mmio[n].memory = memory;
+}
+
 void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
 {
     pio_addr_t i;
diff --git a/hw/sysbus.h b/hw/sysbus.h
index 4e8cb16..5f62e2d 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -4,6 +4,7 @@
 /* Devices attached directly to the main system bus.  */
 
 #include "qdev.h"
+#include "memory.h"
 
 #define QDEV_MAX_MMIO 32
 #define QDEV_MAX_PIO 32
@@ -23,6 +24,7 @@ struct SysBusDevice {
         target_phys_addr_t size;
         mmio_mapfunc cb;
         ram_addr_t iofunc;
+        MemoryRegion *memory;
     } mmio[QDEV_MAX_MMIO];
     int num_pio;
     pio_addr_t pio[QDEV_MAX_PIO];
@@ -46,6 +48,7 @@ void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size,
                       ram_addr_t iofunc);
 void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
                             mmio_mapfunc cb);
+void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory);
 void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
 void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target);
 void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [PATCH 23/23] usb-ohci: convert to MemoryRegion
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 14:03   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/usb-ohci.c |   42 +++++++++++++++++-------------------------
 1 files changed, 17 insertions(+), 25 deletions(-)

diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 8491d59..337b250 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -62,7 +62,7 @@ typedef struct OHCIPort {
 typedef struct {
     USBBus bus;
     qemu_irq irq;
-    int mem;
+    MemoryRegion mem;
     int num_ports;
     const char *name;
 
@@ -1440,13 +1440,13 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
     return;
 }
 
-static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
+static uint64_t ohci_mem_read(void *opaque,
+                              target_phys_addr_t addr,
+                              unsigned size)
 {
-    OHCIState *ohci = ptr;
+    OHCIState *ohci = opaque;
     uint32_t retval;
 
-    addr &= 0xff;
-
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
         fprintf(stderr, "usb-ohci: Mis-aligned read\n");
@@ -1563,11 +1563,12 @@ static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
     return retval;
 }
 
-static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
+static void ohci_mem_write(void *opaque,
+                           target_phys_addr_t addr,
+                           uint64_t val,
+                           unsigned size)
 {
-    OHCIState *ohci = ptr;
-
-    addr &= 0xff;
+    OHCIState *ohci = opaque;
 
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
@@ -1697,18 +1698,10 @@ static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
     }
 }
 
-/* Only dword reads are defined on OHCI register space */
-static CPUReadMemoryFunc * const ohci_readfn[3]={
-    ohci_mem_read,
-    ohci_mem_read,
-    ohci_mem_read
-};
-
-/* Only dword writes are defined on OHCI register space */
-static CPUWriteMemoryFunc * const ohci_writefn[3]={
-    ohci_mem_write,
-    ohci_mem_write,
-    ohci_mem_write
+static const MemoryRegionOps ohci_mem_ops = {
+    .read = ohci_mem_read,
+    .write = ohci_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static USBPortOps ohci_port_ops = {
@@ -1764,8 +1757,7 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
         }
     }
 
-    ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci,
-                                       DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256);
     ohci->localmem_base = localmem_base;
 
     ohci->name = dev->info->name;
@@ -1799,7 +1791,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
     ohci->state.irq = ohci->pci_dev.irq[0];
 
     /* TODO: avoid cast below by using dev */
-    pci_register_bar_simple(&ohci->pci_dev, 0, 256, 0, ohci->state.mem);
+    pci_register_bar_region(&ohci->pci_dev, 0, 0, &ohci->state.mem);
     return 0;
 }
 
@@ -1822,7 +1814,7 @@ static int ohci_init_pxa(SysBusDevice *dev)
     /* Cannot fail as we pass NULL for masterbus */
     usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0);
     sysbus_init_irq(dev, &s->ohci.irq);
-    sysbus_init_mmio(dev, 0x1000, s->ohci.mem);
+    sysbus_init_mmio_region(dev, &s->ohci.mem);
 
     return 0;
 }
-- 
1.7.5.3


^ permalink raw reply related	[flat|nested] 100+ messages in thread

* [Qemu-devel] [PATCH 23/23] usb-ohci: convert to MemoryRegion
@ 2011-07-25 14:03   ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 14:03 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/usb-ohci.c |   42 +++++++++++++++++-------------------------
 1 files changed, 17 insertions(+), 25 deletions(-)

diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 8491d59..337b250 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -62,7 +62,7 @@ typedef struct OHCIPort {
 typedef struct {
     USBBus bus;
     qemu_irq irq;
-    int mem;
+    MemoryRegion mem;
     int num_ports;
     const char *name;
 
@@ -1440,13 +1440,13 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
     return;
 }
 
-static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
+static uint64_t ohci_mem_read(void *opaque,
+                              target_phys_addr_t addr,
+                              unsigned size)
 {
-    OHCIState *ohci = ptr;
+    OHCIState *ohci = opaque;
     uint32_t retval;
 
-    addr &= 0xff;
-
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
         fprintf(stderr, "usb-ohci: Mis-aligned read\n");
@@ -1563,11 +1563,12 @@ static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
     return retval;
 }
 
-static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
+static void ohci_mem_write(void *opaque,
+                           target_phys_addr_t addr,
+                           uint64_t val,
+                           unsigned size)
 {
-    OHCIState *ohci = ptr;
-
-    addr &= 0xff;
+    OHCIState *ohci = opaque;
 
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
@@ -1697,18 +1698,10 @@ static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
     }
 }
 
-/* Only dword reads are defined on OHCI register space */
-static CPUReadMemoryFunc * const ohci_readfn[3]={
-    ohci_mem_read,
-    ohci_mem_read,
-    ohci_mem_read
-};
-
-/* Only dword writes are defined on OHCI register space */
-static CPUWriteMemoryFunc * const ohci_writefn[3]={
-    ohci_mem_write,
-    ohci_mem_write,
-    ohci_mem_write
+static const MemoryRegionOps ohci_mem_ops = {
+    .read = ohci_mem_read,
+    .write = ohci_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static USBPortOps ohci_port_ops = {
@@ -1764,8 +1757,7 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
         }
     }
 
-    ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci,
-                                       DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256);
     ohci->localmem_base = localmem_base;
 
     ohci->name = dev->info->name;
@@ -1799,7 +1791,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
     ohci->state.irq = ohci->pci_dev.irq[0];
 
     /* TODO: avoid cast below by using dev */
-    pci_register_bar_simple(&ohci->pci_dev, 0, 256, 0, ohci->state.mem);
+    pci_register_bar_region(&ohci->pci_dev, 0, 0, &ohci->state.mem);
     return 0;
 }
 
@@ -1822,7 +1814,7 @@ static int ohci_init_pxa(SysBusDevice *dev)
     /* Cannot fail as we pass NULL for masterbus */
     usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset, NULL, 0);
     sysbus_init_irq(dev, &s->ohci.irq);
-    sysbus_init_mmio(dev, 0x1000, s->ohci.mem);
+    sysbus_init_mmio_region(dev, &s->ohci.mem);
 
     return 0;
 }
-- 
1.7.5.3

^ permalink raw reply related	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 15:16   ` malc
  2011-07-25 15:17       ` [Qemu-devel] " Avi Kivity
  -1 siblings, 1 reply; 100+ messages in thread
From: malc @ 2011-07-25 15:16 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On Mon, 25 Jul 2011, Avi Kivity wrote:

> As with the rest of the memory API, the caller associates an eventfd
> with an address, and the memory API takes care of registering or
> unregistering when the address is made visible or invisible to the
> guest.
> 
> Signed-off-by: Avi Kivity <avi@redhat.com>
[..snip..]

> +static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
> +                                           MemoryRegionIoeventfd b)
> +{
> +    if (a.addr.start < b.addr.start) {
> +        return true;
> +    } else if (a.addr.start > b.addr.start) {
> +        return false;
> +    } else if (a.addr.size < b.addr.size) {
> +        return true;
> +    } else if (a.addr.size > b.addr.size) {
> +        return false;
> +    } else if (a.match_data < b.match_data) {
> +        return true;
> +    } else  if (a.match_data > b.match_data) {
> +        return false;
> +    } else if (a.match_data) {
> +        if (a.data < b.data) {
> +            return true;
> +        } else if (a.data > b.data) {
> +            return false;
> +        }
> +    }
> +    if (a.fd < b.fd) {
> +        return true;
> +    } else if (a.fd > b.fd) {
> +        return false;
> +    }

Braces..

> +    return false;
> +}
> +

[..snip..]

-- 
mailto:av1474@comtv.ru

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH 11/23] memory: add ioeventfd support
  2011-07-25 15:16   ` malc
@ 2011-07-25 15:17       ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 15:17 UTC (permalink / raw)
  To: malc; +Cc: qemu-devel, kvm

On 07/25/2011 06:16 PM, malc wrote:
> On Mon, 25 Jul 2011, Avi Kivity wrote:
>
> >  As with the rest of the memory API, the caller associates an eventfd
> >  with an address, and the memory API takes care of registering or
> >  unregistering when the address is made visible or invisible to the
> >  guest.
> >
> >  Signed-off-by: Avi Kivity<avi@redhat.com>
> [..snip..]
>
> >  +static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
> >  +                                           MemoryRegionIoeventfd b)
> >  +{
> >  +    if (a.addr.start<  b.addr.start) {
> >  +        return true;
> >  +    } else if (a.addr.start>  b.addr.start) {
> >  +        return false;
> >  +    } else if (a.addr.size<  b.addr.size) {
> >  +        return true;
> >  +    } else if (a.addr.size>  b.addr.size) {
> >  +        return false;
> >  +    } else if (a.match_data<  b.match_data) {
> >  +        return true;
> >  +    } else  if (a.match_data>  b.match_data) {
> >  +        return false;
> >  +    } else if (a.match_data) {
> >  +        if (a.data<  b.data) {
> >  +            return true;
> >  +        } else if (a.data>  b.data) {
> >  +            return false;
> >  +        }
> >  +    }
> >  +    if (a.fd<  b.fd) {
> >  +        return true;
> >  +    } else if (a.fd>  b.fd) {
> >  +        return false;
> >  +    }
>
> Braces..
>

Where? add? remove?

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support
@ 2011-07-25 15:17       ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 15:17 UTC (permalink / raw)
  To: malc; +Cc: qemu-devel, kvm

On 07/25/2011 06:16 PM, malc wrote:
> On Mon, 25 Jul 2011, Avi Kivity wrote:
>
> >  As with the rest of the memory API, the caller associates an eventfd
> >  with an address, and the memory API takes care of registering or
> >  unregistering when the address is made visible or invisible to the
> >  guest.
> >
> >  Signed-off-by: Avi Kivity<avi@redhat.com>
> [..snip..]
>
> >  +static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
> >  +                                           MemoryRegionIoeventfd b)
> >  +{
> >  +    if (a.addr.start<  b.addr.start) {
> >  +        return true;
> >  +    } else if (a.addr.start>  b.addr.start) {
> >  +        return false;
> >  +    } else if (a.addr.size<  b.addr.size) {
> >  +        return true;
> >  +    } else if (a.addr.size>  b.addr.size) {
> >  +        return false;
> >  +    } else if (a.match_data<  b.match_data) {
> >  +        return true;
> >  +    } else  if (a.match_data>  b.match_data) {
> >  +        return false;
> >  +    } else if (a.match_data) {
> >  +        if (a.data<  b.data) {
> >  +            return true;
> >  +        } else if (a.data>  b.data) {
> >  +            return false;
> >  +        }
> >  +    }
> >  +    if (a.fd<  b.fd) {
> >  +        return true;
> >  +    } else if (a.fd>  b.fd) {
> >  +        return false;
> >  +    }
>
> Braces..
>

Where? add? remove?

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH 11/23] memory: add ioeventfd support
  2011-07-25 15:17       ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 15:22         ` malc
  -1 siblings, 0 replies; 100+ messages in thread
From: malc @ 2011-07-25 15:22 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On Mon, 25 Jul 2011, Avi Kivity wrote:

> On 07/25/2011 06:16 PM, malc wrote:
> > On Mon, 25 Jul 2011, Avi Kivity wrote:
> > 
> > >  As with the rest of the memory API, the caller associates an eventfd
> > >  with an address, and the memory API takes care of registering or
> > >  unregistering when the address is made visible or invisible to the
> > >  guest.
> > >
> > >  Signed-off-by: Avi Kivity<avi@redhat.com>
> > [..snip..]
> > 
> > >  +static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
> > >  +                                           MemoryRegionIoeventfd b)
> > >  +{
> > >  +    if (a.addr.start<  b.addr.start) {
> > >  +        return true;
> > >  +    } else if (a.addr.start>  b.addr.start) {
> > >  +        return false;
> > >  +    } else if (a.addr.size<  b.addr.size) {
> > >  +        return true;
> > >  +    } else if (a.addr.size>  b.addr.size) {
> > >  +        return false;
> > >  +    } else if (a.match_data<  b.match_data) {
> > >  +        return true;
> > >  +    } else  if (a.match_data>  b.match_data) {
> > >  +        return false;
> > >  +    } else if (a.match_data) {
> > >  +        if (a.data<  b.data) {
> > >  +            return true;
> > >  +        } else if (a.data>  b.data) {
> > >  +            return false;
> > >  +        }
> > >  +    }
> > >  +    if (a.fd<  b.fd) {
> > >  +        return true;
> > >  +    } else {
               if (a.fd>  b.fd) {
   > > >  +        return false;
   > > >  +    }
            }
> > 
> > Braces..
> > 
> 
> Where? add? remove?
> 

You authored the coding_style document btw. 


-- 
mailto:av1474@comtv.ru

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support
@ 2011-07-25 15:22         ` malc
  0 siblings, 0 replies; 100+ messages in thread
From: malc @ 2011-07-25 15:22 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On Mon, 25 Jul 2011, Avi Kivity wrote:

> On 07/25/2011 06:16 PM, malc wrote:
> > On Mon, 25 Jul 2011, Avi Kivity wrote:
> > 
> > >  As with the rest of the memory API, the caller associates an eventfd
> > >  with an address, and the memory API takes care of registering or
> > >  unregistering when the address is made visible or invisible to the
> > >  guest.
> > >
> > >  Signed-off-by: Avi Kivity<avi@redhat.com>
> > [..snip..]
> > 
> > >  +static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
> > >  +                                           MemoryRegionIoeventfd b)
> > >  +{
> > >  +    if (a.addr.start<  b.addr.start) {
> > >  +        return true;
> > >  +    } else if (a.addr.start>  b.addr.start) {
> > >  +        return false;
> > >  +    } else if (a.addr.size<  b.addr.size) {
> > >  +        return true;
> > >  +    } else if (a.addr.size>  b.addr.size) {
> > >  +        return false;
> > >  +    } else if (a.match_data<  b.match_data) {
> > >  +        return true;
> > >  +    } else  if (a.match_data>  b.match_data) {
> > >  +        return false;
> > >  +    } else if (a.match_data) {
> > >  +        if (a.data<  b.data) {
> > >  +            return true;
> > >  +        } else if (a.data>  b.data) {
> > >  +            return false;
> > >  +        }
> > >  +    }
> > >  +    if (a.fd<  b.fd) {
> > >  +        return true;
> > >  +    } else {
               if (a.fd>  b.fd) {
   > > >  +        return false;
   > > >  +    }
            }
> > 
> > Braces..
> > 
> 
> Where? add? remove?
> 

You authored the coding_style document btw. 


-- 
mailto:av1474@comtv.ru

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support
  2011-07-25 15:22         ` [Qemu-devel] " malc
  (?)
@ 2011-07-25 15:28         ` Avi Kivity
  2011-07-25 15:38           ` malc
  -1 siblings, 1 reply; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 15:28 UTC (permalink / raw)
  To: malc; +Cc: qemu-devel, kvm

On 07/25/2011 06:22 PM, malc wrote:
> >  >  >   +    }
> >  >  >   +    if (a.fd<   b.fd) {
> >  >  >   +        return true;
> >  >  >   +    } else {
>                 if (a.fd>   b.fd) {
>     >  >  >   +        return false;
>     >  >  >   +    }
>              }

CODING_STYLE permits braceless else if.

> >  >
> >  >  Braces..
> >  >
> >
> >  Where? add? remove?
> >
>
> You authored the coding_style document btw.

It's CODING_STYLE.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support
  2011-07-25 15:28         ` Avi Kivity
@ 2011-07-25 15:38           ` malc
  2011-07-25 15:43             ` Avi Kivity
  0 siblings, 1 reply; 100+ messages in thread
From: malc @ 2011-07-25 15:38 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On Mon, 25 Jul 2011, Avi Kivity wrote:

> On 07/25/2011 06:22 PM, malc wrote:
> > >  >  >   +    }
> > >  >  >   +    if (a.fd<   b.fd) {
> > >  >  >   +        return true;
> > >  >  >   +    } else {
> >                 if (a.fd>   b.fd) {
> >     >  >  >   +        return false;
> >     >  >  >   +    }
> >              }
> 
> CODING_STYLE permits braceless else if.

The example uses it, the text however suggests it's illegal.

[..snip..]

-- 
mailto:av1474@comtv.ru

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support
  2011-07-25 15:38           ` malc
@ 2011-07-25 15:43             ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-25 15:43 UTC (permalink / raw)
  To: malc; +Cc: qemu-devel, kvm

On 07/25/2011 06:38 PM, malc wrote:
> On Mon, 25 Jul 2011, Avi Kivity wrote:
>
> >  On 07/25/2011 06:22 PM, malc wrote:
> >  >  >   >   >    +    }
> >  >  >   >   >    +    if (a.fd<    b.fd) {
> >  >  >   >   >    +        return true;
> >  >  >   >   >    +    } else {
> >  >                  if (a.fd>    b.fd) {
> >  >      >   >   >    +        return false;
> >  >      >   >   >    +    }
> >  >               }
> >
> >  CODING_STYLE permits braceless else if.
>
> The example uses it, the text however suggests it's illegal.

I'll post a patch.  It's perfectly reasonable IMO, and there ~1800 
instances in the tree.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 01/23] Hierarchical memory region API
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 18:41   ` Anthony Liguori
  2011-07-26  9:35     ` Avi Kivity
  -1 siblings, 1 reply; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 18:41 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> The memory API separates the attributes of a memory region (its size, how
> reads or writes are handled, dirty logging, and coalescing) from where it
> is mapped and whether it is enabled.  This allows a device to configure
> a memory region once, then hand it off to its parent bus to map it according
> to the bus configuration.
>
> Hierarchical registration also allows a device to compose a region out of
> a number of sub-regions with different properties; for example some may be
> RAM while others may be MMIO.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>
> ---
>   Makefile.target |    1 +
>   memory.c        |  655 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   memory.h        |  200 +++++++++++++++++
>   3 files changed, 856 insertions(+), 0 deletions(-)
>   create mode 100644 memory.c
>   create mode 100644 memory.h
>
> diff --git a/Makefile.target b/Makefile.target
> index cde509b..8884a56 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -198,6 +198,7 @@ obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
>   obj-y += rwhandler.o
>   obj-$(CONFIG_KVM) += kvm.o kvm-all.o
>   obj-$(CONFIG_NO_KVM) += kvm-stub.o
> +obj-y += memory.o
>   LIBS+=-lz
>
>   QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
> diff --git a/memory.c b/memory.c
> new file mode 100644
> index 0000000..10591bf
> --- /dev/null
> +++ b/memory.c
> @@ -0,0 +1,655 @@
> +/*
> + * Physical memory management
> + *
> + * Copyright 2011 Red Hat, Inc. and/or its affiliates
> + *
> + * Authors:
> + *  Avi Kivity<avi@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2.  See
> + * the COPYING file in the top-level directory.
> + *
> + */
> +
> +#include "memory.h"
> +#include<assert.h>
> +
> +typedef struct AddrRange AddrRange;
> +
> +struct AddrRange {
> +    uint64_t start;
> +    uint64_t size;
> +};
> +
> +static AddrRange addrrange_make(uint64_t start, uint64_t size)
> +{
> +    return (AddrRange) { start, size };
> +}
> +
> +static bool addrrange_equal(AddrRange r1, AddrRange r2)
> +{
> +    return r1.start == r2.start&&  r1.size == r2.size;
> +}
> +
> +static uint64_t addrrange_end(AddrRange r)
> +{
> +    return r.start + r.size;
> +}
> +
> +static AddrRange addrrange_shift(AddrRange range, int64_t delta)
> +{
> +    range.start += delta;
> +    return range;
> +}
> +
> +static bool addrrange_intersects(AddrRange r1, AddrRange r2)
> +{
> +    return (r1.start>= r2.start&&  r1.start<  r2.start + r2.size)
> +        || (r2.start>= r1.start&&  r2.start<  r1.start + r1.size);
> +}
> +
> +static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
> +{
> +    uint64_t start = MAX(r1.start, r2.start);
> +    /* off-by-one arithmetic to prevent overflow */
> +    uint64_t end = MIN(addrrange_end(r1) - 1, addrrange_end(r2) - 1);
> +    return addrrange_make(start, end - start + 1);
> +}
> +
> +struct CoalescedMemoryRange {
> +    AddrRange addr;
> +    QTAILQ_ENTRY(CoalescedMemoryRange) link;
> +};
> +
> +typedef struct FlatRange FlatRange;
> +typedef struct FlatView FlatView;
> +
> +/* Range of memory in the global map.  Addresses are absolute. */
> +struct FlatRange {
> +    MemoryRegion *mr;
> +    target_phys_addr_t offset_in_region;
> +    AddrRange addr;
> +};
> +
> +/* Flattened global view of current active memory hierarchy.  Kept in sorted
> + * order.
> + */
> +struct FlatView {
> +    FlatRange *ranges;
> +    unsigned nr;
> +    unsigned nr_allocated;
> +};
> +
> +#define FOR_EACH_FLAT_RANGE(var, view)          \
> +    for (var = (view)->ranges; var<  (view)->ranges + (view)->nr; ++var)
> +
> +static FlatView current_memory_map;
> +static MemoryRegion *root_memory_region;
> +
> +static bool flatrange_equal(FlatRange *a, FlatRange *b)
> +{
> +    return a->mr == b->mr
> +&&  addrrange_equal(a->addr, b->addr)
> +&&  a->offset_in_region == b->offset_in_region;
> +}
> +
> +static void flatview_init(FlatView *view)
> +{
> +    view->ranges = NULL;
> +    view->nr = 0;
> +    view->nr_allocated = 0;
> +}
> +
> +/* Insert a range into a given position.  Caller is responsible for maintaining
> + * sorting order.
> + */
> +static void flatview_insert(FlatView *view, unsigned pos, FlatRange *range)
> +{
> +    if (view->nr == view->nr_allocated) {
> +        view->nr_allocated = MAX(2 * view->nr, 10);
> +        view->ranges = qemu_realloc(view->ranges,
> +                                    view->nr_allocated * sizeof(*view->ranges));
> +    }
> +    memmove(view->ranges + pos + 1, view->ranges + pos,
> +            (view->nr - pos) * sizeof(FlatRange));
> +    view->ranges[pos] = *range;
> +    ++view->nr;
> +}
> +
> +static void flatview_destroy(FlatView *view)
> +{
> +    qemu_free(view->ranges);
> +}
> +
> +/* Render a memory region into the global view.  Ranges in @view obscure
> + * ranges in @mr.
> + */
> +static void render_memory_region(FlatView *view,
> +                                 MemoryRegion *mr,
> +                                 target_phys_addr_t base,
> +                                 AddrRange clip)
> +{
> +    MemoryRegion *subregion;
> +    unsigned i;
> +    target_phys_addr_t offset_in_region;
> +    uint64_t remain;
> +    uint64_t now;
> +    FlatRange fr;
> +    AddrRange tmp;
> +
> +    base += mr->addr;
> +
> +    tmp = addrrange_make(base, mr->size);
> +
> +    if (!addrrange_intersects(tmp, clip)) {
> +        return;
> +    }
> +
> +    clip = addrrange_intersection(tmp, clip);
> +
> +    if (mr->alias) {
> +        base -= mr->alias->addr;
> +        base -= mr->alias_offset;
> +        render_memory_region(view, mr->alias, base, clip);
> +        return;
> +    }
> +
> +    /* Render subregions in priority order. */
> +    QTAILQ_FOREACH(subregion,&mr->subregions, subregions_link) {
> +        render_memory_region(view, subregion, base, clip);
> +    }
> +
> +    if (!mr->has_ram_addr) {
> +        return;
> +    }
> +
> +    offset_in_region = clip.start - base;
> +    base = clip.start;
> +    remain = clip.size;
> +
> +    /* Render the region itself into any gaps left by the current view. */
> +    for (i = 0; i<  view->nr&&  remain; ++i) {
> +        if (base>= addrrange_end(view->ranges[i].addr)) {
> +            continue;
> +        }
> +        if (base<  view->ranges[i].addr.start) {
> +            now = MIN(remain, view->ranges[i].addr.start - base);
> +            fr.mr = mr;
> +            fr.offset_in_region = offset_in_region;
> +            fr.addr = addrrange_make(base, now);
> +            flatview_insert(view, i,&fr);
> +            ++i;
> +            base += now;
> +            offset_in_region += now;
> +            remain -= now;
> +        }
> +        if (base == view->ranges[i].addr.start) {
> +            now = MIN(remain, view->ranges[i].addr.size);
> +            base += now;
> +            offset_in_region += now;
> +            remain -= now;
> +        }
> +    }
> +    if (remain) {
> +        fr.mr = mr;
> +        fr.offset_in_region = offset_in_region;
> +        fr.addr = addrrange_make(base, remain);
> +        flatview_insert(view, i,&fr);
> +    }
> +}
> +
> +/* Render a memory topology into a list of disjoint absolute ranges. */
> +static FlatView generate_memory_topology(MemoryRegion *mr)
> +{
> +    FlatView view;
> +
> +    flatview_init(&view);
> +
> +    render_memory_region(&view, mr, 0, addrrange_make(0, UINT64_MAX));
> +
> +    return view;
> +}
> +
> +static void memory_region_update_topology(void)
> +{
> +    FlatView old_view = current_memory_map;
> +    FlatView new_view = generate_memory_topology(root_memory_region);
> +    unsigned iold, inew;
> +    FlatRange *frold, *frnew;
> +    ram_addr_t phys_offset, region_offset;
> +
> +    /* Generate a symmetric difference of the old and new memory maps.
> +     * Kill ranges in the old map, and instantiate ranges in the new map.
> +     */
> +    iold = inew = 0;
> +    while (iold<  old_view.nr || inew<  new_view.nr) {
> +        if (iold<  old_view.nr) {
> +            frold =&old_view.ranges[iold];
> +        } else {
> +            frold = NULL;
> +        }
> +        if (inew<  new_view.nr) {
> +            frnew =&new_view.ranges[inew];
> +        } else {
> +            frnew = NULL;
> +        }
> +
> +        if (frold
> +&&  (!frnew
> +                || frold->addr.start<  frnew->addr.start
> +                || (frold->addr.start == frnew->addr.start
> +&&  !flatrange_equal(frold, frnew)))) {
> +            /* In old, but (not in new, or in new but attributes changed). */
> +
> +            cpu_register_physical_memory(frold->addr.start, frold->addr.size,
> +                                         IO_MEM_UNASSIGNED);
> +            ++iold;
> +        } else if (frold&&  frnew&&  flatrange_equal(frold, frnew)) {
> +            /* In both (logging may have changed) */
> +
> +            ++iold;
> +            ++inew;
> +            /* FIXME: dirty logging */
> +        } else {
> +            /* In new */
> +
> +            phys_offset = frnew->mr->ram_addr;
> +            region_offset = frnew->offset_in_region;
> +            /* cpu_register_physical_memory_log() wants region_offset for
> +             * mmio, but prefers offseting phys_offset for RAM.  Humour it.
> +             */
> +            if ((phys_offset&  ~TARGET_PAGE_MASK)<= IO_MEM_ROM) {
> +                phys_offset += region_offset;
> +                region_offset = 0;
> +            }
> +
> +            cpu_register_physical_memory_log(frnew->addr.start,
> +                                             frnew->addr.size,
> +                                             phys_offset,
> +                                             region_offset,
> +                                             0);
> +            ++inew;
> +        }
> +    }
> +    current_memory_map = new_view;
> +    flatview_destroy(&old_view);
> +}
> +
> +void memory_region_init(MemoryRegion *mr,
> +                        const char *name,
> +                        uint64_t size)
> +{
> +    mr->ops = NULL;
> +    mr->parent = NULL;
> +    mr->size = size;
> +    mr->addr = 0;
> +    mr->offset = 0;
> +    mr->has_ram_addr = false;
> +    mr->priority = 0;
> +    mr->may_overlap = false;
> +    mr->alias = NULL;
> +    QTAILQ_INIT(&mr->subregions);
> +    memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
> +    QTAILQ_INIT(&mr->coalesced);
> +    mr->name = qemu_strdup(name);
> +}
> +
> +static bool memory_region_access_valid(MemoryRegion *mr,
> +                                       target_phys_addr_t addr,
> +                                       unsigned size)
> +{
> +    if (!mr->ops->valid.unaligned&&  (addr&  (size - 1))) {
> +        return false;
> +    }
> +
> +    /* Treat zero as compatibility all valid */
> +    if (!mr->ops->valid.max_access_size) {
> +        return true;
> +    }
> +
> +    if (size>  mr->ops->valid.max_access_size
> +        || size<  mr->ops->valid.min_access_size) {
> +        return false;
> +    }
> +    return true;
> +}
> +
> +static uint32_t memory_region_read_thunk_n(void *_mr,
> +                                           target_phys_addr_t addr,
> +                                           unsigned size)
> +{
> +    MemoryRegion *mr = _mr;
> +    unsigned access_size, access_size_min, access_size_max;
> +    uint64_t access_mask;
> +    uint32_t data = 0, tmp;
> +    unsigned i;
> +
> +    if (!memory_region_access_valid(mr, addr, size)) {
> +        return -1U; /* FIXME: better signalling */
> +    }
> +
> +    /* FIXME: support unaligned access */
> +
> +    access_size_min = mr->ops->impl.min_access_size;
> +    if (!access_size_min) {
> +        access_size_min = 1;
> +    }
> +    access_size_max = mr->ops->impl.max_access_size;
> +    if (!access_size_max) {
> +        access_size_max = 4;
> +    }
> +    access_size = MAX(MIN(size, access_size_max), access_size_min);
> +    access_mask = -1ULL>>  (64 - access_size * 8);
> +    addr += mr->offset;
> +    for (i = 0; i<  size; i += access_size) {
> +        /* FIXME: big-endian support */
> +        tmp = mr->ops->read(mr->opaque, addr + i, access_size);
> +        data |= (tmp&  access_mask)<<  (i * 8);
> +    }
> +
> +    return data;
> +}
> +
> +static void memory_region_write_thunk_n(void *_mr,
> +                                        target_phys_addr_t addr,
> +                                        unsigned size,
> +                                        uint64_t data)
> +{
> +    MemoryRegion *mr = _mr;
> +    unsigned access_size, access_size_min, access_size_max;
> +    uint64_t access_mask;
> +    unsigned i;
> +
> +    if (!memory_region_access_valid(mr, addr, size)) {
> +        return; /* FIXME: better signalling */
> +    }
> +
> +    /* FIXME: support unaligned access */
> +
> +    access_size_min = mr->ops->impl.min_access_size;
> +    if (!access_size_min) {
> +        access_size_min = 1;
> +    }
> +    access_size_max = mr->ops->impl.max_access_size;
> +    if (!access_size_max) {
> +        access_size_max = 4;
> +    }
> +    access_size = MAX(MIN(size, access_size_max), access_size_min);
> +    access_mask = -1ULL>>  (64 - access_size * 8);
> +    addr += mr->offset;
> +    for (i = 0; i<  size; i += access_size) {
> +        /* FIXME: big-endian support */
> +        mr->ops->write(mr->opaque, addr + i, (data>>  (i * 8))&  access_mask,
> +                       access_size);
> +    }
> +}
> +
> +static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr)
> +{
> +    return memory_region_read_thunk_n(mr, addr, 1);
> +}
> +
> +static uint32_t memory_region_read_thunk_w(void *mr, target_phys_addr_t addr)
> +{
> +    return memory_region_read_thunk_n(mr, addr, 2);
> +}
> +
> +static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr)
> +{
> +    return memory_region_read_thunk_n(mr, addr, 4);
> +}
> +
> +static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
> +                                        uint32_t data)
> +{
> +    memory_region_write_thunk_n(mr, addr, 1, data);
> +}
> +
> +static void memory_region_write_thunk_w(void *mr, target_phys_addr_t addr,
> +                                        uint32_t data)
> +{
> +    memory_region_write_thunk_n(mr, addr, 2, data);
> +}
> +
> +static void memory_region_write_thunk_l(void *mr, target_phys_addr_t addr,
> +                                        uint32_t data)
> +{
> +    memory_region_write_thunk_n(mr, addr, 4, data);
> +}
> +
> +static CPUReadMemoryFunc * const memory_region_read_thunk[] = {
> +    memory_region_read_thunk_b,
> +    memory_region_read_thunk_w,
> +    memory_region_read_thunk_l,
> +};
> +
> +static CPUWriteMemoryFunc * const memory_region_write_thunk[] = {
> +    memory_region_write_thunk_b,
> +    memory_region_write_thunk_w,
> +    memory_region_write_thunk_l,
> +};
> +
> +void memory_region_init_io(MemoryRegion *mr,
> +                           const MemoryRegionOps *ops,
> +                           void *opaque,
> +                           const char *name,
> +                           uint64_t size)
> +{
> +    memory_region_init(mr, name, size);
> +    mr->ops = ops;
> +    mr->opaque = opaque;
> +    mr->has_ram_addr = true;
> +    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
> +                                          memory_region_write_thunk,
> +                                          mr,
> +                                          mr->ops->endianness);
> +}
> +
> +void memory_region_init_ram(MemoryRegion *mr,
> +                            DeviceState *dev,
> +                            const char *name,
> +                            uint64_t size)
> +{
> +    memory_region_init(mr, name, size);
> +    mr->has_ram_addr = true;
> +    mr->ram_addr = qemu_ram_alloc(dev, name, size);
> +}
> +
> +void memory_region_init_ram_ptr(MemoryRegion *mr,
> +                                DeviceState *dev,
> +                                const char *name,
> +                                uint64_t size,
> +                                void *ptr)
> +{
> +    memory_region_init(mr, name, size);
> +    mr->has_ram_addr = true;
> +    mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
> +}
> +
> +void memory_region_init_alias(MemoryRegion *mr,
> +                              const char *name,
> +                              MemoryRegion *orig,
> +                              target_phys_addr_t offset,
> +                              uint64_t size)
> +{
> +    memory_region_init(mr, name, size);
> +    mr->alias = orig;
> +    mr->alias_offset = offset;
> +}
> +
> +void memory_region_destroy(MemoryRegion *mr)
> +{
> +    assert(QTAILQ_EMPTY(&mr->subregions));
> +    memory_region_clear_coalescing(mr);
> +    qemu_free((char *)mr->name);
> +}
> +
> +target_phys_addr_t memory_region_size(MemoryRegion *mr)
> +{
> +    return mr->size;
> +}
> +
> +void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
> +{
> +    mr->offset = offset;
> +}
> +
> +void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
> +{
> +    /* FIXME */
> +}
> +
> +bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
> +                             unsigned client)
> +{
> +    /* FIXME */
> +    return true;
> +}
> +
> +void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
> +{
> +    /* FIXME */
> +}
> +
> +void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
> +{
> +    /* FIXME */
> +}
> +
> +void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
> +{
> +    /* FIXME */
> +}
> +
> +void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
> +                               target_phys_addr_t size, unsigned client)
> +{
> +    /* FIXME */
> +}
> +
> +void *memory_region_get_ram_ptr(MemoryRegion *mr)
> +{
> +    if (mr->alias) {
> +        return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
> +    }
> +
> +    if (!mr->has_ram_addr) {
> +        abort();
> +    }
> +
> +    return qemu_get_ram_ptr(mr->ram_addr);
> +}
> +
> +static void memory_region_update_coalesced_range(MemoryRegion *mr)
> +{
> +    FlatRange *fr;
> +    CoalescedMemoryRange *cmr;
> +    AddrRange tmp;
> +
> +    FOR_EACH_FLAT_RANGE(fr,&current_memory_map) {
> +        if (fr->mr == mr) {
> +            qemu_unregister_coalesced_mmio(fr->addr.start, fr->addr.size);
> +            QTAILQ_FOREACH(cmr,&mr->coalesced, link) {
> +                tmp = addrrange_shift(cmr->addr,
> +                                      fr->addr.start - fr->offset_in_region);
> +                if (!addrrange_intersects(tmp, fr->addr)) {
> +                    continue;
> +                }
> +                tmp = addrrange_intersection(tmp, fr->addr);
> +                qemu_register_coalesced_mmio(tmp.start, tmp.size);
> +            }
> +        }
> +    }
> +}
> +
> +void memory_region_set_coalescing(MemoryRegion *mr)
> +{
> +    memory_region_clear_coalescing(mr);
> +    memory_region_add_coalescing(mr, 0, mr->size);
> +}
> +
> +void memory_region_add_coalescing(MemoryRegion *mr,
> +                                  target_phys_addr_t offset,
> +                                  uint64_t size)
> +{
> +    CoalescedMemoryRange *cmr = qemu_malloc(sizeof(*cmr));
> +
> +    cmr->addr = addrrange_make(offset, size);
> +    QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
> +    memory_region_update_coalesced_range(mr);
> +}
> +
> +void memory_region_clear_coalescing(MemoryRegion *mr)
> +{
> +    CoalescedMemoryRange *cmr;
> +
> +    while (!QTAILQ_EMPTY(&mr->coalesced)) {
> +        cmr = QTAILQ_FIRST(&mr->coalesced);
> +        QTAILQ_REMOVE(&mr->coalesced, cmr, link);
> +        qemu_free(cmr);
> +    }
> +    memory_region_update_coalesced_range(mr);
> +}
> +
> +static void memory_region_add_subregion_common(MemoryRegion *mr,
> +                                               target_phys_addr_t offset,
> +                                               MemoryRegion *subregion)
> +{
> +    MemoryRegion *other;
> +
> +    assert(!subregion->parent);
> +    subregion->parent = mr;
> +    subregion->addr = offset;
> +    QTAILQ_FOREACH(other,&mr->subregions, subregions_link) {
> +        if (subregion->may_overlap || other->may_overlap) {
> +            continue;
> +        }
> +        if (offset>= other->offset + other->size
> +            || offset + subregion->size<= other->offset) {
> +            continue;
> +        }
> +        printf("warning: subregion collision %llx/%llx vs %llx/%llx\n",
> +               (unsigned long long)offset,
> +               (unsigned long long)subregion->size,
> +               (unsigned long long)other->offset,
> +               (unsigned long long)other->size);
> +    }
> +    QTAILQ_FOREACH(other,&mr->subregions, subregions_link) {
> +        if (subregion->priority>= other->priority) {
> +            QTAILQ_INSERT_BEFORE(other, subregion, subregions_link);
> +            goto done;
> +        }
> +    }
> +    QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
> +done:
> +    memory_region_update_topology();
> +}
> +
> +
> +void memory_region_add_subregion(MemoryRegion *mr,
> +                                 target_phys_addr_t offset,
> +                                 MemoryRegion *subregion)
> +{
> +    subregion->may_overlap = false;
> +    subregion->priority = 0;
> +    memory_region_add_subregion_common(mr, offset, subregion);
> +}
> +
> +void memory_region_add_subregion_overlap(MemoryRegion *mr,
> +                                         target_phys_addr_t offset,
> +                                         MemoryRegion *subregion,
> +                                         unsigned priority)
> +{
> +    subregion->may_overlap = true;
> +    subregion->priority = priority;
> +    memory_region_add_subregion_common(mr, offset, subregion);
> +}
> +
> +void memory_region_del_subregion(MemoryRegion *mr,
> +                                 MemoryRegion *subregion)
> +{
> +    assert(subregion->parent == mr);
> +    subregion->parent = NULL;
> +    QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
> +    memory_region_update_topology();
> +}
> diff --git a/memory.h b/memory.h
> new file mode 100644
> index 0000000..95270aa
> --- /dev/null
> +++ b/memory.h
> @@ -0,0 +1,200 @@
> +#ifndef MEMORY_H
> +#define MEMORY_H
> +
> +#ifndef CONFIG_USER_ONLY
> +
> +#include<stdint.h>
> +#include<stdbool.h>
> +#include "qemu-common.h"
> +#include "cpu-common.h"
> +#include "targphys.h"
> +#include "qemu-queue.h"
> +
> +typedef struct MemoryRegionOps MemoryRegionOps;
> +typedef struct MemoryRegion MemoryRegion;
> +
> +/* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
> + * registration.
> + */
> +#define DIRTY_MEMORY_VGA       0
> +#define DIRTY_MEMORY_CODE      1
> +#define DIRTY_MEMORY_MIGRATION 3
> +
> +/*
> + * Memory region callbacks
> + */
> +struct MemoryRegionOps {
> +    /* Read from the memory region. @addr is relative to @mr; @size is
> +     * in bytes. */
> +    uint64_t (*read)(void *opaque,
> +                     target_phys_addr_t addr,
> +                     unsigned size);
> +    /* Write to the memory region. @addr is relative to @mr; @size is
> +     * in bytes. */
> +    void (*write)(void *opaque,
> +                  target_phys_addr_t addr,
> +                  uint64_t data,
> +                  unsigned size);
> +
> +    enum device_endian endianness;
> +    /* Guest-visible constraints: */
> +    struct {
> +        /* If nonzero, specify bounds on access sizes beyond which a machine
> +         * check is thrown.
> +         */
> +        unsigned min_access_size;
> +        unsigned max_access_size;
> +        /* If true, unaligned accesses are supported.  Otherwise unaligned
> +         * accesses throw machine checks.
> +         */
> +         bool unaligned;
> +    } valid;
> +    /* Internal implementation constraints: */
> +    struct {
> +        /* If nonzero, specifies the minimum size implemented.  Smaller sizes
> +         * will be rounded upwards and a partial result will be returned.
> +         */
> +        unsigned min_access_size;
> +        /* If nonzero, specifies the maximum size implemented.  Larger sizes
> +         * will be done as a series of accesses with smaller sizes.
> +         */
> +        unsigned max_access_size;
> +        /* If true, unaligned accesses are supported.  Otherwise all accesses
> +         * are converted to (possibly multiple) naturally aligned accesses.
> +         */
> +         bool unaligned;
> +    } impl;
> +};
> +
> +typedef struct CoalescedMemoryRange CoalescedMemoryRange;
> +
> +struct MemoryRegion {
> +    /* All fields are private - violators will be prosecuted */
> +    const MemoryRegionOps *ops;
> +    void *opaque;
> +    MemoryRegion *parent;
> +    uint64_t size;
> +    target_phys_addr_t addr;
> +    target_phys_addr_t offset;
> +    ram_addr_t ram_addr;
> +    bool has_ram_addr;
> +    MemoryRegion *alias;
> +    target_phys_addr_t alias_offset;
> +    unsigned priority;
> +    bool may_overlap;
> +    QTAILQ_HEAD(subregions, MemoryRegion) subregions;
> +    QTAILQ_ENTRY(MemoryRegion) subregions_link;
> +    QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
> +    const char *name;
> +};
> +
> +/* Initialize a memory region
> + *
> + * The region typically acts as a container for other memory regions.
> + */

I'm also writing a fair bit of documentation right now.  We should use a 
common format and declare that the doc format in CODING_STYLE.

I think the two choices are gtk-doc (which I have been using):

/**
  * @memory_region_init: Initialize a memory region.
  *
  * The region typically acts as a container for other memory regions.
  *
  * @mr: an uninitialized memory region
  * @name: the name of the memory region (must be unique)
  * @size: the size of the memory region in bytes
  */

Or Doxygen, which in this case would look like:

/**
  * Initialize a memory region.
  *
  * The region typically acts as a container for other memory regions.
  *
  * @param mr an uninitialized memory region
  * @param name the name of the memory region (must be unique)
  * @param size the size of the memory region in bytes
  */

I think gtk-doc is more concise and easier to write.  But Doxygen 
clearly has better tooling.

Otherwise, Reviewed-by: Anthony Liguori <aliguori@us.ibm.com> but not 
tested yet.

I assume that all of the FIXMEs don't actually introduce regressions, right?

Regards,

Anthony Liguori


> +void memory_region_init(MemoryRegion *mr,
> +                        const char *name,
> +                        uint64_t size);
> +/* Initialize an I/O memory region.  Accesses into the region will be
> + * cause the callbacks in @ops to be called.
> + *
> + * if @size is nonzero, subregions will be clipped to @size.
> + */
> +void memory_region_init_io(MemoryRegion *mr,
> +                           const MemoryRegionOps *ops,
> +                           void *opaque,
> +                           const char *name,
> +                           uint64_t size);
> +/* Initialize an I/O memory region.  Accesses into the region will be
> + * modify memory directly.
> + */
> +void memory_region_init_ram(MemoryRegion *mr,
> +                            DeviceState *dev, /* FIXME: layering violation */
> +                            const char *name,
> +                            uint64_t size);
> +/* Initialize a RAM memory region.  Accesses into the region will be
> + * modify memory in @ptr directly.
> + */
> +void memory_region_init_ram_ptr(MemoryRegion *mr,
> +                                DeviceState *dev, /* FIXME: layering violation */
> +                                const char *name,
> +                                uint64_t size,
> +                                void *ptr);
> +/* Initializes a memory region which aliases a section of another memory
> + * region.
> + */
> +void memory_region_init_alias(MemoryRegion *mr,
> +                              const char *name,
> +                              MemoryRegion *orig,
> +                              target_phys_addr_t offset,
> +                              uint64_t size);
> +
> +/* Destroy a memory region.  The memory becomes inaccessible. */
> +void memory_region_destroy(MemoryRegion *mr);
> +
> +target_phys_addr_t memory_region_size(MemoryRegion *mr);
> +
> +/* Get a pointer into a RAM memory region; use with care */
> +void *memory_region_get_ram_ptr(MemoryRegion *mr);
> +
> +/* Sets an offset to be added to MemoryRegionOps callbacks.  This function
> + * is deprecated and should not be used in new code. */
> +void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset);
> +
> +/* Turn logging on or off for specified client (display, migration) */
> +void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client);
> +
> +/* Check whether a page is dirty for a specified client. */
> +bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
> +                             unsigned client);
> +
> +/* Mark a page as dirty in a memory region, after it has been dirtied outside
> + * guest code
> + */
> +void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr);
> +
> +/* Synchronize a region's dirty bitmap with any external TLBs (e.g. kvm) */
> +void memory_region_sync_dirty_bitmap(MemoryRegion *mr);
> +
> +/* Mark a range of pages as not dirty, for a specified client. */
> +void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
> +                               target_phys_addr_t size, unsigned client);
> +
> +/* Turn a memory region read-only (or read-write) */
> +void memory_region_set_readonly(MemoryRegion *mr, bool readonly);
> +
> +/* Enable memory coalescing for the region.  MMIO ->write callbacks may be
> + * delayed until a non-coalesced MMIO is issued.
> + */
> +void memory_region_set_coalescing(MemoryRegion *mr);
> +
> +/* Enable memory coalescing for a sub-range of the region.  MMIO ->write
> + * callbacks may be delayed until a non-coalesced MMIO is issued.
> + */
> +void memory_region_add_coalescing(MemoryRegion *mr,
> +                                  target_phys_addr_t offset,
> +                                  uint64_t size);
> +/* Disable MMIO coalescing for the region. */
> +void memory_region_clear_coalescing(MemoryRegion *mr);
> +
> +/* Add a sub-region at @offset.  The sub-region may not overlap with other
> + * subregions (except for those explicitly marked as overlapping)
> + */
> +void memory_region_add_subregion(MemoryRegion *mr,
> +                                 target_phys_addr_t offset,
> +                                 MemoryRegion *subregion);
> +/* Add a sub-region at @offset.  The sub-region may overlap other subregions;
> + * conflicts are resolved by having a higher @priority hide a lower @priority.
> + * Subregions without priority are taken as @priority 0.
> + */
> +void memory_region_add_subregion_overlap(MemoryRegion *mr,
> +                                         target_phys_addr_t offset,
> +                                         MemoryRegion *subregion,
> +                                         unsigned priority);
> +/* Remove a subregion. */
> +void memory_region_del_subregion(MemoryRegion *mr,
> +                                 MemoryRegion *subregion);
> +
> +#endif
> +
> +#endif


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH 02/23] memory: implement dirty tracking
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 18:43     ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 18:43 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> Currently dirty tracking is implemented by passing through
> all calls to the underlying cpu_physical_memory_*() calls.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

Ah, I see, you're fixing FIXMEs in updated patches before anything uses it.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   memory.c |   39 +++++++++++++++++++++++++++++++--------
>   memory.h |    1 +
>   2 files changed, 32 insertions(+), 8 deletions(-)
>
> diff --git a/memory.c b/memory.c
> index 10591bf..a569666 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -69,6 +69,7 @@ struct FlatRange {
>       MemoryRegion *mr;
>       target_phys_addr_t offset_in_region;
>       AddrRange addr;
> +    uint8_t dirty_log_mask;
>   };
>
>   /* Flattened global view of current active memory hierarchy.  Kept in sorted
> @@ -177,6 +178,7 @@ static void render_memory_region(FlatView *view,
>               fr.mr = mr;
>               fr.offset_in_region = offset_in_region;
>               fr.addr = addrrange_make(base, now);
> +            fr.dirty_log_mask = mr->dirty_log_mask;
>               flatview_insert(view, i,&fr);
>               ++i;
>               base += now;
> @@ -194,6 +196,7 @@ static void render_memory_region(FlatView *view,
>           fr.mr = mr;
>           fr.offset_in_region = offset_in_region;
>           fr.addr = addrrange_make(base, remain);
> +        fr.dirty_log_mask = mr->dirty_log_mask;
>           flatview_insert(view, i,&fr);
>       }
>   }
> @@ -247,9 +250,14 @@ static void memory_region_update_topology(void)
>           } else if (frold&&  frnew&&  flatrange_equal(frold, frnew)) {
>               /* In both (logging may have changed) */
>
> +            if (frold->dirty_log_mask&&  !frnew->dirty_log_mask) {
> +                cpu_physical_log_stop(frnew->addr.start, frnew->addr.size);
> +            } else if (frnew->dirty_log_mask&&  !frold->dirty_log_mask) {
> +                cpu_physical_log_start(frnew->addr.start, frnew->addr.size);
> +            }
> +
>               ++iold;
>               ++inew;
> -            /* FIXME: dirty logging */
>           } else {
>               /* In new */
>
> @@ -267,7 +275,7 @@ static void memory_region_update_topology(void)
>                                                frnew->addr.size,
>                                                phys_offset,
>                                                region_offset,
> -                                             0);
> +                                             frnew->dirty_log_mask);
>               ++inew;
>           }
>       }
> @@ -292,6 +300,7 @@ void memory_region_init(MemoryRegion *mr,
>       memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
>       QTAILQ_INIT(&mr->coalesced);
>       mr->name = qemu_strdup(name);
> +    mr->dirty_log_mask = 0;
>   }
>
>   static bool memory_region_access_valid(MemoryRegion *mr,
> @@ -496,24 +505,35 @@ void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
>
>   void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
>   {
> -    /* FIXME */
> +    uint8_t mask = 1<<  client;
> +
> +    mr->dirty_log_mask = (mr->dirty_log_mask&  ~mask) | (log * mask);
> +    memory_region_update_topology();
>   }
>
>   bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>                                unsigned client)
>   {
> -    /* FIXME */
> -    return true;
> +    assert(mr->has_ram_addr);
> +    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1<<  client);
>   }
>
>   void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
>   {
> -    /* FIXME */
> +    assert(mr->has_ram_addr);
> +    return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
>   }
>
>   void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
>   {
> -    /* FIXME */
> +    FlatRange *fr;
> +
> +    FOR_EACH_FLAT_RANGE(fr,&current_memory_map) {
> +        if (fr->mr == mr) {
> +            cpu_physical_sync_dirty_bitmap(fr->addr.start,
> +                                           fr->addr.start + fr->addr.size);
> +        }
> +    }
>   }
>
>   void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
> @@ -524,7 +544,10 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
>   void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>                                  target_phys_addr_t size, unsigned client)
>   {
> -    /* FIXME */
> +    assert(mr->has_ram_addr);
> +    cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
> +                                    mr->ram_addr + addr + size,
> +                                    1<<  client);
>   }
>
>   void *memory_region_get_ram_ptr(MemoryRegion *mr)
> diff --git a/memory.h b/memory.h
> index 95270aa..8873f75 100644
> --- a/memory.h
> +++ b/memory.h
> @@ -86,6 +86,7 @@ struct MemoryRegion {
>       QTAILQ_ENTRY(MemoryRegion) subregions_link;
>       QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
>       const char *name;
> +    uint8_t dirty_log_mask;
>   };
>
>   /* Initialize a memory region

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 02/23] memory: implement dirty tracking
@ 2011-07-25 18:43     ` Anthony Liguori
  0 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 18:43 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> Currently dirty tracking is implemented by passing through
> all calls to the underlying cpu_physical_memory_*() calls.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

Ah, I see, you're fixing FIXMEs in updated patches before anything uses it.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   memory.c |   39 +++++++++++++++++++++++++++++++--------
>   memory.h |    1 +
>   2 files changed, 32 insertions(+), 8 deletions(-)
>
> diff --git a/memory.c b/memory.c
> index 10591bf..a569666 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -69,6 +69,7 @@ struct FlatRange {
>       MemoryRegion *mr;
>       target_phys_addr_t offset_in_region;
>       AddrRange addr;
> +    uint8_t dirty_log_mask;
>   };
>
>   /* Flattened global view of current active memory hierarchy.  Kept in sorted
> @@ -177,6 +178,7 @@ static void render_memory_region(FlatView *view,
>               fr.mr = mr;
>               fr.offset_in_region = offset_in_region;
>               fr.addr = addrrange_make(base, now);
> +            fr.dirty_log_mask = mr->dirty_log_mask;
>               flatview_insert(view, i,&fr);
>               ++i;
>               base += now;
> @@ -194,6 +196,7 @@ static void render_memory_region(FlatView *view,
>           fr.mr = mr;
>           fr.offset_in_region = offset_in_region;
>           fr.addr = addrrange_make(base, remain);
> +        fr.dirty_log_mask = mr->dirty_log_mask;
>           flatview_insert(view, i,&fr);
>       }
>   }
> @@ -247,9 +250,14 @@ static void memory_region_update_topology(void)
>           } else if (frold&&  frnew&&  flatrange_equal(frold, frnew)) {
>               /* In both (logging may have changed) */
>
> +            if (frold->dirty_log_mask&&  !frnew->dirty_log_mask) {
> +                cpu_physical_log_stop(frnew->addr.start, frnew->addr.size);
> +            } else if (frnew->dirty_log_mask&&  !frold->dirty_log_mask) {
> +                cpu_physical_log_start(frnew->addr.start, frnew->addr.size);
> +            }
> +
>               ++iold;
>               ++inew;
> -            /* FIXME: dirty logging */
>           } else {
>               /* In new */
>
> @@ -267,7 +275,7 @@ static void memory_region_update_topology(void)
>                                                frnew->addr.size,
>                                                phys_offset,
>                                                region_offset,
> -                                             0);
> +                                             frnew->dirty_log_mask);
>               ++inew;
>           }
>       }
> @@ -292,6 +300,7 @@ void memory_region_init(MemoryRegion *mr,
>       memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
>       QTAILQ_INIT(&mr->coalesced);
>       mr->name = qemu_strdup(name);
> +    mr->dirty_log_mask = 0;
>   }
>
>   static bool memory_region_access_valid(MemoryRegion *mr,
> @@ -496,24 +505,35 @@ void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
>
>   void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
>   {
> -    /* FIXME */
> +    uint8_t mask = 1<<  client;
> +
> +    mr->dirty_log_mask = (mr->dirty_log_mask&  ~mask) | (log * mask);
> +    memory_region_update_topology();
>   }
>
>   bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>                                unsigned client)
>   {
> -    /* FIXME */
> -    return true;
> +    assert(mr->has_ram_addr);
> +    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1<<  client);
>   }
>
>   void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
>   {
> -    /* FIXME */
> +    assert(mr->has_ram_addr);
> +    return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
>   }
>
>   void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
>   {
> -    /* FIXME */
> +    FlatRange *fr;
> +
> +    FOR_EACH_FLAT_RANGE(fr,&current_memory_map) {
> +        if (fr->mr == mr) {
> +            cpu_physical_sync_dirty_bitmap(fr->addr.start,
> +                                           fr->addr.start + fr->addr.size);
> +        }
> +    }
>   }
>
>   void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
> @@ -524,7 +544,10 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
>   void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>                                  target_phys_addr_t size, unsigned client)
>   {
> -    /* FIXME */
> +    assert(mr->has_ram_addr);
> +    cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
> +                                    mr->ram_addr + addr + size,
> +                                    1<<  client);
>   }
>
>   void *memory_region_get_ram_ptr(MemoryRegion *mr)
> diff --git a/memory.h b/memory.h
> index 95270aa..8873f75 100644
> --- a/memory.h
> +++ b/memory.h
> @@ -86,6 +86,7 @@ struct MemoryRegion {
>       QTAILQ_ENTRY(MemoryRegion) subregions_link;
>       QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
>       const char *name;
> +    uint8_t dirty_log_mask;
>   };
>
>   /* Initialize a memory region

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 03/23] memory: merge adjacent segments of a single memory region
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 18:48   ` Anthony Liguori
  2011-07-26  9:55     ` Avi Kivity
  -1 siblings, 1 reply; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 18:48 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> Simple implementations of memory routers, for example the Cirrus VGA memory banks
> or the 440FX PAM registers can generate adjacent memory regions which are contiguous.
> Detect these and merge them; this saves kvm memory slots and shortens lookup times.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>
> ---
>   memory.c |   22 ++++++++++++++++++++++
>   1 files changed, 22 insertions(+), 0 deletions(-)
>
> diff --git a/memory.c b/memory.c
> index a569666..339bea3 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -122,6 +122,27 @@ static void flatview_destroy(FlatView *view)
>       qemu_free(view->ranges);
>   }
>
> +/* Attempt to simplify a view by merging ajacent ranges */
> +static void flatview_simplify(FlatView *view)
> +{
> +    unsigned i;
> +    FlatRange *r1, *r2;
> +
> +    for (i = 0; i + 1<  view->nr; ++i) {
> +        r1 =&view->ranges[i];
> +        r2 =&view->ranges[i+1];
> +        if (addrrange_end(r1->addr) == r2->addr.start
> +&&  r1->mr == r2->mr
> +&&  r1->offset_in_region + r1->addr.size == r2->offset_in_region
> +&&  r1->dirty_log_mask == r2->dirty_log_mask) {
> +            r1->addr.size += r2->addr.size;
> +            memmove(r2, r2 + 1, (view->nr - (i + 2)) * sizeof(*r2));
> +            --view->nr;
> +            --i;
> +        }

The --i is pretty subtle.  Moving the index variable backwards in a 
conditional in a for loop is pretty evil :-)  I started writing up why 
this was wrong until I noticed that.

I think the following would be more straight forward:

i = 0;
while (i + 1 < view->nr) {
    int begin = i, end = i + 1;

    while (matches(&view->ranges[begin], &view->ranges[end])) {
       end++;
    }

    memmove(...)
}

Regards,

Anthony Liguori

> +    }
> +}
> +
>   /* Render a memory region into the global view.  Ranges in @view obscure
>    * ranges in @mr.
>    */
> @@ -209,6 +230,7 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
>       flatview_init(&view);
>
>       render_memory_region(&view, mr, 0, addrrange_make(0, UINT64_MAX));
> +    flatview_simplify(&view);
>
>       return view;
>   }


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 04/23] Internal interfaces for memory API
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 18:49   ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 18:49 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> get_system_memory() provides the root of the memory hierarchy.
>
> This interface is intended to be private between memory.c and exec.c.
> If this file is included elsewhere, it should be regarded as a bug (or
> TODO item).  However, it will be temporarily needed for the conversion
> to hierarchical memory routing.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>
> ---
>   exec-memory.h |   23 +++++++++++++++++++++++
>   memory.c      |    7 +++++++
>   2 files changed, 30 insertions(+), 0 deletions(-)
>   create mode 100644 exec-memory.h
>
> diff --git a/exec-memory.h b/exec-memory.h
> new file mode 100644
> index 0000000..7eb9085
> --- /dev/null
> +++ b/exec-memory.h
> @@ -0,0 +1,23 @@

Please add a copyright/license.  Otherwise,

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> +#ifndef EXEC_MEMORY_H
> +#define EXEC_MEMORY_H
> +
> +/*
> + * Internal interfaces between memory.c/exec.c/vl.c.  Do not #include unless
> + * you're one of them.
> + */
> +
> +#include "memory.h"
> +
> +#ifndef CONFIG_USER_ONLY
> +
> +/* Get the root memory region.  This interface should only be used temporarily
> + * until a proper bus interface is available.
> + */
> +MemoryRegion *get_system_memory(void);
> +
> +/* Set the root memory region.  This region is the system memory map. */
> +void set_system_memory_map(MemoryRegion *mr);
> +
> +#endif
> +
> +#endif
> diff --git a/memory.c b/memory.c
> index 339bea3..48470d2 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -12,6 +12,7 @@
>    */
>
>   #include "memory.h"
> +#include "exec-memory.h"
>   #include<assert.h>
>
>   typedef struct AddrRange AddrRange;
> @@ -698,3 +699,9 @@ void memory_region_del_subregion(MemoryRegion *mr,
>       QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
>       memory_region_update_topology();
>   }
> +
> +void set_system_memory_map(MemoryRegion *mr)
> +{
> +    root_memory_region = mr;
> +    memory_region_update_topology();
> +}


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 05/23] memory: abstract address space operations
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 18:51   ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 18:51 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> Prepare for multiple address space support by abstracting away the details
> of registering a memory range with qemu's flat representation into an
> AddressSpace object.
>
> Note operations which are memory specific are not abstracted, since they will
> never be called on I/O address spaces anyway.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   memory.c |  111 +++++++++++++++++++++++++++++++++++++++++++++-----------------
>   1 files changed, 81 insertions(+), 30 deletions(-)
>
> diff --git a/memory.c b/memory.c
> index 48470d2..7187223 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -82,12 +82,26 @@ struct FlatView {
>       unsigned nr_allocated;
>   };
>
> +typedef struct AddressSpace AddressSpace;
> +typedef struct AddressSpaceOps AddressSpaceOps;
> +
> +/* A system address space - I/O, memory, etc. */
> +struct AddressSpace {
> +    const AddressSpaceOps *ops;
> +    MemoryRegion *root;
> +    FlatView current_map;
> +};
> +
> +struct AddressSpaceOps {
> +    void (*range_add)(AddressSpace *as, FlatRange *fr);
> +    void (*range_del)(AddressSpace *as, FlatRange *fr);
> +    void (*log_start)(AddressSpace *as, FlatRange *fr);
> +    void (*log_stop)(AddressSpace *as, FlatRange *fr);
> +};
> +
>   #define FOR_EACH_FLAT_RANGE(var, view)          \
>       for (var = (view)->ranges; var<  (view)->ranges + (view)->nr; ++var)
>
> -static FlatView current_memory_map;
> -static MemoryRegion *root_memory_region;
> -
>   static bool flatrange_equal(FlatRange *a, FlatRange *b)
>   {
>       return a->mr == b->mr
> @@ -144,6 +158,54 @@ static void flatview_simplify(FlatView *view)
>       }
>   }
>
> +static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
> +{
> +    ram_addr_t phys_offset, region_offset;
> +
> +    phys_offset = fr->mr->ram_addr;
> +    region_offset = fr->offset_in_region;
> +    /* cpu_register_physical_memory_log() wants region_offset for
> +     * mmio, but prefers offseting phys_offset for RAM.  Humour it.
> +     */
> +    if ((phys_offset&  ~TARGET_PAGE_MASK)<= IO_MEM_ROM) {
> +        phys_offset += region_offset;
> +        region_offset = 0;
> +    }
> +
> +    cpu_register_physical_memory_log(fr->addr.start,
> +                                     fr->addr.size,
> +                                     phys_offset,
> +                                     region_offset,
> +                                     fr->dirty_log_mask);
> +}
> +
> +static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
> +{
> +    cpu_register_physical_memory(fr->addr.start, fr->addr.size,
> +                                 IO_MEM_UNASSIGNED);
> +}
> +
> +static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
> +{
> +    cpu_physical_log_start(fr->addr.start, fr->addr.size);
> +}
> +
> +static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
> +{
> +    cpu_physical_log_stop(fr->addr.start, fr->addr.size);
> +}
> +
> +static const AddressSpaceOps address_space_ops_memory = {
> +    .range_add = as_memory_range_add,
> +    .range_del = as_memory_range_del,
> +    .log_start = as_memory_log_start,
> +    .log_stop = as_memory_log_stop,
> +};
> +
> +static AddressSpace address_space_memory = {
> +    .ops =&address_space_ops_memory,
> +};
> +
>   /* Render a memory region into the global view.  Ranges in @view obscure
>    * ranges in @mr.
>    */
> @@ -236,13 +298,12 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
>       return view;
>   }
>
> -static void memory_region_update_topology(void)
> +static void address_space_update_topology(AddressSpace *as)
>   {
> -    FlatView old_view = current_memory_map;
> -    FlatView new_view = generate_memory_topology(root_memory_region);
> +    FlatView old_view = as->current_map;
> +    FlatView new_view = generate_memory_topology(as->root);
>       unsigned iold, inew;
>       FlatRange *frold, *frnew;
> -    ram_addr_t phys_offset, region_offset;
>
>       /* Generate a symmetric difference of the old and new memory maps.
>        * Kill ranges in the old map, and instantiate ranges in the new map.
> @@ -267,16 +328,15 @@ static void memory_region_update_topology(void)
>                       &&  !flatrange_equal(frold, frnew)))) {
>               /* In old, but (not in new, or in new but attributes changed). */
>
> -            cpu_register_physical_memory(frold->addr.start, frold->addr.size,
> -                                         IO_MEM_UNASSIGNED);
> +            as->ops->range_del(as, frold);
>               ++iold;
>           } else if (frold&&  frnew&&  flatrange_equal(frold, frnew)) {
>               /* In both (logging may have changed) */
>
>               if (frold->dirty_log_mask&&  !frnew->dirty_log_mask) {
> -                cpu_physical_log_stop(frnew->addr.start, frnew->addr.size);
> +                as->ops->log_stop(as, frnew);
>               } else if (frnew->dirty_log_mask&&  !frold->dirty_log_mask) {
> -                cpu_physical_log_start(frnew->addr.start, frnew->addr.size);
> +                as->ops->log_start(as, frnew);
>               }
>
>               ++iold;
> @@ -284,28 +344,19 @@ static void memory_region_update_topology(void)
>           } else {
>               /* In new */
>
> -            phys_offset = frnew->mr->ram_addr;
> -            region_offset = frnew->offset_in_region;
> -            /* cpu_register_physical_memory_log() wants region_offset for
> -             * mmio, but prefers offseting phys_offset for RAM.  Humour it.
> -             */
> -            if ((phys_offset&  ~TARGET_PAGE_MASK)<= IO_MEM_ROM) {
> -                phys_offset += region_offset;
> -                region_offset = 0;
> -            }
> -
> -            cpu_register_physical_memory_log(frnew->addr.start,
> -                                             frnew->addr.size,
> -                                             phys_offset,
> -                                             region_offset,
> -                                             frnew->dirty_log_mask);
> +            as->ops->range_add(as, frnew);
>               ++inew;
>           }
>       }
> -    current_memory_map = new_view;
> +    as->current_map = new_view;
>       flatview_destroy(&old_view);
>   }
>
> +static void memory_region_update_topology(void)
> +{
> +    address_space_update_topology(&address_space_memory);
> +}
> +
>   void memory_region_init(MemoryRegion *mr,
>                           const char *name,
>                           uint64_t size)
> @@ -551,7 +602,7 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
>   {
>       FlatRange *fr;
>
> -    FOR_EACH_FLAT_RANGE(fr,&current_memory_map) {
> +    FOR_EACH_FLAT_RANGE(fr,&address_space_memory.current_map) {
>           if (fr->mr == mr) {
>               cpu_physical_sync_dirty_bitmap(fr->addr.start,
>                                              fr->addr.start + fr->addr.size);
> @@ -592,7 +643,7 @@ static void memory_region_update_coalesced_range(MemoryRegion *mr)
>       CoalescedMemoryRange *cmr;
>       AddrRange tmp;
>
> -    FOR_EACH_FLAT_RANGE(fr,&current_memory_map) {
> +    FOR_EACH_FLAT_RANGE(fr,&address_space_memory.current_map) {
>           if (fr->mr == mr) {
>               qemu_unregister_coalesced_mmio(fr->addr.start, fr->addr.size);
>               QTAILQ_FOREACH(cmr,&mr->coalesced, link) {
> @@ -702,6 +753,6 @@ void memory_region_del_subregion(MemoryRegion *mr,
>
>   void set_system_memory_map(MemoryRegion *mr)
>   {
> -    root_memory_region = mr;
> +    address_space_memory.root = mr;
>       memory_region_update_topology();
>   }


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 06/23] memory: rename MemoryRegion::has_ram_addr to ::terminates
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 18:56   ` Anthony Liguori
  2011-07-26  9:59     ` Avi Kivity
  -1 siblings, 1 reply; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 18:56 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> I/O regions will not have ram_addrs, so this is a better name.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Although it seems squashable.

Regards,

Anthony Liguori

> ---
>   memory.c |   18 +++++++++---------
>   memory.h |    2 +-
>   2 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/memory.c b/memory.c
> index 7187223..5fda4a0 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -244,7 +244,7 @@ static void render_memory_region(FlatView *view,
>           render_memory_region(view, subregion, base, clip);
>       }
>
> -    if (!mr->has_ram_addr) {
> +    if (!mr->terminates) {
>           return;
>       }
>
> @@ -366,7 +366,7 @@ void memory_region_init(MemoryRegion *mr,
>       mr->size = size;
>       mr->addr = 0;
>       mr->offset = 0;
> -    mr->has_ram_addr = false;
> +    mr->terminates = false;
>       mr->priority = 0;
>       mr->may_overlap = false;
>       mr->alias = NULL;
> @@ -521,7 +521,7 @@ void memory_region_init_io(MemoryRegion *mr,
>       memory_region_init(mr, name, size);
>       mr->ops = ops;
>       mr->opaque = opaque;
> -    mr->has_ram_addr = true;
> +    mr->terminates = true;
>       mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
>                                             memory_region_write_thunk,
>                                             mr,
> @@ -534,7 +534,7 @@ void memory_region_init_ram(MemoryRegion *mr,
>                               uint64_t size)
>   {
>       memory_region_init(mr, name, size);
> -    mr->has_ram_addr = true;
> +    mr->terminates = true;
>       mr->ram_addr = qemu_ram_alloc(dev, name, size);
>   }
>
> @@ -545,7 +545,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
>                                   void *ptr)
>   {
>       memory_region_init(mr, name, size);
> -    mr->has_ram_addr = true;
> +    mr->terminates = true;
>       mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
>   }
>
> @@ -588,13 +588,13 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
>   bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>                                unsigned client)
>   {
> -    assert(mr->has_ram_addr);
> +    assert(mr->terminates);
>       return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1<<  client);
>   }
>
>   void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
>   {
> -    assert(mr->has_ram_addr);
> +    assert(mr->terminates);
>       return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
>   }
>
> @@ -618,7 +618,7 @@ void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
>   void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
>                                  target_phys_addr_t size, unsigned client)
>   {
> -    assert(mr->has_ram_addr);
> +    assert(mr->terminates);
>       cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
>                                       mr->ram_addr + addr + size,
>                                       1<<  client);
> @@ -630,7 +630,7 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr)
>           return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
>       }
>
> -    if (!mr->has_ram_addr) {
> +    if (!mr->terminates) {
>           abort();
>       }
>
> diff --git a/memory.h b/memory.h
> index 8873f75..2ad7202 100644
> --- a/memory.h
> +++ b/memory.h
> @@ -77,7 +77,7 @@ struct MemoryRegion {
>       target_phys_addr_t addr;
>       target_phys_addr_t offset;
>       ram_addr_t ram_addr;
> -    bool has_ram_addr;
> +    bool terminates;
>       MemoryRegion *alias;
>       target_phys_addr_t alias_offset;
>       unsigned priority;


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 08/23] memory:  I/O address space support
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 19:00   ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 19:00 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> Allow registering I/O ports via the same mechanism as mmio ranges.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   exec-memory.h |    3 ++
>   memory.c      |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>   memory.h      |    2 +
>   3 files changed, 64 insertions(+), 1 deletions(-)
>
> diff --git a/exec-memory.h b/exec-memory.h
> index 7eb9085..aad21b5 100644
> --- a/exec-memory.h
> +++ b/exec-memory.h
> @@ -18,6 +18,9 @@ MemoryRegion *get_system_memory(void);
>   /* Set the root memory region.  This region is the system memory map. */
>   void set_system_memory_map(MemoryRegion *mr);
>
> +/* Set the I/O memory region.  This region is the I/O memory map. */
> +void set_system_io_map(MemoryRegion *mr);
> +
>   #endif
>
>   #endif
> diff --git a/memory.c b/memory.c
> index bc8bfa2..62bd60b 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -13,6 +13,7 @@
>
>   #include "memory.h"
>   #include "exec-memory.h"
> +#include "ioport.h"
>   #include<assert.h>
>
>   typedef struct AddrRange AddrRange;
> @@ -210,6 +211,52 @@ static AddressSpace address_space_memory = {
>       .ops =&address_space_ops_memory,
>   };
>
> +static void memory_region_iorange_read(IORange *iorange,
> +                                       uint64_t offset,
> +                                       unsigned width,
> +                                       uint64_t *data)
> +{
> +    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
> +
> +    *data = mr->ops->read(mr->opaque, offset, width);
> +}
> +
> +static void memory_region_iorange_write(IORange *iorange,
> +                                        uint64_t offset,
> +                                        unsigned width,
> +                                        uint64_t data)
> +{
> +    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
> +
> +    mr->ops->write(mr->opaque, offset, data, width);
> +}
> +
> +static const IORangeOps memory_region_iorange_ops = {
> +    .read = memory_region_iorange_read,
> +    .write = memory_region_iorange_write,
> +};
> +
> +static void as_io_range_add(AddressSpace *as, FlatRange *fr)
> +{
> +    iorange_init(&fr->mr->iorange,&memory_region_iorange_ops,
> +                 fr->addr.start,fr->addr.size);
> +    ioport_register(&fr->mr->iorange);
> +}
> +
> +static void as_io_range_del(AddressSpace *as, FlatRange *fr)
> +{
> +    isa_unassign_ioport(fr->addr.start, fr->addr.size);
> +}
> +
> +static const AddressSpaceOps address_space_ops_io = {
> +    .range_add = as_io_range_add,
> +    .range_del = as_io_range_del,
> +};
> +
> +static AddressSpace address_space_io = {
> +    .ops =&address_space_ops_io,
> +};
> +
>   /* Render a memory region into the global view.  Ranges in @view obscure
>    * ranges in @mr.
>    */
> @@ -358,7 +405,12 @@ static void address_space_update_topology(AddressSpace *as)
>
>   static void memory_region_update_topology(void)
>   {
> -    address_space_update_topology(&address_space_memory);
> +    if (address_space_memory.root) {
> +        address_space_update_topology(&address_space_memory);
> +    }
> +    if (address_space_io.root) {
> +        address_space_update_topology(&address_space_io);
> +    }
>   }
>
>   void memory_region_init(MemoryRegion *mr,
> @@ -772,3 +824,9 @@ void set_system_memory_map(MemoryRegion *mr)
>       address_space_memory.root = mr;
>       memory_region_update_topology();
>   }
> +
> +void set_system_io_map(MemoryRegion *mr)
> +{
> +    address_space_io.root = mr;
> +    memory_region_update_topology();
> +}
> diff --git a/memory.h b/memory.h
> index 0994b18..2afbf13 100644
> --- a/memory.h
> +++ b/memory.h
> @@ -9,6 +9,7 @@
>   #include "cpu-common.h"
>   #include "targphys.h"
>   #include "qemu-queue.h"
> +#include "iorange.h"
>
>   typedef struct MemoryRegionOps MemoryRegionOps;
>   typedef struct MemoryRegion MemoryRegion;
> @@ -78,6 +79,7 @@ struct MemoryRegion {
>       target_phys_addr_t offset;
>       bool backend_registered;
>       ram_addr_t ram_addr;
> +    IORange iorange;
>       bool terminates;
>       MemoryRegion *alias;
>       target_phys_addr_t alias_offset;


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 09/23] memory: add backward compatibility for old portio registration
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 19:01   ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 19:01 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> Signed-off-by: Avi Kivity<avi@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   memory.c |   32 ++++++++++++++++++++++++++++++++
>   memory.h |   17 +++++++++++++++++
>   2 files changed, 49 insertions(+), 0 deletions(-)
>
> diff --git a/memory.c b/memory.c
> index 62bd60b..bb04952 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -211,6 +211,21 @@ static AddressSpace address_space_memory = {
>       .ops =&address_space_ops_memory,
>   };
>
> +static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset,
> +                                             unsigned width, bool write)
> +{
> +    const MemoryRegionPortio *mrp;
> +
> +    for (mrp = mr->ops->old_portio; mrp->size; ++mrp) {
> +        if (offset>= mrp->offset&&  offset<  mrp->offset + mrp->len
> +&&  width == mrp->size
> +&&  (write ? (bool)mrp->write : (bool)mrp->read)) {
> +            return mrp;
> +        }
> +    }
> +    return NULL;
> +}
> +
>   static void memory_region_iorange_read(IORange *iorange,
>                                          uint64_t offset,
>                                          unsigned width,
> @@ -218,6 +233,15 @@ static void memory_region_iorange_read(IORange *iorange,
>   {
>       MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
>
> +    if (mr->ops->old_portio) {
> +        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, false);
> +
> +        *data = ((uint64_t)1<<  (width * 8)) - 1;
> +        if (mrp) {
> +            *data = mrp->read(mr->opaque, offset - mrp->offset);
> +        }
> +        return;
> +    }
>       *data = mr->ops->read(mr->opaque, offset, width);
>   }
>
> @@ -228,6 +252,14 @@ static void memory_region_iorange_write(IORange *iorange,
>   {
>       MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
>
> +    if (mr->ops->old_portio) {
> +        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true);
> +
> +        if (mrp) {
> +            mrp->write(mr->opaque, offset - mrp->offset, data);
> +        }
> +        return;
> +    }
>       mr->ops->write(mr->opaque, offset, data, width);
>   }
>
> diff --git a/memory.h b/memory.h
> index 2afbf13..f026eae 100644
> --- a/memory.h
> +++ b/memory.h
> @@ -10,9 +10,11 @@
>   #include "targphys.h"
>   #include "qemu-queue.h"
>   #include "iorange.h"
> +#include "ioport.h"
>
>   typedef struct MemoryRegionOps MemoryRegionOps;
>   typedef struct MemoryRegion MemoryRegion;
> +typedef struct MemoryRegionPortio MemoryRegionPortio;
>
>   /* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
>    * registration.
> @@ -65,6 +67,11 @@ struct MemoryRegionOps {
>            */
>            bool unaligned;
>       } impl;
> +
> +    /* If .read and .write are not present, old_portio may be used for
> +     * backwards compatibility with old portio registration
> +     */
> +    const MemoryRegionPortio *old_portio;
>   };
>
>   typedef struct CoalescedMemoryRange CoalescedMemoryRange;
> @@ -92,6 +99,16 @@ struct MemoryRegion {
>       uint8_t dirty_log_mask;
>   };
>
> +struct MemoryRegionPortio {
> +    uint32_t offset;
> +    uint32_t len;
> +    unsigned size;
> +    IOPortReadFunc *read;
> +    IOPortWriteFunc *write;
> +};
> +
> +#define PORTIO_END { }
> +
>   /* Initialize a memory region
>    *
>    * The region typically acts as a container for other memory regions.


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 10/23] memory: add backward compatibility for old mmio registration
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 19:02   ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 19:02 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> This eases the transition to the new API.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   memory.c |   10 ++++++++++
>   memory.h |   10 ++++++++++
>   2 files changed, 20 insertions(+), 0 deletions(-)
>
> diff --git a/memory.c b/memory.c
> index bb04952..e4446a0 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -14,6 +14,7 @@
>   #include "memory.h"
>   #include "exec-memory.h"
>   #include "ioport.h"
> +#include "bitops.h"
>   #include<assert.h>
>
>   typedef struct AddrRange AddrRange;
> @@ -499,6 +500,10 @@ static uint32_t memory_region_read_thunk_n(void *_mr,
>           return -1U; /* FIXME: better signalling */
>       }
>
> +    if (!mr->ops->read) {
> +        return mr->ops->old_mmio.read[bitops_ffsl(size)](mr->opaque, addr);
> +    }
> +
>       /* FIXME: support unaligned access */
>
>       access_size_min = mr->ops->impl.min_access_size;
> @@ -535,6 +540,11 @@ static void memory_region_write_thunk_n(void *_mr,
>           return; /* FIXME: better signalling */
>       }
>
> +    if (!mr->ops->write) {
> +        mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data);
> +        return;
> +    }
> +
>       /* FIXME: support unaligned access */
>
>       access_size_min = mr->ops->impl.min_access_size;
> diff --git a/memory.h b/memory.h
> index f026eae..4624946 100644
> --- a/memory.h
> +++ b/memory.h
> @@ -15,6 +15,7 @@
>   typedef struct MemoryRegionOps MemoryRegionOps;
>   typedef struct MemoryRegion MemoryRegion;
>   typedef struct MemoryRegionPortio MemoryRegionPortio;
> +typedef struct MemoryRegionMmio MemoryRegionMmio;
>
>   /* Must match *_DIRTY_FLAGS in cpu-all.h.  To be replaced with dynamic
>    * registration.
> @@ -23,6 +24,11 @@ typedef struct MemoryRegionPortio MemoryRegionPortio;
>   #define DIRTY_MEMORY_CODE      1
>   #define DIRTY_MEMORY_MIGRATION 3
>
> +struct MemoryRegionMmio {
> +    CPUReadMemoryFunc *read[3];
> +    CPUWriteMemoryFunc *write[3];
> +};
> +
>   /*
>    * Memory region callbacks
>    */
> @@ -72,6 +78,10 @@ struct MemoryRegionOps {
>        * backwards compatibility with old portio registration
>        */
>       const MemoryRegionPortio *old_portio;
> +    /* If .read and .write are not present, old_mmio may be used for
> +     * backwards compatibility with old mmio registration
> +     */
> +    const MemoryRegionMmio old_mmio;
>   };
>
>   typedef struct CoalescedMemoryRange CoalescedMemoryRange;


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
  (?)
@ 2011-07-25 19:08   ` Anthony Liguori
  2011-07-26 10:08     ` Avi Kivity
  -1 siblings, 1 reply; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 19:08 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> As with the rest of the memory API, the caller associates an eventfd
> with an address, and the memory API takes care of registering or
> unregistering when the address is made visible or invisible to the
> guest.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>
> ---
>   memory.c |  230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   memory.h |   20 ++++++
>   2 files changed, 250 insertions(+), 0 deletions(-)
>
> diff --git a/memory.c b/memory.c
> index e4446a0..a5cde0c 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -15,6 +15,7 @@
>   #include "exec-memory.h"
>   #include "ioport.h"
>   #include "bitops.h"
> +#include "kvm.h"
>   #include<assert.h>
>
>   typedef struct AddrRange AddrRange;
> @@ -64,6 +65,50 @@ struct CoalescedMemoryRange {
>       QTAILQ_ENTRY(CoalescedMemoryRange) link;
>   };
>
> +struct MemoryRegionIoeventfd {
> +    AddrRange addr;
> +    bool match_data;
> +    uint64_t data;
> +    int fd;
> +};
> +
> +static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
> +                                           MemoryRegionIoeventfd b)
> +{
> +    if (a.addr.start<  b.addr.start) {
> +        return true;
> +    } else if (a.addr.start>  b.addr.start) {
> +        return false;
> +    } else if (a.addr.size<  b.addr.size) {
> +        return true;
> +    } else if (a.addr.size>  b.addr.size) {
> +        return false;
> +    } else if (a.match_data<  b.match_data) {
> +        return true;
> +    } else  if (a.match_data>  b.match_data) {
> +        return false;
> +    } else if (a.match_data) {
> +        if (a.data<  b.data) {
> +            return true;
> +        } else if (a.data>  b.data) {
> +            return false;
> +        }
> +    }
> +    if (a.fd<  b.fd) {
> +        return true;
> +    } else if (a.fd>  b.fd) {
> +        return false;
> +    }
> +    return false;
> +}
> +
> +static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a,
> +                                          MemoryRegionIoeventfd b)
> +{
> +    return !memory_region_ioeventfd_before(a, b)
> +&&  !memory_region_ioeventfd_before(b, a);
> +}
> +
>   typedef struct FlatRange FlatRange;
>   typedef struct FlatView FlatView;
>
> @@ -92,6 +137,8 @@ struct AddressSpace {
>       const AddressSpaceOps *ops;
>       MemoryRegion *root;
>       FlatView current_map;
> +    int ioeventfd_nb;
> +    MemoryRegionIoeventfd *ioeventfds;
>   };
>
>   struct AddressSpaceOps {
> @@ -99,6 +146,8 @@ struct AddressSpaceOps {
>       void (*range_del)(AddressSpace *as, FlatRange *fr);
>       void (*log_start)(AddressSpace *as, FlatRange *fr);
>       void (*log_stop)(AddressSpace *as, FlatRange *fr);
> +    void (*ioeventfd_add)(AddressSpace *as, MemoryRegionIoeventfd *fd);
> +    void (*ioeventfd_del)(AddressSpace *as, MemoryRegionIoeventfd *fd);
>   };
>
>   #define FOR_EACH_FLAT_RANGE(var, view)          \
> @@ -201,11 +250,37 @@ static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
>       cpu_physical_log_stop(fr->addr.start, fr->addr.size);
>   }
>
> +static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
> +{
> +    int r;
> +
> +    if (!fd->match_data || fd->addr.size != 4) {
> +        abort();
> +    }
> +
> +    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, true);
> +    if (r<  0) {
> +        abort();
> +    }

asserts would be friendlier.

I really dislike baking ioeventfd into this API.  There is only one user 
of ioeventfd in the tree.

I worry that by having things like ioeventfd the API, we're making it 
too difficult to side-step the API which prevents future optimizations.

I'd prefer virtio-pci to have ugliness in it where it circumvented the 
layering vs. having such a device specific thing in generic code.

Regards,

Anthony Liguori

> +}
> +
> +static void as_memory_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
> +{
> +    int r;
> +
> +    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, false);
> +    if (r<  0) {
> +        abort();
> +    }
> +}
> +
>   static const AddressSpaceOps address_space_ops_memory = {
>       .range_add = as_memory_range_add,
>       .range_del = as_memory_range_del,
>       .log_start = as_memory_log_start,
>       .log_stop = as_memory_log_stop,
> +    .ioeventfd_add = as_memory_ioeventfd_add,
> +    .ioeventfd_del = as_memory_ioeventfd_del,
>   };
>
>   static AddressSpace address_space_memory = {
> @@ -281,9 +356,35 @@ static void as_io_range_del(AddressSpace *as, FlatRange *fr)
>       isa_unassign_ioport(fr->addr.start, fr->addr.size);
>   }
>
> +static void as_io_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
> +{
> +    int r;
> +
> +    if (!fd->match_data || fd->addr.size != 2) {
> +        abort();
> +    }
> +
> +    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, true);
> +    if (r<  0) {
> +        abort();
> +    }
> +}
> +
> +static void as_io_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
> +{
> +    int r;
> +
> +    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, false);
> +    if (r<  0) {
> +        abort();
> +    }
> +}
> +
>   static const AddressSpaceOps address_space_ops_io = {
>       .range_add = as_io_range_add,
>       .range_del = as_io_range_del,
> +    .ioeventfd_add = as_io_ioeventfd_add,
> +    .ioeventfd_del = as_io_ioeventfd_del,
>   };
>
>   static AddressSpace address_space_io = {
> @@ -382,6 +483,69 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
>       return view;
>   }
>
> +static void address_space_add_del_ioeventfds(AddressSpace *as,
> +                                             MemoryRegionIoeventfd *fds_new,
> +                                             unsigned fds_new_nb,
> +                                             MemoryRegionIoeventfd *fds_old,
> +                                             unsigned fds_old_nb)
> +{
> +    unsigned iold, inew;
> +
> +    /* Generate a symmetric difference of the old and new fd sets, adding
> +     * and deleting as necessary.
> +     */
> +
> +    iold = inew = 0;
> +    while (iold<  fds_old_nb || inew<  fds_new_nb) {
> +        if (iold<  fds_old_nb
> +&&  (inew == fds_new_nb
> +                || memory_region_ioeventfd_before(fds_old[iold],
> +                                                  fds_new[inew]))) {
> +            as->ops->ioeventfd_del(as,&fds_old[iold]);
> +            ++iold;
> +        } else if (inew<  fds_new_nb
> +&&  (iold == fds_old_nb
> +                       || memory_region_ioeventfd_before(fds_new[inew],
> +                                                         fds_old[iold]))) {
> +            as->ops->ioeventfd_add(as,&fds_new[inew]);
> +            ++inew;
> +        } else {
> +            ++iold;
> +            ++inew;
> +        }
> +    }
> +}
> +
> +static void address_space_update_ioeventfds(AddressSpace *as)
> +{
> +    FlatRange *fr;
> +    unsigned ioeventfd_nb = 0;
> +    MemoryRegionIoeventfd *ioeventfds = NULL;
> +    AddrRange tmp;
> +    unsigned i;
> +
> +    FOR_EACH_FLAT_RANGE(fr,&as->current_map) {
> +        for (i = 0; i<  fr->mr->ioeventfd_nb; ++i) {
> +            tmp = addrrange_shift(fr->mr->ioeventfds[i].addr,
> +                                  fr->addr.start - fr->offset_in_region);
> +            if (addrrange_intersects(fr->addr, tmp)) {
> +                ++ioeventfd_nb;
> +                ioeventfds = qemu_realloc(ioeventfds,
> +                                          ioeventfd_nb * sizeof(*ioeventfds));
> +                ioeventfds[ioeventfd_nb-1] = fr->mr->ioeventfds[i];
> +                ioeventfds[ioeventfd_nb-1].addr = tmp;
> +            }
> +        }
> +    }
> +
> +    address_space_add_del_ioeventfds(as, ioeventfds, ioeventfd_nb,
> +                                     as->ioeventfds, as->ioeventfd_nb);
> +
> +    qemu_free(as->ioeventfds);
> +    as->ioeventfds = ioeventfds;
> +    as->ioeventfd_nb = ioeventfd_nb;
> +}
> +
>   static void address_space_update_topology(AddressSpace *as)
>   {
>       FlatView old_view = as->current_map;
> @@ -434,6 +598,7 @@ static void address_space_update_topology(AddressSpace *as)
>       }
>       as->current_map = new_view;
>       flatview_destroy(&old_view);
> +    address_space_update_ioeventfds(as);
>   }
>
>   static void memory_region_update_topology(void)
> @@ -464,6 +629,8 @@ void memory_region_init(MemoryRegion *mr,
>       QTAILQ_INIT(&mr->coalesced);
>       mr->name = qemu_strdup(name);
>       mr->dirty_log_mask = 0;
> +    mr->ioeventfd_nb = 0;
> +    mr->ioeventfds = NULL;
>   }
>
>   static bool memory_region_access_valid(MemoryRegion *mr,
> @@ -675,6 +842,7 @@ void memory_region_destroy(MemoryRegion *mr)
>       assert(QTAILQ_EMPTY(&mr->subregions));
>       memory_region_clear_coalescing(mr);
>       qemu_free((char *)mr->name);
> +    qemu_free(mr->ioeventfds);
>   }
>
>   target_phys_addr_t memory_region_size(MemoryRegion *mr)
> @@ -798,6 +966,68 @@ void memory_region_clear_coalescing(MemoryRegion *mr)
>       memory_region_update_coalesced_range(mr);
>   }
>
> +void memory_region_add_eventfd(MemoryRegion *mr,
> +                               target_phys_addr_t addr,
> +                               unsigned size,
> +                               bool match_data,
> +                               uint64_t data,
> +                               int fd)
> +{
> +    MemoryRegionIoeventfd mrfd = {
> +        .addr.start = addr,
> +        .addr.size = size,
> +        .match_data = match_data,
> +        .data = data,
> +        .fd = fd,
> +    };
> +    unsigned i;
> +
> +    for (i = 0; i<  mr->ioeventfd_nb; ++i) {
> +        if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) {
> +            break;
> +        }
> +    }
> +    ++mr->ioeventfd_nb;
> +    mr->ioeventfds = qemu_realloc(mr->ioeventfds,
> +                                  sizeof(*mr->ioeventfds) * mr->ioeventfd_nb);
> +    memmove(&mr->ioeventfds[i+1],&mr->ioeventfds[i],
> +            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
> +    mr->ioeventfds[i] = mrfd;
> +    memory_region_update_topology();
> +}
> +
> +void memory_region_del_eventfd(MemoryRegion *mr,
> +                               target_phys_addr_t addr,
> +                               unsigned size,
> +                               bool match_data,
> +                               uint64_t data,
> +                               int fd)
> +{
> +    MemoryRegionIoeventfd mrfd = {
> +        .addr.start = addr,
> +        .addr.size = size,
> +        .match_data = match_data,
> +        .data = data,
> +        .fd = fd,
> +    };
> +    unsigned i;
> +
> +    for (i = 0; i<  mr->ioeventfd_nb; ++i) {
> +        if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) {
> +            break;
> +        }
> +    }
> +    if (i == mr->ioeventfd_nb) {
> +        abort();
> +    }
> +    memmove(&mr->ioeventfds[i],&mr->ioeventfds[i+1],
> +            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb - (i+1)));
> +    --mr->ioeventfd_nb;
> +    mr->ioeventfds = qemu_realloc(mr->ioeventfds,
> +                                  sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
> +    memory_region_update_topology();
> +}
> +
>   static void memory_region_add_subregion_common(MemoryRegion *mr,
>                                                  target_phys_addr_t offset,
>                                                  MemoryRegion *subregion)
> diff --git a/memory.h b/memory.h
> index 4624946..e4c0ad1 100644
> --- a/memory.h
> +++ b/memory.h
> @@ -85,6 +85,7 @@ struct MemoryRegionOps {
>   };
>
>   typedef struct CoalescedMemoryRange CoalescedMemoryRange;
> +typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
>
>   struct MemoryRegion {
>       /* All fields are private - violators will be prosecuted */
> @@ -107,6 +108,8 @@ struct MemoryRegion {
>       QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
>       const char *name;
>       uint8_t dirty_log_mask;
> +    unsigned ioeventfd_nb;
> +    MemoryRegionIoeventfd *ioeventfds;
>   };
>
>   struct MemoryRegionPortio {
> @@ -208,6 +211,23 @@ void memory_region_add_coalescing(MemoryRegion *mr,
>   /* Disable MMIO coalescing for the region. */
>   void memory_region_clear_coalescing(MemoryRegion *mr);
>
> +
> +/* Request an eventfd to be triggered when a word is written to a location */
> +void memory_region_add_eventfd(MemoryRegion *mr,
> +                               target_phys_addr_t addr,
> +                               unsigned size,
> +                               bool match_data,
> +                               uint64_t data,
> +                               int fd);
> +
> +/* Cancel an existing eventfd  */
> +void memory_region_del_eventfd(MemoryRegion *mr,
> +                               target_phys_addr_t addr,
> +                               unsigned size,
> +                               bool match_data,
> +                               uint64_t data,
> +                               int fd);
> +
>   /* Add a sub-region at @offset.  The sub-region may not overlap with other
>    * subregions (except for those explicitly marked as overlapping)
>    */


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 12/23] memory: separate building the final memory map into two steps
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 19:12   ` Anthony Liguori
  2011-07-26 10:43       ` [Qemu-devel] " Avi Kivity
  -1 siblings, 1 reply; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 19:12 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> Instead of adding and deleting regions in one pass, do a delete
> pass followed by an add pass.  This fixes the following case:
>
> from:
>    0x0000-0x0fff ram  (a1)
>    0x1000-0x1fff mmio (a2)
>    0x2000-0x2fff ram  (a3)
>
> to:
>    0x0000-0x2fff ram  (b1)
>
> The single pass algorithm removed a1, added b2, then removed a2 and a2,

You mean a2 and a3 I suppose?

Regards,

Anthony Liguori

> which caused the wrong memory map to be built.  The two pass algorithm
> removes a1, a2, and a3, then adds b1.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>
> ---
>   memory.c |   38 +++++++++++++++++++++++++++++---------
>   1 files changed, 29 insertions(+), 9 deletions(-)
>
> diff --git a/memory.c b/memory.c
> index a5cde0c..009ad33 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -546,10 +546,11 @@ static void address_space_update_ioeventfds(AddressSpace *as)
>       as->ioeventfd_nb = ioeventfd_nb;
>   }
>
> -static void address_space_update_topology(AddressSpace *as)
> +static void address_space_update_topology_pass(AddressSpace *as,
> +                                               FlatView old_view,
> +                                               FlatView new_view,
> +                                               bool adding)
>   {
> -    FlatView old_view = as->current_map;
> -    FlatView new_view = generate_memory_topology(as->root);
>       unsigned iold, inew;
>       FlatRange *frold, *frnew;
>
> @@ -576,15 +577,20 @@ static void address_space_update_topology(AddressSpace *as)
>                       &&  !flatrange_equal(frold, frnew)))) {
>               /* In old, but (not in new, or in new but attributes changed). */
>
> -            as->ops->range_del(as, frold);
> +            if (!adding) {
> +                as->ops->range_del(as, frold);
> +            }
> +
>               ++iold;
>           } else if (frold&&  frnew&&  flatrange_equal(frold, frnew)) {
>               /* In both (logging may have changed) */
>
> -            if (frold->dirty_log_mask&&  !frnew->dirty_log_mask) {
> -                as->ops->log_stop(as, frnew);
> -            } else if (frnew->dirty_log_mask&&  !frold->dirty_log_mask) {
> -                as->ops->log_start(as, frnew);
> +            if (adding) {
> +                if (frold->dirty_log_mask&&  !frnew->dirty_log_mask) {
> +                    as->ops->log_stop(as, frnew);
> +                } else if (frnew->dirty_log_mask&&  !frold->dirty_log_mask) {
> +                    as->ops->log_start(as, frnew);
> +                }
>               }
>
>               ++iold;
> @@ -592,10 +598,24 @@ static void address_space_update_topology(AddressSpace *as)
>           } else {
>               /* In new */
>
> -            as->ops->range_add(as, frnew);
> +            if (adding) {
> +                as->ops->range_add(as, frnew);
> +            }
> +
>               ++inew;
>           }
>       }
> +}
> +
> +
> +static void address_space_update_topology(AddressSpace *as)
> +{
> +    FlatView old_view = as->current_map;
> +    FlatView new_view = generate_memory_topology(as->root);
> +
> +    address_space_update_topology_pass(as, old_view, new_view, false);
> +    address_space_update_topology_pass(as, old_view, new_view, true);
> +
>       as->current_map = new_view;
>       flatview_destroy(&old_view);
>       address_space_update_ioeventfds(as);


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 13/23] memory: document the memory API
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 19:15   ` Anthony Liguori
  2011-07-26 10:44     ` Avi Kivity
  -1 siblings, 1 reply; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 19:15 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> Signed-off-by: Avi Kivity<avi@redhat.com>
> ---
>   docs/memory.txt |  172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 files changed, 172 insertions(+), 0 deletions(-)
>   create mode 100644 docs/memory.txt
>
> diff --git a/docs/memory.txt b/docs/memory.txt
> new file mode 100644
> index 0000000..4460c06
> --- /dev/null
> +++ b/docs/memory.txt
> @@ -0,0 +1,172 @@
> +The memory API
> +==============
> +
> +The memory API models the memory and I/O buses and controllers of a QEMU
> +machine.  It attempts to allow modelling of:
> +
> + - ordinary RAM
> + - memory-mapped I/O (MMIO)
> + - memory controllers that can dynamically reroute physical memory regions
> +  to different destinations
> +
> +The memory model provides support for
> +
> + - tracking RAM changes by the guest
> + - setting up coalesced memory for kvm
> + - setting up ioeventfd regions for kvm
> +
> +Memory is modelled as an tree (really acyclic graph) of MemoryRegion objects.
> +The root of the tree is memory as seen from the CPU's viewpoint (the system
> +bus).  Nodes in the tree represent other buses, memory controllers, and
> +memory regions that have been rerouted.  Leaves are RAM and MMIO regions.
> +
> +Types of regions
> +----------------
> +
> +There are four types of memory regions (all represented by a single C type
> +MemoryRegion):
> +
> +- RAM: a RAM region is simply a range of host memory that can be made available
> +  to the guest.
> +
> +- MMIO: a range of guest memory that is implemented by host callbacks;
> +  each read or write causes a callback to be called on the host.
> +
> +- container: a container simply includes other memory regions, each at
> +  a different offset.  Containers are useful for grouping several regions
> +  into one unit.  For example, a PCI BAR may be composed of a RAM region
> +  and an MMIO region.
> +
> +  A container's subregions are usually non-overlapping.  In some cases it is
> +  useful to have overlapping regions; for example a memory controller that
> +  can overlay a subregion of RAM with MMIO or ROM, or a PCI controller
> +  that does not prevent card from claiming overlapping BARs.
> +
> +- alias: a subsection of another region.  Aliases allow a region to be
> +  split apart into discontiguous regions.  Examples of uses are memory banks
> +  used when the guest address space is smaller than the amount of RAM
> +  addressed, or a memory controller that splits main memory to expose a "PCI
> +  hole".  Aliases may point to any type of region, including other aliases,
> +  but an alias may not point back to itself, directly or indirectly.
> +
> +
> +Region names
> +------------
> +
> +Regions are assigned names by the constructor.  For most regions these are
> +only used for debugging purposes, but RAM regions also use the name to identify
> +live migration sections.  This means that RAM region names need to have ABI
> +stability.

I don't think this needs to change for this series, but long term, this 
is something that we need to better think through.

Device ROM is part of the device.  It shouldn't be migrated as RAM, it 
should be included in the device state.

Would be nice to make this patch #1 in the series.

Regards,

Anthony Liguori

> +
> +Region lifecycle
> +----------------
> +
> +A region is created by one of the constructor functions (memory_region_init*())
> +and destroyed by the destructor (memory_region_destroy()).  In between,
> +a region can be added to an address space by using memory_region_add_subregion()
> +and removed using memory_region_del_subregion().  Region attributes may be
> +changed at any point; they take effect once the region becomes exposed to the
> +guest.
> +
> +Overlapping regions and priority
> +--------------------------------
> +Usually, regions may not overlap each other; a memory address decodes into
> +exactly one target.  In some cases it is useful to allow regions to overlap,
> +and sometimes to control which of an overlapping regions is visible to the
> +guest.  This is done with memory_region_add_subregion_overlap(), which
> +allows the region to overlap any other region in the same container, and
> +specifies a priority that allows the core to decide which of two regions at
> +the same address are visible (highest wins).
> +
> +Visibility
> +----------
> +The memory core uses the following rules to select a memory region when the
> +guest accesses an address:
> +
> +- all direct subregions of the root region are matched against the address, in
> +  descending priority order
> +  - if the address lies outside the region offset/size, the subregion is
> +    discarded
> +  - if the subregion is a leaf (RAM or MMIO), the seach terminates
> +  - if the subregion is a container, the same algorithm is used within the
> +    subregion (after the address is adjusted by the subregion offset)
> +  - if the subregion is an alias, the search is continues at the alias target
> +    (after the address is adjusted by the subregion offset and alias offset)
> +
> +Example memory map
> +------------------
> +
> +system_memory: container@0-2^48-1
> + |
> + +---- lomem: alias@0-0xdfffffff --->  #ram (0-0xdfffffff)
> + |
> + +---- himem: alias@0x100000000-0x11fffffff --->  #ram (0xe0000000-0xffffffff)
> + |
> + +---- vga-window: alias@0xa0000-0xbfffff --->  #pci (0xa0000-0xbffff)
> + |      (prio 1)
> + |
> + +---- pci-hole: alias@0xe0000000-0xffffffff --->  #pci (0xe0000000-0xffffffff)
> +
> +pci (0-2^32-1)
> + |
> + +--- vga-area: container@0xa0000-0xbffff
> + |      |
> + |      +--- alias@0x00000-0x7fff  --->  #vram (0x010000-0x017fff)
> + |      |
> + |      +--- alias@0x08000-0xffff  --->  #vram (0x020000-0x027fff)
> + |
> + +---- vram: ram@0xe1000000-0xe1ffffff
> + |
> + +---- vga-mmio: mmio@0xe2000000-0xe200ffff
> +
> +ram: ram@0x00000000-0xffffffff
> +
> +The is a (simplified) PC memory map. The 4GB RAM block is mapped into the
> +system address space via two aliases: "lomem" is a 1:1 mapping of the first
> +3.5GB; "himem" maps the last 0.5GB at address 4GB.  This leaves 0.5GB for the
> +so-called PCI hole, that allows a 32-bit PCI bus to exist in a system with
> +4GB of memory.
> +
> +The memory controller diverts addresses in the range 640K-768K to the PCI
> +address space.  This is modeled using the "vga-window" alias, mapped at a
> +higher priority so it obscures the RAM at the same addresses.  The vga window
> +can be removed by programming the memory controller; this is modelled by
> +removing the alias and exposing the RAM underneath.
> +
> +The pci address space is not a direct child of the system address space, since
> +we only want parts of it to be visible (we accomplish this using aliases).
> +It has two subregions: vga-area models the legacy vga window and is occupied
> +by two 32K memory banks pointing at two sections of the framebuffer.
> +In addition the vram is mapped as a BAR at address e1000000, and an additional
> +BAR containing MMIO registers is mapped after it.
> +
> +Note that if the guest maps a BAR outside the PCI hole, it would not be
> +visible as the pci-hole alias clips it to a 0.5GB range.
> +
> +Attributes
> +----------
> +
> +Various region attributes (read-only, dirty logging, coalesced mmio, ioeventfd)
> +can be changed during the region lifecycle.  They take effect once the region
> +is made visible (which can be immediately, later, or never).
> +
> +MMIO Operations
> +---------------
> +
> +MMIO regions are provided with ->read() and ->write() callbacks; in addition
> +various constraints can be supplied to control how these callbacks are called:
> +
> + - .valid.min_access_size, .valid.max_access_size define the access sizes
> +   (in bytes) which the device accepts; accesses outside this range will
> +   have device and bus specific behaviour (ignored, or machine check)
> + - .valid.aligned specifies that the device only accepts naturally aligned
> +   accesses.  Unaligned accesses invoke device and bus specific behaviour.
> + - .impl.min_access_size, .impl.max_access_size define the access sizes
> +   (in bytes) supported by the *implementation*; other access sizes will be
> +   emulated using the ones available.  For example a 4-byte write will be
> +   emulated using four 1-byte write, is .impl.max_access_size = 1.
> + - .impl.valid specifies that the *implementation* only supports unaligned
> +   accesses; unaligned accesses will be emulated by two aligned accesses.
> + - .old_portio and .old_mmio can be used to ease porting from code using
> +   cpu_register_io_memory() and register_ioport().  They should not be used
> +   in new code.


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 14/23] memory: transaction API
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 19:16   ` Anthony Liguori
  2011-07-26 10:48     ` Avi Kivity
  -1 siblings, 1 reply; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 19:16 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> Allow changes to the memory hierarchy to be accumulated and
> made visible all at once.  This reduces computational effort,
> especially when an accelerator (e.g. kvm) is involved.
>
> Useful when a single register update causes multiple changes
> to an address space.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

What's the motivation for this?  Was this just because it seemed neat to 
do or did you run into a performance issue you were trying to solve?


> ---
>   memory.c |   20 ++++++++++++++++++++
>   memory.h |    8 ++++++++
>   2 files changed, 28 insertions(+), 0 deletions(-)
>
> diff --git a/memory.c b/memory.c
> index 009ad33..370e189 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -18,6 +18,8 @@
>   #include "kvm.h"
>   #include<assert.h>
>
> +unsigned memory_region_transaction_depth = 0;

Shouldn't this be static?

Regards,

Anthony Liguori

> +
>   typedef struct AddrRange AddrRange;
>
>   struct AddrRange {
> @@ -623,6 +625,10 @@ static void address_space_update_topology(AddressSpace *as)
>
>   static void memory_region_update_topology(void)
>   {
> +    if (memory_region_transaction_depth) {
> +        return;
> +    }
> +
>       if (address_space_memory.root) {
>           address_space_update_topology(&address_space_memory);
>       }
> @@ -631,6 +637,20 @@ static void memory_region_update_topology(void)
>       }
>   }
>
> +void memory_region_transaction_begin(void)
> +{
> +    ++memory_region_transaction_depth;
> +}
> +
> +void memory_region_transaction_commit(void)
> +{
> +    if (!memory_region_transaction_depth) {
> +        abort();
> +    }
> +    --memory_region_transaction_depth;
> +    memory_region_update_topology();
> +}
> +
>   void memory_region_init(MemoryRegion *mr,
>                           const char *name,
>                           uint64_t size)
> diff --git a/memory.h b/memory.h
> index e4c0ad1..cb3a9b6 100644
> --- a/memory.h
> +++ b/memory.h
> @@ -246,6 +246,14 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
>   void memory_region_del_subregion(MemoryRegion *mr,
>                                    MemoryRegion *subregion);
>
> +/* Start a transaction; changes will be accumulated and made visible only
> + * when the transaction ends.
> + */
> +void memory_region_transaction_begin(void);
> +/* Commit a transaction and make changes visible to the guest.
> + */
> +void memory_region_transaction_commit(void);
> +
>   #endif
>
>   #endif


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 15/23] exec.c: initialize memory map
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 19:17   ` Anthony Liguori
  2011-07-26 10:55       ` [Qemu-devel] " Avi Kivity
  -1 siblings, 1 reply; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 19:17 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> Allocate the root memory region and initialize it.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>
> ---
>   exec.c |   19 +++++++++++++++++++
>   1 files changed, 19 insertions(+), 0 deletions(-)
>
> diff --git a/exec.c b/exec.c
> index 2160ded..d51502f 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -33,6 +33,8 @@
>   #include "kvm.h"
>   #include "hw/xen.h"
>   #include "qemu-timer.h"
> +#include "memory.h"
> +#include "exec-memory.h"
>   #if defined(CONFIG_USER_ONLY)
>   #include<qemu.h>
>   #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
> @@ -109,6 +111,9 @@ int phys_ram_fd;
>   static int in_migration;
>
>   RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list) };
> +
> +static MemoryRegion *system_memory;
> +
>   #endif
>
>   CPUState *first_cpu;
> @@ -197,6 +202,7 @@ typedef struct PhysPageDesc {
>   static void *l1_phys_map[P_L1_SIZE];
>
>   static void io_mem_init(void);
> +static void memory_map_init(void);
>
>   /* io memory support */
>   CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
> @@ -571,6 +577,7 @@ void cpu_exec_init_all(unsigned long tb_size)
>       code_gen_ptr = code_gen_buffer;
>       page_init();
>   #if !defined(CONFIG_USER_ONLY)
> +    memory_map_init();
>       io_mem_init();
>   #endif
>   #if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
> @@ -3807,6 +3814,18 @@ static void io_mem_init(void)
>                                             DEVICE_NATIVE_ENDIAN);
>   }
>
> +static void memory_map_init(void)
> +{
> +    system_memory = qemu_malloc(sizeof(*system_memory));
> +    memory_region_init(system_memory, "system", UINT64_MAX);

Would be nice to #define MEM_REG_SIZE_ALL UINT64_MAX

Without reading the docs, it seems like an odd bit of code otherwise.

Regards,

Anthony Liguori

> +    set_system_memory_map(system_memory);
> +}
> +
> +MemoryRegion *get_system_memory(void)
> +{
> +    return system_memory;
> +}
> +
>   #endif /* !defined(CONFIG_USER_ONLY) */
>
>   /* physical memory access (slow version, mainly for debug) */


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 16/23] ioport: register ranges by byte aligned addresses always
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 19:20   ` Anthony Liguori
  2011-07-26 10:59     ` Avi Kivity
  -1 siblings, 1 reply; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 19:20 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> The I/O port space is byte addressable, even for word and long accesses.
>
> An example is the VMware svga card, which has long ports on offsets 0,
> 1, and 2.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

I've always thought this was odd but didn't know of a specific 
circumstance where it broke a device.

This was a big problem with the old API.  Devices don't register their 
interest in specific sizes.  They may ignore certain size accesses but 
that's a device specific behavior.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   ioport.c |    4 ++--
>   1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/ioport.c b/ioport.c
> index 0d2611d..a32483b 100644
> --- a/ioport.c
> +++ b/ioport.c
> @@ -146,7 +146,7 @@ int register_ioport_read(pio_addr_t start, int length, int size,
>           hw_error("register_ioport_read: invalid size");
>           return -1;
>       }
> -    for(i = start; i<  start + length; i += size) {
> +    for(i = start; i<  start + length; ++i) {
>           ioport_read_table[bsize][i] = func;
>           if (ioport_opaque[i] != NULL&&  ioport_opaque[i] != opaque)
>               hw_error("register_ioport_read: invalid opaque for address 0x%x",
> @@ -166,7 +166,7 @@ int register_ioport_write(pio_addr_t start, int length, int size,
>           hw_error("register_ioport_write: invalid size");
>           return -1;
>       }
> -    for(i = start; i<  start + length; i += size) {
> +    for(i = start; i<  start + length; ++i) {
>           ioport_write_table[bsize][i] = func;
>           if (ioport_opaque[i] != NULL&&  ioport_opaque[i] != opaque)
>               hw_error("register_ioport_write: invalid opaque for address 0x%x",


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 17/23] pc: grab system_memory
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 19:22   ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 19:22 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> While eventually this should come from the machine initialization function,
> take a short cut to avoid converting all machines now.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

I think it should happen in the i440fx actually.  We should treat RAM as 
just another device as it would allow for better support of platforms 
with more interesting RAM topologies.

But for right now, this is appropriate.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   hw/pc.c      |    3 ++-
>   hw/pc.h      |    4 +++-
>   hw/pc_piix.c |    8 +++++++-
>   3 files changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/hw/pc.c b/hw/pc.c
> index a3e8539..369566a 100644
> --- a/hw/pc.c
> +++ b/hw/pc.c
> @@ -957,7 +957,8 @@ void pc_cpus_init(const char *cpu_model)
>       }
>   }
>
> -void pc_memory_init(const char *kernel_filename,
> +void pc_memory_init(MemoryRegion *system_memory,
> +                    const char *kernel_filename,
>                       const char *kernel_cmdline,
>                       const char *initrd_filename,
>                       ram_addr_t below_4g_mem_size,
> diff --git a/hw/pc.h b/hw/pc.h
> index 6d5730b..fa57583 100644
> --- a/hw/pc.h
> +++ b/hw/pc.h
> @@ -6,6 +6,7 @@
>   #include "isa.h"
>   #include "fdc.h"
>   #include "net.h"
> +#include "memory.h"
>
>   /* PC-style peripherals (also used by other machines).  */
>
> @@ -129,7 +130,8 @@ void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
>   void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
>
>   void pc_cpus_init(const char *cpu_model);
> -void pc_memory_init(const char *kernel_filename,
> +void pc_memory_init(MemoryRegion *system_memory,
> +                    const char *kernel_filename,
>                       const char *kernel_cmdline,
>                       const char *initrd_filename,
>                       ram_addr_t below_4g_mem_size,
> diff --git a/hw/pc_piix.c b/hw/pc_piix.c
> index c5c16b4..d83854c 100644
> --- a/hw/pc_piix.c
> +++ b/hw/pc_piix.c
> @@ -39,6 +39,8 @@
>   #include "blockdev.h"
>   #include "smbus.h"
>   #include "xen.h"
> +#include "memory.h"
> +#include "exec-memory.h"
>   #ifdef CONFIG_XEN
>   #  include<xen/hvm/hvm_info_table.h>
>   #endif
> @@ -89,6 +91,9 @@ static void pc_init1(ram_addr_t ram_size,
>       DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
>       BusState *idebus[MAX_IDE_BUS];
>       ISADevice *rtc_state;
> +    MemoryRegion *system_memory;
> +
> +    system_memory = get_system_memory();
>
>       pc_cpus_init(cpu_model);
>
> @@ -106,7 +111,8 @@ static void pc_init1(ram_addr_t ram_size,
>
>       /* allocate ram and load rom/bios */
>       if (!xen_enabled()) {
> -        pc_memory_init(kernel_filename, kernel_cmdline, initrd_filename,
> +        pc_memory_init(system_memory,
> +                       kernel_filename, kernel_cmdline, initrd_filename,
>                          below_4g_mem_size, above_4g_mem_size);
>       }
>


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 18/23] pc: convert pc_memory_init() to memory API
  2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 19:23   ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 19:23 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> Signed-off-by: Avi Kivity<avi@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   hw/pc.c |   59 ++++++++++++++++++++++++++++++++++++++++-------------------
>   hw/pc.h |    1 +
>   2 files changed, 41 insertions(+), 19 deletions(-)
>
> diff --git a/hw/pc.c b/hw/pc.c
> index 369566a..1c9d89a 100644
> --- a/hw/pc.c
> +++ b/hw/pc.c
> @@ -41,6 +41,7 @@
>   #include "sysemu.h"
>   #include "blockdev.h"
>   #include "ui/qemu-spice.h"
> +#include "memory.h"
>
>   /* output Bochs bios info messages */
>   //#define DEBUG_BIOS
> @@ -966,22 +967,30 @@ void pc_memory_init(MemoryRegion *system_memory,
>   {
>       char *filename;
>       int ret, linux_boot, i;
> -    ram_addr_t ram_addr, bios_offset, option_rom_offset;
> +    MemoryRegion *ram, *bios, *isa_bios, *option_rom_mr;
> +    MemoryRegion *ram_below_4g, *ram_above_4g;
>       int bios_size, isa_bios_size;
>       void *fw_cfg;
>
>       linux_boot = (kernel_filename != NULL);
>
> -    /* allocate RAM */
> -    ram_addr = qemu_ram_alloc(NULL, "pc.ram",
> -                              below_4g_mem_size + above_4g_mem_size);
> -    cpu_register_physical_memory(0, 0xa0000, ram_addr);
> -    cpu_register_physical_memory(0x100000,
> -                 below_4g_mem_size - 0x100000,
> -                 ram_addr + 0x100000);
> +    /* Allocate RAM.  We allocate it as a single memory region and use
> +     * aliases to address portions of it, mostly for backwards compatiblity
> +     * with older qemus that used qemu_ram_alloc().
> +     */
> +    ram = qemu_malloc(sizeof(*ram));
> +    memory_region_init_ram(ram, NULL, "pc.ram",
> +                           below_4g_mem_size + above_4g_mem_size);
> +    ram_below_4g = qemu_malloc(sizeof(*ram_below_4g));
> +    memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
> +                             0, below_4g_mem_size);
> +    memory_region_add_subregion(system_memory, 0, ram_below_4g);
>       if (above_4g_mem_size>  0) {
> -        cpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
> -                                     ram_addr + below_4g_mem_size);
> +        ram_above_4g = qemu_malloc(sizeof(*ram_above_4g));
> +        memory_region_init_alias(ram_above_4g, "ram-above-4g", ram,
> +                                 below_4g_mem_size, above_4g_mem_size);
> +        memory_region_add_subregion(system_memory, 0x100000000ULL,
> +                                    ram_above_4g);
>       }
>
>       /* BIOS load */
> @@ -997,7 +1006,9 @@ void pc_memory_init(MemoryRegion *system_memory,
>           (bios_size % 65536) != 0) {
>           goto bios_error;
>       }
> -    bios_offset = qemu_ram_alloc(NULL, "pc.bios", bios_size);
> +    bios = qemu_malloc(sizeof(*bios));
> +    memory_region_init_ram(bios, NULL, "pc.bios", bios_size);
> +    memory_region_set_readonly(bios, true);
>       ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
>       if (ret != 0) {
>       bios_error:
> @@ -1011,16 +1022,26 @@ void pc_memory_init(MemoryRegion *system_memory,
>       isa_bios_size = bios_size;
>       if (isa_bios_size>  (128 * 1024))
>           isa_bios_size = 128 * 1024;
> -    cpu_register_physical_memory(0x100000 - isa_bios_size,
> -                                 isa_bios_size,
> -                                 (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
> -
> -    option_rom_offset = qemu_ram_alloc(NULL, "pc.rom", PC_ROM_SIZE);
> -    cpu_register_physical_memory(PC_ROM_MIN_VGA, PC_ROM_SIZE, option_rom_offset);
> +    isa_bios = qemu_malloc(sizeof(*isa_bios));
> +    memory_region_init_alias(isa_bios, "isa-bios", bios,
> +                             bios_size - isa_bios_size, isa_bios_size);
> +    memory_region_add_subregion_overlap(system_memory,
> +                                        0x100000 - isa_bios_size,
> +                                        isa_bios,
> +                                        1);
> +    memory_region_set_readonly(isa_bios, true);
> +
> +    option_rom_mr = qemu_malloc(sizeof(*option_rom_mr));
> +    memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE);
> +    memory_region_add_subregion_overlap(system_memory,
> +                                        PC_ROM_MIN_VGA,
> +                                        option_rom_mr,
> +                                        1);
>
>       /* map all the bios at the top of memory */
> -    cpu_register_physical_memory((uint32_t)(-bios_size),
> -                                 bios_size, bios_offset | IO_MEM_ROM);
> +    memory_region_add_subregion(system_memory,
> +                                (uint32_t)(-bios_size),
> +                                bios);
>
>       fw_cfg = bochs_bios_init();
>       rom_set_fw(fw_cfg);
> diff --git a/hw/pc.h b/hw/pc.h
> index fa57583..40684f4 100644
> --- a/hw/pc.h
> +++ b/hw/pc.h
> @@ -2,6 +2,7 @@
>   #define HW_PC_H
>
>   #include "qemu-common.h"
> +#include "memory.h"
>   #include "ioport.h"
>   #include "isa.h"
>   #include "fdc.h"


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 19/23] pc: move global memory map out of pc_init1() and into its callers
  2011-07-25 14:03   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 20:02   ` Anthony Liguori
  2011-07-26 11:02     ` Avi Kivity
  -1 siblings, 1 reply; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 20:02 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:03 AM, Avi Kivity wrote:
> Signed-off-by: Avi Kivity<avi@redhat.com>

What's the rationale here?

Regards,

Anthony Liguori

> ---
>   hw/pc_piix.c |   15 ++++++++-------
>   1 files changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/hw/pc_piix.c b/hw/pc_piix.c
> index d83854c..f2d0476 100644
> --- a/hw/pc_piix.c
> +++ b/hw/pc_piix.c
> @@ -68,7 +68,8 @@ static void ioapic_init(IsaIrqState *isa_irq_state)
>   }
>
>   /* PC hardware initialisation */
> -static void pc_init1(ram_addr_t ram_size,
> +static void pc_init1(MemoryRegion *system_memory,
> +                     ram_addr_t ram_size,
>                        const char *boot_device,
>                        const char *kernel_filename,
>                        const char *kernel_cmdline,
> @@ -91,9 +92,6 @@ static void pc_init1(ram_addr_t ram_size,
>       DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
>       BusState *idebus[MAX_IDE_BUS];
>       ISADevice *rtc_state;
> -    MemoryRegion *system_memory;
> -
> -    system_memory = get_system_memory();
>
>       pc_cpus_init(cpu_model);
>
> @@ -214,7 +212,8 @@ static void pc_init_pci(ram_addr_t ram_size,
>                           const char *initrd_filename,
>                           const char *cpu_model)
>   {
> -    pc_init1(ram_size, boot_device,
> +    pc_init1(get_system_memory(),
> +             ram_size, boot_device,
>                kernel_filename, kernel_cmdline,
>                initrd_filename, cpu_model, 1, 1);
>   }
> @@ -226,7 +225,8 @@ static void pc_init_pci_no_kvmclock(ram_addr_t ram_size,
>                                       const char *initrd_filename,
>                                       const char *cpu_model)
>   {
> -    pc_init1(ram_size, boot_device,
> +    pc_init1(get_system_memory(),
> +             ram_size, boot_device,
>                kernel_filename, kernel_cmdline,
>                initrd_filename, cpu_model, 1, 0);
>   }
> @@ -240,7 +240,8 @@ static void pc_init_isa(ram_addr_t ram_size,
>   {
>       if (cpu_model == NULL)
>           cpu_model = "486";
> -    pc_init1(ram_size, boot_device,
> +    pc_init1(get_system_memory(),
> +             ram_size, boot_device,
>                kernel_filename, kernel_cmdline,
>                initrd_filename, cpu_model, 0, 1);
>   }


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH 20/23] pci: pass address space to pci bus when created
  2011-07-25 14:03   ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 20:03     ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 20:03 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:03 AM, Avi Kivity wrote:
> This is now done sloppily, via get_system_memory().  Eventually callers
> will be converted to stop using that.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   hw/apb_pci.c       |    2 ++
>   hw/bonito.c        |    4 +++-
>   hw/grackle_pci.c   |    5 +++--
>   hw/gt64xxx.c       |    4 +++-
>   hw/pc.h            |    4 +++-
>   hw/pc_piix.c       |    3 ++-
>   hw/pci.c           |   16 +++++++++++-----
>   hw/pci.h           |   12 +++++++++---
>   hw/pci_host.h      |    1 +
>   hw/pci_internals.h |    1 +
>   hw/piix_pci.c      |   13 +++++++++----
>   hw/ppc4xx_pci.c    |    5 ++++-
>   hw/ppc_mac.h       |    9 ++++++---
>   hw/ppc_newworld.c  |    5 +++--
>   hw/ppc_oldworld.c  |    3 ++-
>   hw/ppc_prep.c      |    3 ++-
>   hw/ppce500_pci.c   |    6 +++++-
>   hw/prep_pci.c      |    5 +++--
>   hw/prep_pci.h      |    3 ++-
>   hw/sh_pci.c        |    4 +++-
>   hw/unin_pci.c      |   10 ++++++----
>   hw/versatile_pci.c |    2 ++
>   22 files changed, 85 insertions(+), 35 deletions(-)
>
> diff --git a/hw/apb_pci.c b/hw/apb_pci.c
> index 974c87a..8b9939c 100644
> --- a/hw/apb_pci.c
> +++ b/hw/apb_pci.c
> @@ -34,6 +34,7 @@
>   #include "rwhandler.h"
>   #include "apb_pci.h"
>   #include "sysemu.h"
> +#include "exec-memory.h"
>
>   /* debug APB */
>   //#define DEBUG_APB
> @@ -346,6 +347,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
>
>       d->bus = pci_register_bus(&d->busdev.qdev, "pci",
>                                            pci_apb_set_irq, pci_pbm_map_irq, d,
> +                                         get_system_memory(),
>                                            0, 32);
>       pci_bus_set_mem_base(d->bus, mem_base);
>
> diff --git a/hw/bonito.c b/hw/bonito.c
> index e8c57a3..5f62dda 100644
> --- a/hw/bonito.c
> +++ b/hw/bonito.c
> @@ -42,6 +42,7 @@
>   #include "mips.h"
>   #include "pci_host.h"
>   #include "sysemu.h"
> +#include "exec-memory.h"
>
>   //#define DEBUG_BONITO
>
> @@ -773,7 +774,8 @@ PCIBus *bonito_init(qemu_irq *pic)
>       dev = qdev_create(NULL, "Bonito-pcihost");
>       pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev));
>       b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq,
> -                         pci_bonito_map_irq, pic, 0x28, 32);
> +                         pci_bonito_map_irq, pic, get_system_memory(),
> +                         0x28, 32);
>       pcihost->bus = b;
>       qdev_init_nofail(dev);
>
> diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
> index cee07e0..da67cf9 100644
> --- a/hw/grackle_pci.c
> +++ b/hw/grackle_pci.c
> @@ -61,7 +61,8 @@ static void pci_grackle_reset(void *opaque)
>   {
>   }
>
> -PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
> +PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
> +                         MemoryRegion *address_space)
>   {
>       DeviceState *dev;
>       SysBusDevice *s;
> @@ -74,7 +75,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
>       d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
>                                            pci_grackle_set_irq,
>                                            pci_grackle_map_irq,
> -                                         pic, 0, 4);
> +                                         pic, address_space, 0, 4);
>
>       pci_create_simple(d->host_state.bus, 0, "grackle");
>
> diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
> index 8e1f6a0..65e63dd 100644
> --- a/hw/gt64xxx.c
> +++ b/hw/gt64xxx.c
> @@ -27,6 +27,7 @@
>   #include "pci.h"
>   #include "pci_host.h"
>   #include "pc.h"
> +#include "exec-memory.h"
>
>   //#define DEBUG
>
> @@ -1092,7 +1093,8 @@ PCIBus *gt64120_register(qemu_irq *pic)
>       d = FROM_SYSBUS(GT64120State, s);
>       d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci",
>                                     gt64120_pci_set_irq, gt64120_pci_map_irq,
> -                                  pic, PCI_DEVFN(18, 0), 4);
> +                                  pic, get_system_memory(),
> +                                  PCI_DEVFN(18, 0), 4);
>       d->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, d,
>                                              DEVICE_NATIVE_ENDIAN);
>
> diff --git a/hw/pc.h b/hw/pc.h
> index 40684f4..a2de0fe 100644
> --- a/hw/pc.h
> +++ b/hw/pc.h
> @@ -178,7 +178,9 @@ int pcspk_audio_init(qemu_irq *pic);
>   struct PCII440FXState;
>   typedef struct PCII440FXState PCII440FXState;
>
> -PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, ram_addr_t ram_size);
> +PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
> +                    qemu_irq *pic, MemoryRegion *address_space,
> +                    ram_addr_t ram_size);
>   void i440fx_init_memory_mappings(PCII440FXState *d);
>
>   /* piix4.c */
> diff --git a/hw/pc_piix.c b/hw/pc_piix.c
> index f2d0476..2b9c2b1 100644
> --- a/hw/pc_piix.c
> +++ b/hw/pc_piix.c
> @@ -128,7 +128,8 @@ static void pc_init1(MemoryRegion *system_memory,
>       isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
>
>       if (pci_enabled) {
> -        pci_bus = i440fx_init(&i440fx_state,&piix3_devfn, isa_irq, ram_size);
> +        pci_bus = i440fx_init(&i440fx_state,&piix3_devfn, isa_irq,
> +                              system_memory, ram_size);
>       } else {
>           pci_bus = NULL;
>           i440fx_state = NULL;
> diff --git a/hw/pci.c b/hw/pci.c
> index b904a4e..cf16f3b 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -263,11 +263,14 @@ int pci_find_domain(const PCIBus *bus)
>   }
>
>   void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
> -                         const char *name, uint8_t devfn_min)
> +                         const char *name,
> +                         MemoryRegion *address_space,
> +                         uint8_t devfn_min)
>   {
>       qbus_create_inplace(&bus->qbus,&pci_bus_info, parent, name);
>       assert(PCI_FUNC(devfn_min) == 0);
>       bus->devfn_min = devfn_min;
> +    bus->address_space = address_space;
>
>       /* host bridge */
>       QLIST_INIT(&bus->child);
> @@ -276,13 +279,14 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
>       vmstate_register(NULL, -1,&vmstate_pcibus, bus);
>   }
>
> -PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min)
> +PCIBus *pci_bus_new(DeviceState *parent, const char *name,
> +                    MemoryRegion *address_space, uint8_t devfn_min)
>   {
>       PCIBus *bus;
>
>       bus = qemu_mallocz(sizeof(*bus));
>       bus->qbus.qdev_allocated = 1;
> -    pci_bus_new_inplace(bus, parent, name, devfn_min);
> +    pci_bus_new_inplace(bus, parent, name, address_space, devfn_min);
>       return bus;
>   }
>
> @@ -310,11 +314,13 @@ void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base)
>
>   PCIBus *pci_register_bus(DeviceState *parent, const char *name,
>                            pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
> -                         void *irq_opaque, uint8_t devfn_min, int nirq)
> +                         void *irq_opaque,
> +                         MemoryRegion *address_space,
> +                         uint8_t devfn_min, int nirq)
>   {
>       PCIBus *bus;
>
> -    bus = pci_bus_new(parent, name, devfn_min);
> +    bus = pci_bus_new(parent, name, address_space, devfn_min);
>       pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
>       return bus;
>   }
> diff --git a/hw/pci.h b/hw/pci.h
> index c220745..cfeb042 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -5,6 +5,7 @@
>   #include "qobject.h"
>
>   #include "qdev.h"
> +#include "memory.h"
>
>   /* PCI includes legacy ISA access.  */
>   #include "isa.h"
> @@ -233,15 +234,20 @@ typedef enum {
>   typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
>                                 PCIHotplugState state);
>   void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
> -                         const char *name, uint8_t devfn_min);
> -PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
> +                         const char *name,
> +                         MemoryRegion *address_space,
> +                         uint8_t devfn_min);
> +PCIBus *pci_bus_new(DeviceState *parent, const char *name,
> +                    MemoryRegion *address_space, uint8_t devfn_min);
>   void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
>                     void *irq_opaque, int nirq);
>   int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
>   void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
>   PCIBus *pci_register_bus(DeviceState *parent, const char *name,
>                            pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
> -                         void *irq_opaque, uint8_t devfn_min, int nirq);
> +                         void *irq_opaque,
> +                         MemoryRegion *address_space,
> +                         uint8_t devfn_min, int nirq);
>   void pci_device_reset(PCIDevice *dev);
>   void pci_bus_reset(PCIBus *bus);
>
> diff --git a/hw/pci_host.h b/hw/pci_host.h
> index 0a58595..05dcb66 100644
> --- a/hw/pci_host.h
> +++ b/hw/pci_host.h
> @@ -35,6 +35,7 @@ struct PCIHostState {
>       SysBusDevice busdev;
>       ReadWriteHandler conf_handler;
>       ReadWriteHandler data_handler;
> +    MemoryRegion *address_space;
>       uint32_t config_reg;
>       PCIBus *bus;
>   };
> diff --git a/hw/pci_internals.h b/hw/pci_internals.h
> index fbe1866..c3a463a 100644
> --- a/hw/pci_internals.h
> +++ b/hw/pci_internals.h
> @@ -25,6 +25,7 @@ struct PCIBus {
>       PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
>       PCIDevice *parent_dev;
>       target_phys_addr_t mem_base;
> +    MemoryRegion *address_space;
>
>       QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
>       QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
> diff --git a/hw/piix_pci.c b/hw/piix_pci.c
> index d08b31a..80d6665 100644
> --- a/hw/piix_pci.c
> +++ b/hw/piix_pci.c
> @@ -241,7 +241,9 @@ static int i440fx_initfn(PCIDevice *dev)
>   static PCIBus *i440fx_common_init(const char *device_name,
>                                     PCII440FXState **pi440fx_state,
>                                     int *piix3_devfn,
> -                                  qemu_irq *pic, ram_addr_t ram_size)
> +                                  qemu_irq *pic,
> +                                  MemoryRegion *address_space,
> +                                  ram_addr_t ram_size)
>   {
>       DeviceState *dev;
>       PCIBus *b;
> @@ -251,7 +253,8 @@ static PCIBus *i440fx_common_init(const char *device_name,
>
>       dev = qdev_create(NULL, "i440FX-pcihost");
>       s = FROM_SYSBUS(I440FXState, sysbus_from_qdev(dev));
> -    b = pci_bus_new(&s->busdev.qdev, NULL, 0);
> +    s->address_space = address_space;
> +    b = pci_bus_new(&s->busdev.qdev, NULL, s->address_space, 0);
>       s->bus = b;
>       qdev_init_nofail(dev);
>
> @@ -288,11 +291,13 @@ static PCIBus *i440fx_common_init(const char *device_name,
>   }
>
>   PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
> -                    qemu_irq *pic, ram_addr_t ram_size)
> +                    qemu_irq *pic, MemoryRegion *address_space,
> +                    ram_addr_t ram_size)
>   {
>       PCIBus *b;
>
> -    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic, ram_size);
> +    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic,
> +                           address_space, ram_size);
>       return b;
>   }
>
> diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
> index 299473c..15c24f6 100644
> --- a/hw/ppc4xx_pci.c
> +++ b/hw/ppc4xx_pci.c
> @@ -24,6 +24,7 @@
>   #include "ppc4xx.h"
>   #include "pci.h"
>   #include "pci_host.h"
> +#include "exec-memory.h"
>
>   #undef DEBUG
>   #ifdef DEBUG
> @@ -345,7 +346,9 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
>       controller->pci_state.bus = pci_register_bus(NULL, "pci",
>                                                    ppc4xx_pci_set_irq,
>                                                    ppc4xx_pci_map_irq,
> -                                                 pci_irqs, 0, 4);
> +                                                 pci_irqs,
> +                                                 get_system_memory(),
> +                                                 0, 4);
>
>       controller->pci_dev = pci_register_device(controller->pci_state.bus,
>                                                 "host bridge", sizeof(PCIDevice),
> diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
> index 68dade7..6fad20a 100644
> --- a/hw/ppc_mac.h
> +++ b/hw/ppc_mac.h
> @@ -25,6 +25,8 @@
>   #if !defined(__PPC_MAC_H__)
>   #define __PPC_MAC_H__
>
> +#include "memory.h"
> +
>   /* SMP is not enabled, for now */
>   #define MAX_CPUS 1
>
> @@ -52,11 +54,12 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
>                               int nb_cpus, qemu_irq **irqs);
>
>   /* Grackle PCI */
> -PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
> +PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
> +                         MemoryRegion *address_space);
>
>   /* UniNorth PCI */
> -PCIBus *pci_pmac_init(qemu_irq *pic);
> -PCIBus *pci_pmac_u3_init(qemu_irq *pic);
> +PCIBus *pci_pmac_init(qemu_irq *pic, MemoryRegion *address_space);
> +PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space);
>
>   /* Mac NVRAM */
>   typedef struct MacIONVRAMState MacIONVRAMState;
> diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
> index 5bce709..2c0fae8 100644
> --- a/hw/ppc_newworld.c
> +++ b/hw/ppc_newworld.c
> @@ -67,6 +67,7 @@
>   #include "kvm_ppc.h"
>   #include "hw/usb.h"
>   #include "blockdev.h"
> +#include "exec-memory.h"
>
>   #define MAX_IDE_BUS 2
>   #define CFG_ADDR 0xf0000510
> @@ -317,10 +318,10 @@ static void ppc_core99_init (ram_addr_t ram_size,
>       pic = openpic_init(NULL,&pic_mem_index, smp_cpus, openpic_irqs, NULL);
>       if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
>           /* 970 gets a U3 bus */
> -        pci_bus = pci_pmac_u3_init(pic);
> +        pci_bus = pci_pmac_u3_init(pic, get_system_memory());
>           machine_arch = ARCH_MAC99_U3;
>       } else {
> -        pci_bus = pci_pmac_init(pic);
> +        pci_bus = pci_pmac_init(pic, get_system_memory());
>           machine_arch = ARCH_MAC99;
>       }
>       /* init basic PC hardware */
> diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
> index 20cd8e1..585afd6 100644
> --- a/hw/ppc_oldworld.c
> +++ b/hw/ppc_oldworld.c
> @@ -43,6 +43,7 @@
>   #include "kvm.h"
>   #include "kvm_ppc.h"
>   #include "blockdev.h"
> +#include "exec-memory.h"
>
>   #define MAX_IDE_BUS 2
>   #define CFG_ADDR 0xf0000510
> @@ -233,7 +234,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
>           hw_error("Only 6xx bus is supported on heathrow machine\n");
>       }
>       pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
> -    pci_bus = pci_grackle_init(0xfec00000, pic);
> +    pci_bus = pci_grackle_init(0xfec00000, pic, get_system_memory());
>       pci_vga_init(pci_bus);
>
>       escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
> diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
> index 0e9cfc2..91ebe07 100644
> --- a/hw/ppc_prep.c
> +++ b/hw/ppc_prep.c
> @@ -38,6 +38,7 @@
>   #include "loader.h"
>   #include "mc146818rtc.h"
>   #include "blockdev.h"
> +#include "exec-memory.h"
>
>   //#define HARD_DEBUG_PPC_IO
>   //#define DEBUG_PPC_IO
> @@ -648,7 +649,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
>           hw_error("Only 6xx bus is supported on PREP machine\n");
>       }
>       i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
> -    pci_bus = pci_prep_init(i8259);
> +    pci_bus = pci_prep_init(i8259, get_system_memory());
>       /* Hmm, prep has no pci-isa bridge ??? */
>       isa_bus_new(NULL);
>       isa_bus_irqs(i8259);
> diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
> index fc11af4..1344539 100644
> --- a/hw/ppce500_pci.c
> +++ b/hw/ppce500_pci.c
> @@ -274,12 +274,15 @@ static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
>                                    s->reg);
>   }
>
> +#include "exec-memory.h"
> +
>   static int e500_pcihost_initfn(SysBusDevice *dev)
>   {
>       PCIHostState *h;
>       PPCE500PCIState *s;
>       PCIBus *b;
>       int i;
> +    MemoryRegion *address_space = get_system_memory();
>
>       h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
>       s = DO_UPCAST(PPCE500PCIState, pci_state, h);
> @@ -289,7 +292,8 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
>       }
>
>       b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
> -                         mpc85xx_pci_map_irq, s->irq, PCI_DEVFN(0x11, 0), 4);
> +                         mpc85xx_pci_map_irq, s->irq, address_space,
> +                         PCI_DEVFN(0x11, 0), 4);
>       s->pci_state.bus = b;
>
>       pci_create_simple(b, 0, "e500-host-bridge");
> diff --git a/hw/prep_pci.c b/hw/prep_pci.c
> index f88b825..da02f0e 100644
> --- a/hw/prep_pci.c
> +++ b/hw/prep_pci.c
> @@ -110,7 +110,7 @@ static void prep_set_irq(void *opaque, int irq_num, int level)
>       qemu_set_irq(pic[(irq_num&  1) ? 11 : 9] , level);
>   }
>
> -PCIBus *pci_prep_init(qemu_irq *pic)
> +PCIBus *pci_prep_init(qemu_irq *pic, MemoryRegion *address_space)
>   {
>       PREPPCIState *s;
>       PCIDevice *d;
> @@ -118,7 +118,8 @@ PCIBus *pci_prep_init(qemu_irq *pic)
>
>       s = qemu_mallocz(sizeof(PREPPCIState));
>       s->bus = pci_register_bus(NULL, "pci",
> -                              prep_set_irq, prep_map_irq, pic, 0, 4);
> +                              prep_set_irq, prep_map_irq, pic,
> +                              address_space, 0, 4);
>
>       pci_host_conf_register_ioport(0xcf8, s);
>
> diff --git a/hw/prep_pci.h b/hw/prep_pci.h
> index cd68512..a27368b 100644
> --- a/hw/prep_pci.h
> +++ b/hw/prep_pci.h
> @@ -2,7 +2,8 @@
>   #define QEMU_PREP_PCI_H
>
>   #include "qemu-common.h"
> +#include "memory.h"
>
> -PCIBus *pci_prep_init(qemu_irq *pic);
> +PCIBus *pci_prep_init(qemu_irq *pic, MemoryRegion *address_space);
>
>   #endif
> diff --git a/hw/sh_pci.c b/hw/sh_pci.c
> index a076cf2..0ef93a0 100644
> --- a/hw/sh_pci.c
> +++ b/hw/sh_pci.c
> @@ -26,6 +26,7 @@
>   #include "pci.h"
>   #include "pci_host.h"
>   #include "bswap.h"
> +#include "exec-memory.h"
>
>   typedef struct SHPCIState {
>       SysBusDevice busdev;
> @@ -127,7 +128,8 @@ static int sh_pci_init_device(SysBusDevice *dev)
>       }
>       s->bus = pci_register_bus(&s->busdev.qdev, "pci",
>                                 sh_pci_set_irq, sh_pci_map_irq,
> -                              s->irq, PCI_DEVFN(0, 0), 4);
> +                              s->irq, get_system_memory(),
> +                              PCI_DEVFN(0, 0), 4);
>       s->memconfig = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w,
>                                             s, DEVICE_NATIVE_ENDIAN);
>       sysbus_init_mmio_cb(dev, 0x224, sh_pci_map);
> diff --git a/hw/unin_pci.c b/hw/unin_pci.c
> index d364daa..b499523 100644
> --- a/hw/unin_pci.c
> +++ b/hw/unin_pci.c
> @@ -201,7 +201,7 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
>       return 0;
>   }
>
> -PCIBus *pci_pmac_init(qemu_irq *pic)
> +PCIBus *pci_pmac_init(qemu_irq *pic, MemoryRegion *address_space)
>   {
>       DeviceState *dev;
>       SysBusDevice *s;
> @@ -215,7 +215,8 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
>       d = FROM_SYSBUS(UNINState, s);
>       d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
>                                            pci_unin_set_irq, pci_unin_map_irq,
> -                                         pic, PCI_DEVFN(11, 0), 4);
> +                                         pic, address_space,
> +                                         PCI_DEVFN(11, 0), 4);
>
>   #if 0
>       pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
> @@ -252,7 +253,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
>       return d->host_state.bus;
>   }
>
> -PCIBus *pci_pmac_u3_init(qemu_irq *pic)
> +PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space)
>   {
>       DeviceState *dev;
>       SysBusDevice *s;
> @@ -267,7 +268,8 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic)
>
>       d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
>                                            pci_unin_set_irq, pci_unin_map_irq,
> -                                         pic, PCI_DEVFN(11, 0), 4);
> +                                         pic, address_space,
> +                                         PCI_DEVFN(11, 0), 4);
>
>       sysbus_mmio_map(s, 0, 0xf0800000);
>       sysbus_mmio_map(s, 1, 0xf0c00000);
> diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
> index 290a900..cffe387 100644
> --- a/hw/versatile_pci.c
> +++ b/hw/versatile_pci.c
> @@ -10,6 +10,7 @@
>   #include "sysbus.h"
>   #include "pci.h"
>   #include "pci_host.h"
> +#include "exec-memory.h"
>
>   typedef struct {
>       SysBusDevice busdev;
> @@ -111,6 +112,7 @@ static int pci_vpb_init(SysBusDevice *dev)
>       }
>       bus = pci_register_bus(&dev->qdev, "pci",
>                              pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
> +                           get_system_memory(),
>                              PCI_DEVFN(11, 0), 4);
>
>       /* ??? Register memory space.  */

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 20/23] pci: pass address space to pci bus when created
@ 2011-07-25 20:03     ` Anthony Liguori
  0 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 20:03 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:03 AM, Avi Kivity wrote:
> This is now done sloppily, via get_system_memory().  Eventually callers
> will be converted to stop using that.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   hw/apb_pci.c       |    2 ++
>   hw/bonito.c        |    4 +++-
>   hw/grackle_pci.c   |    5 +++--
>   hw/gt64xxx.c       |    4 +++-
>   hw/pc.h            |    4 +++-
>   hw/pc_piix.c       |    3 ++-
>   hw/pci.c           |   16 +++++++++++-----
>   hw/pci.h           |   12 +++++++++---
>   hw/pci_host.h      |    1 +
>   hw/pci_internals.h |    1 +
>   hw/piix_pci.c      |   13 +++++++++----
>   hw/ppc4xx_pci.c    |    5 ++++-
>   hw/ppc_mac.h       |    9 ++++++---
>   hw/ppc_newworld.c  |    5 +++--
>   hw/ppc_oldworld.c  |    3 ++-
>   hw/ppc_prep.c      |    3 ++-
>   hw/ppce500_pci.c   |    6 +++++-
>   hw/prep_pci.c      |    5 +++--
>   hw/prep_pci.h      |    3 ++-
>   hw/sh_pci.c        |    4 +++-
>   hw/unin_pci.c      |   10 ++++++----
>   hw/versatile_pci.c |    2 ++
>   22 files changed, 85 insertions(+), 35 deletions(-)
>
> diff --git a/hw/apb_pci.c b/hw/apb_pci.c
> index 974c87a..8b9939c 100644
> --- a/hw/apb_pci.c
> +++ b/hw/apb_pci.c
> @@ -34,6 +34,7 @@
>   #include "rwhandler.h"
>   #include "apb_pci.h"
>   #include "sysemu.h"
> +#include "exec-memory.h"
>
>   /* debug APB */
>   //#define DEBUG_APB
> @@ -346,6 +347,7 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
>
>       d->bus = pci_register_bus(&d->busdev.qdev, "pci",
>                                            pci_apb_set_irq, pci_pbm_map_irq, d,
> +                                         get_system_memory(),
>                                            0, 32);
>       pci_bus_set_mem_base(d->bus, mem_base);
>
> diff --git a/hw/bonito.c b/hw/bonito.c
> index e8c57a3..5f62dda 100644
> --- a/hw/bonito.c
> +++ b/hw/bonito.c
> @@ -42,6 +42,7 @@
>   #include "mips.h"
>   #include "pci_host.h"
>   #include "sysemu.h"
> +#include "exec-memory.h"
>
>   //#define DEBUG_BONITO
>
> @@ -773,7 +774,8 @@ PCIBus *bonito_init(qemu_irq *pic)
>       dev = qdev_create(NULL, "Bonito-pcihost");
>       pcihost = FROM_SYSBUS(BonitoState, sysbus_from_qdev(dev));
>       b = pci_register_bus(&pcihost->busdev.qdev, "pci", pci_bonito_set_irq,
> -                         pci_bonito_map_irq, pic, 0x28, 32);
> +                         pci_bonito_map_irq, pic, get_system_memory(),
> +                         0x28, 32);
>       pcihost->bus = b;
>       qdev_init_nofail(dev);
>
> diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
> index cee07e0..da67cf9 100644
> --- a/hw/grackle_pci.c
> +++ b/hw/grackle_pci.c
> @@ -61,7 +61,8 @@ static void pci_grackle_reset(void *opaque)
>   {
>   }
>
> -PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
> +PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
> +                         MemoryRegion *address_space)
>   {
>       DeviceState *dev;
>       SysBusDevice *s;
> @@ -74,7 +75,7 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic)
>       d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
>                                            pci_grackle_set_irq,
>                                            pci_grackle_map_irq,
> -                                         pic, 0, 4);
> +                                         pic, address_space, 0, 4);
>
>       pci_create_simple(d->host_state.bus, 0, "grackle");
>
> diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
> index 8e1f6a0..65e63dd 100644
> --- a/hw/gt64xxx.c
> +++ b/hw/gt64xxx.c
> @@ -27,6 +27,7 @@
>   #include "pci.h"
>   #include "pci_host.h"
>   #include "pc.h"
> +#include "exec-memory.h"
>
>   //#define DEBUG
>
> @@ -1092,7 +1093,8 @@ PCIBus *gt64120_register(qemu_irq *pic)
>       d = FROM_SYSBUS(GT64120State, s);
>       d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci",
>                                     gt64120_pci_set_irq, gt64120_pci_map_irq,
> -                                  pic, PCI_DEVFN(18, 0), 4);
> +                                  pic, get_system_memory(),
> +                                  PCI_DEVFN(18, 0), 4);
>       d->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, d,
>                                              DEVICE_NATIVE_ENDIAN);
>
> diff --git a/hw/pc.h b/hw/pc.h
> index 40684f4..a2de0fe 100644
> --- a/hw/pc.h
> +++ b/hw/pc.h
> @@ -178,7 +178,9 @@ int pcspk_audio_init(qemu_irq *pic);
>   struct PCII440FXState;
>   typedef struct PCII440FXState PCII440FXState;
>
> -PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, ram_addr_t ram_size);
> +PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn,
> +                    qemu_irq *pic, MemoryRegion *address_space,
> +                    ram_addr_t ram_size);
>   void i440fx_init_memory_mappings(PCII440FXState *d);
>
>   /* piix4.c */
> diff --git a/hw/pc_piix.c b/hw/pc_piix.c
> index f2d0476..2b9c2b1 100644
> --- a/hw/pc_piix.c
> +++ b/hw/pc_piix.c
> @@ -128,7 +128,8 @@ static void pc_init1(MemoryRegion *system_memory,
>       isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
>
>       if (pci_enabled) {
> -        pci_bus = i440fx_init(&i440fx_state,&piix3_devfn, isa_irq, ram_size);
> +        pci_bus = i440fx_init(&i440fx_state,&piix3_devfn, isa_irq,
> +                              system_memory, ram_size);
>       } else {
>           pci_bus = NULL;
>           i440fx_state = NULL;
> diff --git a/hw/pci.c b/hw/pci.c
> index b904a4e..cf16f3b 100644
> --- a/hw/pci.c
> +++ b/hw/pci.c
> @@ -263,11 +263,14 @@ int pci_find_domain(const PCIBus *bus)
>   }
>
>   void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
> -                         const char *name, uint8_t devfn_min)
> +                         const char *name,
> +                         MemoryRegion *address_space,
> +                         uint8_t devfn_min)
>   {
>       qbus_create_inplace(&bus->qbus,&pci_bus_info, parent, name);
>       assert(PCI_FUNC(devfn_min) == 0);
>       bus->devfn_min = devfn_min;
> +    bus->address_space = address_space;
>
>       /* host bridge */
>       QLIST_INIT(&bus->child);
> @@ -276,13 +279,14 @@ void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
>       vmstate_register(NULL, -1,&vmstate_pcibus, bus);
>   }
>
> -PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min)
> +PCIBus *pci_bus_new(DeviceState *parent, const char *name,
> +                    MemoryRegion *address_space, uint8_t devfn_min)
>   {
>       PCIBus *bus;
>
>       bus = qemu_mallocz(sizeof(*bus));
>       bus->qbus.qdev_allocated = 1;
> -    pci_bus_new_inplace(bus, parent, name, devfn_min);
> +    pci_bus_new_inplace(bus, parent, name, address_space, devfn_min);
>       return bus;
>   }
>
> @@ -310,11 +314,13 @@ void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base)
>
>   PCIBus *pci_register_bus(DeviceState *parent, const char *name,
>                            pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
> -                         void *irq_opaque, uint8_t devfn_min, int nirq)
> +                         void *irq_opaque,
> +                         MemoryRegion *address_space,
> +                         uint8_t devfn_min, int nirq)
>   {
>       PCIBus *bus;
>
> -    bus = pci_bus_new(parent, name, devfn_min);
> +    bus = pci_bus_new(parent, name, address_space, devfn_min);
>       pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
>       return bus;
>   }
> diff --git a/hw/pci.h b/hw/pci.h
> index c220745..cfeb042 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -5,6 +5,7 @@
>   #include "qobject.h"
>
>   #include "qdev.h"
> +#include "memory.h"
>
>   /* PCI includes legacy ISA access.  */
>   #include "isa.h"
> @@ -233,15 +234,20 @@ typedef enum {
>   typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
>                                 PCIHotplugState state);
>   void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
> -                         const char *name, uint8_t devfn_min);
> -PCIBus *pci_bus_new(DeviceState *parent, const char *name, uint8_t devfn_min);
> +                         const char *name,
> +                         MemoryRegion *address_space,
> +                         uint8_t devfn_min);
> +PCIBus *pci_bus_new(DeviceState *parent, const char *name,
> +                    MemoryRegion *address_space, uint8_t devfn_min);
>   void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
>                     void *irq_opaque, int nirq);
>   int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
>   void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
>   PCIBus *pci_register_bus(DeviceState *parent, const char *name,
>                            pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
> -                         void *irq_opaque, uint8_t devfn_min, int nirq);
> +                         void *irq_opaque,
> +                         MemoryRegion *address_space,
> +                         uint8_t devfn_min, int nirq);
>   void pci_device_reset(PCIDevice *dev);
>   void pci_bus_reset(PCIBus *bus);
>
> diff --git a/hw/pci_host.h b/hw/pci_host.h
> index 0a58595..05dcb66 100644
> --- a/hw/pci_host.h
> +++ b/hw/pci_host.h
> @@ -35,6 +35,7 @@ struct PCIHostState {
>       SysBusDevice busdev;
>       ReadWriteHandler conf_handler;
>       ReadWriteHandler data_handler;
> +    MemoryRegion *address_space;
>       uint32_t config_reg;
>       PCIBus *bus;
>   };
> diff --git a/hw/pci_internals.h b/hw/pci_internals.h
> index fbe1866..c3a463a 100644
> --- a/hw/pci_internals.h
> +++ b/hw/pci_internals.h
> @@ -25,6 +25,7 @@ struct PCIBus {
>       PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
>       PCIDevice *parent_dev;
>       target_phys_addr_t mem_base;
> +    MemoryRegion *address_space;
>
>       QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
>       QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
> diff --git a/hw/piix_pci.c b/hw/piix_pci.c
> index d08b31a..80d6665 100644
> --- a/hw/piix_pci.c
> +++ b/hw/piix_pci.c
> @@ -241,7 +241,9 @@ static int i440fx_initfn(PCIDevice *dev)
>   static PCIBus *i440fx_common_init(const char *device_name,
>                                     PCII440FXState **pi440fx_state,
>                                     int *piix3_devfn,
> -                                  qemu_irq *pic, ram_addr_t ram_size)
> +                                  qemu_irq *pic,
> +                                  MemoryRegion *address_space,
> +                                  ram_addr_t ram_size)
>   {
>       DeviceState *dev;
>       PCIBus *b;
> @@ -251,7 +253,8 @@ static PCIBus *i440fx_common_init(const char *device_name,
>
>       dev = qdev_create(NULL, "i440FX-pcihost");
>       s = FROM_SYSBUS(I440FXState, sysbus_from_qdev(dev));
> -    b = pci_bus_new(&s->busdev.qdev, NULL, 0);
> +    s->address_space = address_space;
> +    b = pci_bus_new(&s->busdev.qdev, NULL, s->address_space, 0);
>       s->bus = b;
>       qdev_init_nofail(dev);
>
> @@ -288,11 +291,13 @@ static PCIBus *i440fx_common_init(const char *device_name,
>   }
>
>   PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn,
> -                    qemu_irq *pic, ram_addr_t ram_size)
> +                    qemu_irq *pic, MemoryRegion *address_space,
> +                    ram_addr_t ram_size)
>   {
>       PCIBus *b;
>
> -    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic, ram_size);
> +    b = i440fx_common_init("i440FX", pi440fx_state, piix3_devfn, pic,
> +                           address_space, ram_size);
>       return b;
>   }
>
> diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
> index 299473c..15c24f6 100644
> --- a/hw/ppc4xx_pci.c
> +++ b/hw/ppc4xx_pci.c
> @@ -24,6 +24,7 @@
>   #include "ppc4xx.h"
>   #include "pci.h"
>   #include "pci_host.h"
> +#include "exec-memory.h"
>
>   #undef DEBUG
>   #ifdef DEBUG
> @@ -345,7 +346,9 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4],
>       controller->pci_state.bus = pci_register_bus(NULL, "pci",
>                                                    ppc4xx_pci_set_irq,
>                                                    ppc4xx_pci_map_irq,
> -                                                 pci_irqs, 0, 4);
> +                                                 pci_irqs,
> +                                                 get_system_memory(),
> +                                                 0, 4);
>
>       controller->pci_dev = pci_register_device(controller->pci_state.bus,
>                                                 "host bridge", sizeof(PCIDevice),
> diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
> index 68dade7..6fad20a 100644
> --- a/hw/ppc_mac.h
> +++ b/hw/ppc_mac.h
> @@ -25,6 +25,8 @@
>   #if !defined(__PPC_MAC_H__)
>   #define __PPC_MAC_H__
>
> +#include "memory.h"
> +
>   /* SMP is not enabled, for now */
>   #define MAX_CPUS 1
>
> @@ -52,11 +54,12 @@ qemu_irq *heathrow_pic_init(int *pmem_index,
>                               int nb_cpus, qemu_irq **irqs);
>
>   /* Grackle PCI */
> -PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic);
> +PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
> +                         MemoryRegion *address_space);
>
>   /* UniNorth PCI */
> -PCIBus *pci_pmac_init(qemu_irq *pic);
> -PCIBus *pci_pmac_u3_init(qemu_irq *pic);
> +PCIBus *pci_pmac_init(qemu_irq *pic, MemoryRegion *address_space);
> +PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space);
>
>   /* Mac NVRAM */
>   typedef struct MacIONVRAMState MacIONVRAMState;
> diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
> index 5bce709..2c0fae8 100644
> --- a/hw/ppc_newworld.c
> +++ b/hw/ppc_newworld.c
> @@ -67,6 +67,7 @@
>   #include "kvm_ppc.h"
>   #include "hw/usb.h"
>   #include "blockdev.h"
> +#include "exec-memory.h"
>
>   #define MAX_IDE_BUS 2
>   #define CFG_ADDR 0xf0000510
> @@ -317,10 +318,10 @@ static void ppc_core99_init (ram_addr_t ram_size,
>       pic = openpic_init(NULL,&pic_mem_index, smp_cpus, openpic_irqs, NULL);
>       if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
>           /* 970 gets a U3 bus */
> -        pci_bus = pci_pmac_u3_init(pic);
> +        pci_bus = pci_pmac_u3_init(pic, get_system_memory());
>           machine_arch = ARCH_MAC99_U3;
>       } else {
> -        pci_bus = pci_pmac_init(pic);
> +        pci_bus = pci_pmac_init(pic, get_system_memory());
>           machine_arch = ARCH_MAC99;
>       }
>       /* init basic PC hardware */
> diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
> index 20cd8e1..585afd6 100644
> --- a/hw/ppc_oldworld.c
> +++ b/hw/ppc_oldworld.c
> @@ -43,6 +43,7 @@
>   #include "kvm.h"
>   #include "kvm_ppc.h"
>   #include "blockdev.h"
> +#include "exec-memory.h"
>
>   #define MAX_IDE_BUS 2
>   #define CFG_ADDR 0xf0000510
> @@ -233,7 +234,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
>           hw_error("Only 6xx bus is supported on heathrow machine\n");
>       }
>       pic = heathrow_pic_init(&pic_mem_index, 1, heathrow_irqs);
> -    pci_bus = pci_grackle_init(0xfec00000, pic);
> +    pci_bus = pci_grackle_init(0xfec00000, pic, get_system_memory());
>       pci_vga_init(pci_bus);
>
>       escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
> diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
> index 0e9cfc2..91ebe07 100644
> --- a/hw/ppc_prep.c
> +++ b/hw/ppc_prep.c
> @@ -38,6 +38,7 @@
>   #include "loader.h"
>   #include "mc146818rtc.h"
>   #include "blockdev.h"
> +#include "exec-memory.h"
>
>   //#define HARD_DEBUG_PPC_IO
>   //#define DEBUG_PPC_IO
> @@ -648,7 +649,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
>           hw_error("Only 6xx bus is supported on PREP machine\n");
>       }
>       i8259 = i8259_init(first_cpu->irq_inputs[PPC6xx_INPUT_INT]);
> -    pci_bus = pci_prep_init(i8259);
> +    pci_bus = pci_prep_init(i8259, get_system_memory());
>       /* Hmm, prep has no pci-isa bridge ??? */
>       isa_bus_new(NULL);
>       isa_bus_irqs(i8259);
> diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
> index fc11af4..1344539 100644
> --- a/hw/ppce500_pci.c
> +++ b/hw/ppce500_pci.c
> @@ -274,12 +274,15 @@ static void e500_pci_map(SysBusDevice *dev, target_phys_addr_t base)
>                                    s->reg);
>   }
>
> +#include "exec-memory.h"
> +
>   static int e500_pcihost_initfn(SysBusDevice *dev)
>   {
>       PCIHostState *h;
>       PPCE500PCIState *s;
>       PCIBus *b;
>       int i;
> +    MemoryRegion *address_space = get_system_memory();
>
>       h = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
>       s = DO_UPCAST(PPCE500PCIState, pci_state, h);
> @@ -289,7 +292,8 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
>       }
>
>       b = pci_register_bus(&s->pci_state.busdev.qdev, NULL, mpc85xx_pci_set_irq,
> -                         mpc85xx_pci_map_irq, s->irq, PCI_DEVFN(0x11, 0), 4);
> +                         mpc85xx_pci_map_irq, s->irq, address_space,
> +                         PCI_DEVFN(0x11, 0), 4);
>       s->pci_state.bus = b;
>
>       pci_create_simple(b, 0, "e500-host-bridge");
> diff --git a/hw/prep_pci.c b/hw/prep_pci.c
> index f88b825..da02f0e 100644
> --- a/hw/prep_pci.c
> +++ b/hw/prep_pci.c
> @@ -110,7 +110,7 @@ static void prep_set_irq(void *opaque, int irq_num, int level)
>       qemu_set_irq(pic[(irq_num&  1) ? 11 : 9] , level);
>   }
>
> -PCIBus *pci_prep_init(qemu_irq *pic)
> +PCIBus *pci_prep_init(qemu_irq *pic, MemoryRegion *address_space)
>   {
>       PREPPCIState *s;
>       PCIDevice *d;
> @@ -118,7 +118,8 @@ PCIBus *pci_prep_init(qemu_irq *pic)
>
>       s = qemu_mallocz(sizeof(PREPPCIState));
>       s->bus = pci_register_bus(NULL, "pci",
> -                              prep_set_irq, prep_map_irq, pic, 0, 4);
> +                              prep_set_irq, prep_map_irq, pic,
> +                              address_space, 0, 4);
>
>       pci_host_conf_register_ioport(0xcf8, s);
>
> diff --git a/hw/prep_pci.h b/hw/prep_pci.h
> index cd68512..a27368b 100644
> --- a/hw/prep_pci.h
> +++ b/hw/prep_pci.h
> @@ -2,7 +2,8 @@
>   #define QEMU_PREP_PCI_H
>
>   #include "qemu-common.h"
> +#include "memory.h"
>
> -PCIBus *pci_prep_init(qemu_irq *pic);
> +PCIBus *pci_prep_init(qemu_irq *pic, MemoryRegion *address_space);
>
>   #endif
> diff --git a/hw/sh_pci.c b/hw/sh_pci.c
> index a076cf2..0ef93a0 100644
> --- a/hw/sh_pci.c
> +++ b/hw/sh_pci.c
> @@ -26,6 +26,7 @@
>   #include "pci.h"
>   #include "pci_host.h"
>   #include "bswap.h"
> +#include "exec-memory.h"
>
>   typedef struct SHPCIState {
>       SysBusDevice busdev;
> @@ -127,7 +128,8 @@ static int sh_pci_init_device(SysBusDevice *dev)
>       }
>       s->bus = pci_register_bus(&s->busdev.qdev, "pci",
>                                 sh_pci_set_irq, sh_pci_map_irq,
> -                              s->irq, PCI_DEVFN(0, 0), 4);
> +                              s->irq, get_system_memory(),
> +                              PCI_DEVFN(0, 0), 4);
>       s->memconfig = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w,
>                                             s, DEVICE_NATIVE_ENDIAN);
>       sysbus_init_mmio_cb(dev, 0x224, sh_pci_map);
> diff --git a/hw/unin_pci.c b/hw/unin_pci.c
> index d364daa..b499523 100644
> --- a/hw/unin_pci.c
> +++ b/hw/unin_pci.c
> @@ -201,7 +201,7 @@ static int pci_unin_internal_init_device(SysBusDevice *dev)
>       return 0;
>   }
>
> -PCIBus *pci_pmac_init(qemu_irq *pic)
> +PCIBus *pci_pmac_init(qemu_irq *pic, MemoryRegion *address_space)
>   {
>       DeviceState *dev;
>       SysBusDevice *s;
> @@ -215,7 +215,8 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
>       d = FROM_SYSBUS(UNINState, s);
>       d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
>                                            pci_unin_set_irq, pci_unin_map_irq,
> -                                         pic, PCI_DEVFN(11, 0), 4);
> +                                         pic, address_space,
> +                                         PCI_DEVFN(11, 0), 4);
>
>   #if 0
>       pci_create_simple(d->host_state.bus, PCI_DEVFN(11, 0), "uni-north");
> @@ -252,7 +253,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
>       return d->host_state.bus;
>   }
>
> -PCIBus *pci_pmac_u3_init(qemu_irq *pic)
> +PCIBus *pci_pmac_u3_init(qemu_irq *pic, MemoryRegion *address_space)
>   {
>       DeviceState *dev;
>       SysBusDevice *s;
> @@ -267,7 +268,8 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic)
>
>       d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
>                                            pci_unin_set_irq, pci_unin_map_irq,
> -                                         pic, PCI_DEVFN(11, 0), 4);
> +                                         pic, address_space,
> +                                         PCI_DEVFN(11, 0), 4);
>
>       sysbus_mmio_map(s, 0, 0xf0800000);
>       sysbus_mmio_map(s, 1, 0xf0c00000);
> diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
> index 290a900..cffe387 100644
> --- a/hw/versatile_pci.c
> +++ b/hw/versatile_pci.c
> @@ -10,6 +10,7 @@
>   #include "sysbus.h"
>   #include "pci.h"
>   #include "pci_host.h"
> +#include "exec-memory.h"
>
>   typedef struct {
>       SysBusDevice busdev;
> @@ -111,6 +112,7 @@ static int pci_vpb_init(SysBusDevice *dev)
>       }
>       bus = pci_register_bus(&dev->qdev, "pci",
>                              pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
> +                           get_system_memory(),
>                              PCI_DEVFN(11, 0), 4);
>
>       /* ??? Register memory space.  */

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH 21/23] pci: add MemoryRegion based BAR management API
  2011-07-25 14:03   ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 20:20     ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 20:20 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:03 AM, Avi Kivity wrote:
> Allow registering a BAR using a MemoryRegion.  Once all users are converted,
> pci_register_bar() and pci_register_bar_simple() will be removed.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

> diff --git a/hw/pci.h b/hw/pci.h
> index cfeb042..c51156d 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -94,6 +94,7 @@ typedef struct PCIIORegion {
>       uint8_t type;
>       PCIMapIORegionFunc *map_func;
>       ram_addr_t ram_addr;
> +    MemoryRegion *memory;
>   } PCIIORegion;
>
>   #define PCI_ROM_SLOT 6
> @@ -204,6 +205,8 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
>                               PCIMapIORegionFunc *map_func);
>   void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
>                                pcibus_t size, uint8_t attr, ram_addr_t ram_addr);
> +void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
> +                             uint8_t attr, MemoryRegion *memory);

This ends up being a very nice API.  I had always thought this should be 
a PCI specific set of callbacks but I do see the benefits of having the 
callbacks be generic.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

One thing I'm curious about, what's the symmetric view of this API?

Would you see a device doing something like:

memory_region_read(&dev->pci_bus->memory, addr, &data, sizeof(data))

?

Regards,

Anthony Liguori

>   int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
>                          uint8_t offset, uint8_t size);

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 21/23] pci: add MemoryRegion based BAR management API
@ 2011-07-25 20:20     ` Anthony Liguori
  0 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 20:20 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:03 AM, Avi Kivity wrote:
> Allow registering a BAR using a MemoryRegion.  Once all users are converted,
> pci_register_bar() and pci_register_bar_simple() will be removed.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

> diff --git a/hw/pci.h b/hw/pci.h
> index cfeb042..c51156d 100644
> --- a/hw/pci.h
> +++ b/hw/pci.h
> @@ -94,6 +94,7 @@ typedef struct PCIIORegion {
>       uint8_t type;
>       PCIMapIORegionFunc *map_func;
>       ram_addr_t ram_addr;
> +    MemoryRegion *memory;
>   } PCIIORegion;
>
>   #define PCI_ROM_SLOT 6
> @@ -204,6 +205,8 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
>                               PCIMapIORegionFunc *map_func);
>   void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
>                                pcibus_t size, uint8_t attr, ram_addr_t ram_addr);
> +void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
> +                             uint8_t attr, MemoryRegion *memory);

This ends up being a very nice API.  I had always thought this should be 
a PCI specific set of callbacks but I do see the benefits of having the 
callbacks be generic.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

One thing I'm curious about, what's the symmetric view of this API?

Would you see a device doing something like:

memory_region_read(&dev->pci_bus->memory, addr, &data, sizeof(data))

?

Regards,

Anthony Liguori

>   int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
>                          uint8_t offset, uint8_t size);

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH 22/23] sysbus: add MemoryRegion based memory management API
  2011-07-25 14:03   ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 20:21     ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 20:21 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:03 AM, Avi Kivity wrote:
> Allow registering sysbus device memory using a MemoryRegion.  Once all users
> are converted, sysbus_init_mmio() and sysbus_init_mmio_cb() will be removed.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   hw/sysbus.c |   27 ++++++++++++++++++++++++---
>   hw/sysbus.h |    3 +++
>   2 files changed, 27 insertions(+), 3 deletions(-)
>
> diff --git a/hw/sysbus.c b/hw/sysbus.c
> index 2e22be7..ea442ac 100644
> --- a/hw/sysbus.c
> +++ b/hw/sysbus.c
> @@ -19,6 +19,7 @@
>
>   #include "sysbus.h"
>   #include "monitor.h"
> +#include "exec-memory.h"
>
>   static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
>   static char *sysbus_get_fw_dev_path(DeviceState *dev);
> @@ -49,11 +50,20 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
>       }
>       if (dev->mmio[n].addr != (target_phys_addr_t)-1) {
>           /* Unregister previous mapping.  */
> -        cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
> -                                     IO_MEM_UNASSIGNED);
> +        if (dev->mmio[n].memory) {
> +            memory_region_del_subregion(get_system_memory(),
> +                                        dev->mmio[n].memory);
> +        } else {
> +            cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
> +                                         IO_MEM_UNASSIGNED);
> +        }
>       }
>       dev->mmio[n].addr = addr;
> -    if (dev->mmio[n].cb) {
> +    if (dev->mmio[n].memory) {
> +        memory_region_add_subregion(get_system_memory(),
> +                                    addr,
> +                                    dev->mmio[n].memory);
> +    } else if (dev->mmio[n].cb) {
>           dev->mmio[n].cb(dev, addr);
>       } else {
>           cpu_register_physical_memory(addr, dev->mmio[n].size,
> @@ -107,6 +117,17 @@ void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
>       dev->mmio[n].cb = cb;
>   }
>
> +void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory)
> +{
> +    int n;
> +
> +    assert(dev->num_mmio<  QDEV_MAX_MMIO);
> +    n = dev->num_mmio++;
> +    dev->mmio[n].addr = -1;
> +    dev->mmio[n].size = memory_region_size(memory);
> +    dev->mmio[n].memory = memory;
> +}
> +
>   void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
>   {
>       pio_addr_t i;
> diff --git a/hw/sysbus.h b/hw/sysbus.h
> index 4e8cb16..5f62e2d 100644
> --- a/hw/sysbus.h
> +++ b/hw/sysbus.h
> @@ -4,6 +4,7 @@
>   /* Devices attached directly to the main system bus.  */
>
>   #include "qdev.h"
> +#include "memory.h"
>
>   #define QDEV_MAX_MMIO 32
>   #define QDEV_MAX_PIO 32
> @@ -23,6 +24,7 @@ struct SysBusDevice {
>           target_phys_addr_t size;
>           mmio_mapfunc cb;
>           ram_addr_t iofunc;
> +        MemoryRegion *memory;
>       } mmio[QDEV_MAX_MMIO];
>       int num_pio;
>       pio_addr_t pio[QDEV_MAX_PIO];
> @@ -46,6 +48,7 @@ void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size,
>                         ram_addr_t iofunc);
>   void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
>                               mmio_mapfunc cb);
> +void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory);
>   void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
>   void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target);
>   void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 22/23] sysbus: add MemoryRegion based memory management API
@ 2011-07-25 20:21     ` Anthony Liguori
  0 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 20:21 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:03 AM, Avi Kivity wrote:
> Allow registering sysbus device memory using a MemoryRegion.  Once all users
> are converted, sysbus_init_mmio() and sysbus_init_mmio_cb() will be removed.
>
> Signed-off-by: Avi Kivity<avi@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   hw/sysbus.c |   27 ++++++++++++++++++++++++---
>   hw/sysbus.h |    3 +++
>   2 files changed, 27 insertions(+), 3 deletions(-)
>
> diff --git a/hw/sysbus.c b/hw/sysbus.c
> index 2e22be7..ea442ac 100644
> --- a/hw/sysbus.c
> +++ b/hw/sysbus.c
> @@ -19,6 +19,7 @@
>
>   #include "sysbus.h"
>   #include "monitor.h"
> +#include "exec-memory.h"
>
>   static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
>   static char *sysbus_get_fw_dev_path(DeviceState *dev);
> @@ -49,11 +50,20 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)
>       }
>       if (dev->mmio[n].addr != (target_phys_addr_t)-1) {
>           /* Unregister previous mapping.  */
> -        cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
> -                                     IO_MEM_UNASSIGNED);
> +        if (dev->mmio[n].memory) {
> +            memory_region_del_subregion(get_system_memory(),
> +                                        dev->mmio[n].memory);
> +        } else {
> +            cpu_register_physical_memory(dev->mmio[n].addr, dev->mmio[n].size,
> +                                         IO_MEM_UNASSIGNED);
> +        }
>       }
>       dev->mmio[n].addr = addr;
> -    if (dev->mmio[n].cb) {
> +    if (dev->mmio[n].memory) {
> +        memory_region_add_subregion(get_system_memory(),
> +                                    addr,
> +                                    dev->mmio[n].memory);
> +    } else if (dev->mmio[n].cb) {
>           dev->mmio[n].cb(dev, addr);
>       } else {
>           cpu_register_physical_memory(addr, dev->mmio[n].size,
> @@ -107,6 +117,17 @@ void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
>       dev->mmio[n].cb = cb;
>   }
>
> +void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory)
> +{
> +    int n;
> +
> +    assert(dev->num_mmio<  QDEV_MAX_MMIO);
> +    n = dev->num_mmio++;
> +    dev->mmio[n].addr = -1;
> +    dev->mmio[n].size = memory_region_size(memory);
> +    dev->mmio[n].memory = memory;
> +}
> +
>   void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size)
>   {
>       pio_addr_t i;
> diff --git a/hw/sysbus.h b/hw/sysbus.h
> index 4e8cb16..5f62e2d 100644
> --- a/hw/sysbus.h
> +++ b/hw/sysbus.h
> @@ -4,6 +4,7 @@
>   /* Devices attached directly to the main system bus.  */
>
>   #include "qdev.h"
> +#include "memory.h"
>
>   #define QDEV_MAX_MMIO 32
>   #define QDEV_MAX_PIO 32
> @@ -23,6 +24,7 @@ struct SysBusDevice {
>           target_phys_addr_t size;
>           mmio_mapfunc cb;
>           ram_addr_t iofunc;
> +        MemoryRegion *memory;
>       } mmio[QDEV_MAX_MMIO];
>       int num_pio;
>       pio_addr_t pio[QDEV_MAX_PIO];
> @@ -46,6 +48,7 @@ void sysbus_init_mmio(SysBusDevice *dev, target_phys_addr_t size,
>                         ram_addr_t iofunc);
>   void sysbus_init_mmio_cb(SysBusDevice *dev, target_phys_addr_t size,
>                               mmio_mapfunc cb);
> +void sysbus_init_mmio_region(SysBusDevice *dev, MemoryRegion *memory);
>   void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p);
>   void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target);
>   void sysbus_init_ioports(SysBusDevice *dev, pio_addr_t ioport, pio_addr_t size);

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 23/23] usb-ohci: convert to MemoryRegion
  2011-07-25 14:03   ` [Qemu-devel] " Avi Kivity
  (?)
@ 2011-07-25 20:22   ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 20:22 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:03 AM, Avi Kivity wrote:
> Signed-off-by: Avi Kivity<avi@redhat.com>

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>

Regards,

Anthony Liguori

> ---
>   hw/usb-ohci.c |   42 +++++++++++++++++-------------------------
>   1 files changed, 17 insertions(+), 25 deletions(-)
>
> diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
> index 8491d59..337b250 100644
> --- a/hw/usb-ohci.c
> +++ b/hw/usb-ohci.c
> @@ -62,7 +62,7 @@ typedef struct OHCIPort {
>   typedef struct {
>       USBBus bus;
>       qemu_irq irq;
> -    int mem;
> +    MemoryRegion mem;
>       int num_ports;
>       const char *name;
>
> @@ -1440,13 +1440,13 @@ static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val)
>       return;
>   }
>
> -static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
> +static uint64_t ohci_mem_read(void *opaque,
> +                              target_phys_addr_t addr,
> +                              unsigned size)
>   {
> -    OHCIState *ohci = ptr;
> +    OHCIState *ohci = opaque;
>       uint32_t retval;
>
> -    addr&= 0xff;
> -
>       /* Only aligned reads are allowed on OHCI */
>       if (addr&  3) {
>           fprintf(stderr, "usb-ohci: Mis-aligned read\n");
> @@ -1563,11 +1563,12 @@ static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
>       return retval;
>   }
>
> -static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
> +static void ohci_mem_write(void *opaque,
> +                           target_phys_addr_t addr,
> +                           uint64_t val,
> +                           unsigned size)
>   {
> -    OHCIState *ohci = ptr;
> -
> -    addr&= 0xff;
> +    OHCIState *ohci = opaque;
>
>       /* Only aligned reads are allowed on OHCI */
>       if (addr&  3) {
> @@ -1697,18 +1698,10 @@ static void ohci_async_cancel_device(OHCIState *ohci, USBDevice *dev)
>       }
>   }
>
> -/* Only dword reads are defined on OHCI register space */
> -static CPUReadMemoryFunc * const ohci_readfn[3]={
> -    ohci_mem_read,
> -    ohci_mem_read,
> -    ohci_mem_read
> -};
> -
> -/* Only dword writes are defined on OHCI register space */
> -static CPUWriteMemoryFunc * const ohci_writefn[3]={
> -    ohci_mem_write,
> -    ohci_mem_write,
> -    ohci_mem_write
> +static const MemoryRegionOps ohci_mem_ops = {
> +    .read = ohci_mem_read,
> +    .write = ohci_mem_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
>   };
>
>   static USBPortOps ohci_port_ops = {
> @@ -1764,8 +1757,7 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState *dev,
>           }
>       }
>
> -    ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci,
> -                                       DEVICE_LITTLE_ENDIAN);
> +    memory_region_init_io(&ohci->mem,&ohci_mem_ops, ohci, "ohci", 256);
>       ohci->localmem_base = localmem_base;
>
>       ohci->name = dev->info->name;
> @@ -1799,7 +1791,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
>       ohci->state.irq = ohci->pci_dev.irq[0];
>
>       /* TODO: avoid cast below by using dev */
> -    pci_register_bar_simple(&ohci->pci_dev, 0, 256, 0, ohci->state.mem);
> +    pci_register_bar_region(&ohci->pci_dev, 0, 0,&ohci->state.mem);
>       return 0;
>   }
>
> @@ -1822,7 +1814,7 @@ static int ohci_init_pxa(SysBusDevice *dev)
>       /* Cannot fail as we pass NULL for masterbus */
>       usb_ohci_init(&s->ohci,&dev->qdev, s->num_ports, s->dma_offset, NULL, 0);
>       sysbus_init_irq(dev,&s->ohci.irq);
> -    sysbus_init_mmio(dev, 0x1000, s->ohci.mem);
> +    sysbus_init_mmio_region(dev,&s->ohci.mem);
>
>       return 0;
>   }


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH 00/23] Memory API, batch 1
  2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
@ 2011-07-25 20:23   ` Anthony Liguori
  -1 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 20:23 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> This patchset contains the core of the memory API, with one device
> (usb-ohci) coverted for reference.  The API is currently implemented on
> top of the old ram_addr_t/cpu_register_physical_memory() API, but the plan
> is to make it standalone later.
>
> The goals of the API are:
>   - correctness: by modelling the memory hierarchy, things like the 440FX PAM
>     registers and movable, overlapping PCI BARs can be modelled accurately.
>   - efficiency: by maintaining an object tree describing guest memory, we
>     can eventually get rid of the page descriptor array
>   - security: by having more information available declaratively, we reduce
>     coding errors that may be exploited by malicious guests
>
> Also available from
>
>    git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git
>       refs/tags/memory-region-batch-1

Very nice series.

Despite my lack of exciting over ioeventfd and coalescing, if you fix 
the few minor comments, this should be a no brainer to merge.

Regards,

Anthony Liguori

>
> Avi Kivity (23):
>    Hierarchical memory region API
>    memory: implement dirty tracking
>    memory: merge adjacent segments of a single memory region
>    Internal interfaces for memory API
>    memory: abstract address space operations
>    memory: rename MemoryRegion::has_ram_addr to ::terminates
>    memory: late initialization of ram_addr
>    memory:  I/O address space support
>    memory: add backward compatibility for old portio registration
>    memory: add backward compatibility for old mmio registration
>    memory: add ioeventfd support
>    memory: separate building the final memory map into two steps
>    memory: document the memory API
>    memory: transaction API
>    exec.c: initialize memory map
>    ioport: register ranges by byte aligned addresses always
>    pc: grab system_memory
>    pc: convert pc_memory_init() to memory API
>    pc: move global memory map out of pc_init1() and into its callers
>    pci: pass address space to pci bus when created
>    pci: add MemoryRegion based BAR management API
>    sysbus: add MemoryRegion based memory management API
>    usb-ohci: convert to MemoryRegion
>
>   Makefile.target    |    1 +
>   docs/memory.txt    |  172 ++++++++
>   exec-memory.h      |   26 ++
>   exec.c             |   19 +
>   hw/apb_pci.c       |    2 +
>   hw/bonito.c        |    4 +-
>   hw/grackle_pci.c   |    5 +-
>   hw/gt64xxx.c       |    4 +-
>   hw/pc.c            |   62 ++-
>   hw/pc.h            |    9 +-
>   hw/pc_piix.c       |   20 +-
>   hw/pci.c           |   63 +++-
>   hw/pci.h           |   15 +-
>   hw/pci_host.h      |    1 +
>   hw/pci_internals.h |    1 +
>   hw/piix_pci.c      |   13 +-
>   hw/ppc4xx_pci.c    |    5 +-
>   hw/ppc_mac.h       |    9 +-
>   hw/ppc_newworld.c  |    5 +-
>   hw/ppc_oldworld.c  |    3 +-
>   hw/ppc_prep.c      |    3 +-
>   hw/ppce500_pci.c   |    6 +-
>   hw/prep_pci.c      |    5 +-
>   hw/prep_pci.h      |    3 +-
>   hw/sh_pci.c        |    4 +-
>   hw/sysbus.c        |   27 ++-
>   hw/sysbus.h        |    3 +
>   hw/unin_pci.c      |   10 +-
>   hw/usb-ohci.c      |   42 +--
>   hw/versatile_pci.c |    2 +
>   ioport.c           |    4 +-
>   memory.c           | 1144 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>   memory.h           |  259 ++++++++++++
>   33 files changed, 1852 insertions(+), 99 deletions(-)
>   create mode 100644 docs/memory.txt
>   create mode 100644 exec-memory.h
>   create mode 100644 memory.c
>   create mode 100644 memory.h
>

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 00/23] Memory API, batch 1
@ 2011-07-25 20:23   ` Anthony Liguori
  0 siblings, 0 replies; 100+ messages in thread
From: Anthony Liguori @ 2011-07-25 20:23 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 07/25/2011 09:02 AM, Avi Kivity wrote:
> This patchset contains the core of the memory API, with one device
> (usb-ohci) coverted for reference.  The API is currently implemented on
> top of the old ram_addr_t/cpu_register_physical_memory() API, but the plan
> is to make it standalone later.
>
> The goals of the API are:
>   - correctness: by modelling the memory hierarchy, things like the 440FX PAM
>     registers and movable, overlapping PCI BARs can be modelled accurately.
>   - efficiency: by maintaining an object tree describing guest memory, we
>     can eventually get rid of the page descriptor array
>   - security: by having more information available declaratively, we reduce
>     coding errors that may be exploited by malicious guests
>
> Also available from
>
>    git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git
>       refs/tags/memory-region-batch-1

Very nice series.

Despite my lack of exciting over ioeventfd and coalescing, if you fix 
the few minor comments, this should be a no brainer to merge.

Regards,

Anthony Liguori

>
> Avi Kivity (23):
>    Hierarchical memory region API
>    memory: implement dirty tracking
>    memory: merge adjacent segments of a single memory region
>    Internal interfaces for memory API
>    memory: abstract address space operations
>    memory: rename MemoryRegion::has_ram_addr to ::terminates
>    memory: late initialization of ram_addr
>    memory:  I/O address space support
>    memory: add backward compatibility for old portio registration
>    memory: add backward compatibility for old mmio registration
>    memory: add ioeventfd support
>    memory: separate building the final memory map into two steps
>    memory: document the memory API
>    memory: transaction API
>    exec.c: initialize memory map
>    ioport: register ranges by byte aligned addresses always
>    pc: grab system_memory
>    pc: convert pc_memory_init() to memory API
>    pc: move global memory map out of pc_init1() and into its callers
>    pci: pass address space to pci bus when created
>    pci: add MemoryRegion based BAR management API
>    sysbus: add MemoryRegion based memory management API
>    usb-ohci: convert to MemoryRegion
>
>   Makefile.target    |    1 +
>   docs/memory.txt    |  172 ++++++++
>   exec-memory.h      |   26 ++
>   exec.c             |   19 +
>   hw/apb_pci.c       |    2 +
>   hw/bonito.c        |    4 +-
>   hw/grackle_pci.c   |    5 +-
>   hw/gt64xxx.c       |    4 +-
>   hw/pc.c            |   62 ++-
>   hw/pc.h            |    9 +-
>   hw/pc_piix.c       |   20 +-
>   hw/pci.c           |   63 +++-
>   hw/pci.h           |   15 +-
>   hw/pci_host.h      |    1 +
>   hw/pci_internals.h |    1 +
>   hw/piix_pci.c      |   13 +-
>   hw/ppc4xx_pci.c    |    5 +-
>   hw/ppc_mac.h       |    9 +-
>   hw/ppc_newworld.c  |    5 +-
>   hw/ppc_oldworld.c  |    3 +-
>   hw/ppc_prep.c      |    3 +-
>   hw/ppce500_pci.c   |    6 +-
>   hw/prep_pci.c      |    5 +-
>   hw/prep_pci.h      |    3 +-
>   hw/sh_pci.c        |    4 +-
>   hw/sysbus.c        |   27 ++-
>   hw/sysbus.h        |    3 +
>   hw/unin_pci.c      |   10 +-
>   hw/usb-ohci.c      |   42 +--
>   hw/versatile_pci.c |    2 +
>   ioport.c           |    4 +-
>   memory.c           | 1144 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>   memory.h           |  259 ++++++++++++
>   33 files changed, 1852 insertions(+), 99 deletions(-)
>   create mode 100644 docs/memory.txt
>   create mode 100644 exec-memory.h
>   create mode 100644 memory.c
>   create mode 100644 memory.h
>

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 01/23] Hierarchical memory region API
  2011-07-25 18:41   ` Anthony Liguori
@ 2011-07-26  9:35     ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26  9:35 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 09:41 PM, Anthony Liguori wrote:
>> +/* Initialize a memory region
>> + *
>> + * The region typically acts as a container for other memory regions.
>> + */
>
>
> I'm also writing a fair bit of documentation right now.  We should use 
> a common format and declare that the doc format in CODING_STYLE.
>
> I think the two choices are gtk-doc (which I have been using):
>
<snip>

> I think gtk-doc is more concise and easier to write.  But Doxygen 
> clearly has better tooling.

Updated to use gtk-doc.  Ugh, a large API.

>
> Otherwise, Reviewed-by: Anthony Liguori <aliguori@us.ibm.com> but not 
> tested yet.
>
> I assume that all of the FIXMEs don't actually introduce regressions, 
> right?

Not intentionally.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 03/23] memory: merge adjacent segments of a single memory region
  2011-07-25 18:48   ` Anthony Liguori
@ 2011-07-26  9:55     ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26  9:55 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 09:48 PM, Anthony Liguori wrote:
>> +/* Attempt to simplify a view by merging ajacent ranges */
>> +static void flatview_simplify(FlatView *view)
>> +{
>> +    unsigned i;
>> +    FlatRange *r1, *r2;
>> +
>> +    for (i = 0; i + 1<  view->nr; ++i) {
>> +        r1 =&view->ranges[i];
>> +        r2 =&view->ranges[i+1];
>> +        if (addrrange_end(r1->addr) == r2->addr.start
>> +&&  r1->mr == r2->mr
>> +&&  r1->offset_in_region + r1->addr.size == r2->offset_in_region
>> +&&  r1->dirty_log_mask == r2->dirty_log_mask) {
>> +            r1->addr.size += r2->addr.size;
>> +            memmove(r2, r2 + 1, (view->nr - (i + 2)) * sizeof(*r2));
>> +            --view->nr;
>> +            --i;
>> +        }
>
>
> The --i is pretty subtle.  Moving the index variable backwards in a 
> conditional in a for loop is pretty evil :-)  I started writing up why 
> this was wrong until I noticed that.
>
> I think the following would be more straight forward:
>
> i = 0;
> while (i + 1 < view->nr) {
>    int begin = i, end = i + 1;
>
>    while (matches(&view->ranges[begin], &view->ranges[end])) {
>       end++;
>    }
>
>    memmove(...)
> }
>

Right; updated to something along these lines.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 06/23] memory: rename MemoryRegion::has_ram_addr to ::terminates
  2011-07-25 18:56   ` Anthony Liguori
@ 2011-07-26  9:59     ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26  9:59 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 09:56 PM, Anthony Liguori wrote:
> On 07/25/2011 09:02 AM, Avi Kivity wrote:
>> I/O regions will not have ram_addrs, so this is a better name.
>>
>> Signed-off-by: Avi Kivity<avi@redhat.com>
>
> Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
>
> Although it seems squashable.

Yeah, I'm loath to squash across a conflicting commit though.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support
  2011-07-25 19:08   ` Anthony Liguori
@ 2011-07-26 10:08     ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 10:08 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 10:08 PM, Anthony Liguori wrote:
>>
>> +static void as_memory_ioeventfd_add(AddressSpace *as, 
>> MemoryRegionIoeventfd *fd)
>> +{
>> +    int r;
>> +
>> +    if (!fd->match_data || fd->addr.size != 4) {
>> +        abort();
>> +    }
>> +
>> +    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, 
>> fd->data, true);
>> +    if (r<  0) {
>> +        abort();
>> +    }
>
>
> asserts would be friendlier.

I thought asserts were disabled by default.  But I see it isn't so; will 
update.

>
> I really dislike baking ioeventfd into this API.  There is only one 
> user of ioeventfd in the tree.

Two: virtio-pci and ivshmem.

>
> I worry that by having things like ioeventfd the API, we're making it 
> too difficult to side-step the API which prevents future optimizations.
>
> I'd prefer virtio-pci to have ugliness in it where it circumvented the 
> layering vs. having such a device specific thing in generic code.

It's impossible (or at least, impossible without further information 
from the API) to do this and retain correctness.  Currently virtio-pci 
is broken wrt bridges and overlapping BARs; it's probably also broken on 
targets that bridge the I/O address space to MMIO.

With the memory API, this is fixed in a natural way by making the I/O 
address space a subregion of the bridge which does the conversion; the 
code will automatically add the needed offset and use MMIO ioeventfd 
instead of portio.

On a more general note, I don't want this to be a lean and mean API that 
throws any complexity to the users; instead I want to make writing 
devices as simple as possible and own all the smarts.

(an example - undecoded address bits can be specified to the API which 
then takes care of replication or shifting).

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH 12/23] memory: separate building the final memory map into two steps
  2011-07-25 19:12   ` Anthony Liguori
@ 2011-07-26 10:43       ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 10:43 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 10:12 PM, Anthony Liguori wrote:
> On 07/25/2011 09:02 AM, Avi Kivity wrote:
>> Instead of adding and deleting regions in one pass, do a delete
>> pass followed by an add pass.  This fixes the following case:
>>
>> from:
>>    0x0000-0x0fff ram  (a1)
>>    0x1000-0x1fff mmio (a2)
>>    0x2000-0x2fff ram  (a3)
>>
>> to:
>>    0x0000-0x2fff ram  (b1)
>>
>> The single pass algorithm removed a1, added b2, then removed a2 and a2,
>
> You mean a2 and a3 I suppose?

Yes; fixed.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 12/23] memory: separate building the final memory map into two steps
@ 2011-07-26 10:43       ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 10:43 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 10:12 PM, Anthony Liguori wrote:
> On 07/25/2011 09:02 AM, Avi Kivity wrote:
>> Instead of adding and deleting regions in one pass, do a delete
>> pass followed by an add pass.  This fixes the following case:
>>
>> from:
>>    0x0000-0x0fff ram  (a1)
>>    0x1000-0x1fff mmio (a2)
>>    0x2000-0x2fff ram  (a3)
>>
>> to:
>>    0x0000-0x2fff ram  (b1)
>>
>> The single pass algorithm removed a1, added b2, then removed a2 and a2,
>
> You mean a2 and a3 I suppose?

Yes; fixed.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 13/23] memory: document the memory API
  2011-07-25 19:15   ` Anthony Liguori
@ 2011-07-26 10:44     ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 10:44 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 10:15 PM, Anthony Liguori wrote:
>> +Region names
>> +------------
>> +
>> +Regions are assigned names by the constructor.  For most regions 
>> these are
>> +only used for debugging purposes, but RAM regions also use the name 
>> to identify
>> +live migration sections.  This means that RAM region names need to 
>> have ABI
>> +stability.
> +
>
> I don't think this needs to change for this series, but long term, 
> this is something that we need to better think through.
>
> Device ROM is part of the device.  It shouldn't be migrated as RAM, it 
> should be included in the device state.

Agreed; however I tries to limit the amount of functional change, 
especially with anything resembling an ABI.

>
> Would be nice to make this patch #1 in the series.

Done.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 14/23] memory: transaction API
  2011-07-25 19:16   ` Anthony Liguori
@ 2011-07-26 10:48     ` Avi Kivity
  2011-07-26 11:39       ` Avi Kivity
  0 siblings, 1 reply; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 10:48 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 10:16 PM, Anthony Liguori wrote:
> On 07/25/2011 09:02 AM, Avi Kivity wrote:
>> Allow changes to the memory hierarchy to be accumulated and
>> made visible all at once.  This reduces computational effort,
>> especially when an accelerator (e.g. kvm) is involved.
>>
>> Useful when a single register update causes multiple changes
>> to an address space.
>>
>> Signed-off-by: Avi Kivity<avi@redhat.com>
>
> What's the motivation for this?  Was this just because it seemed neat 
> to do or did you run into a performance issue you were trying to solve?

Both cirrus and 440fx need this; look at i440fx_update_memory_mappings() 
for example, it blindly updates mappings even for PAMs which haven't 
changed.

These issues can be also solved by more care on the caller's side, or by 
making the API richer, but it's good to have a no-thought-required 
solution, particularly as it's so easy to do.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH 15/23] exec.c: initialize memory map
  2011-07-25 19:17   ` Anthony Liguori
@ 2011-07-26 10:55       ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 10:55 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 10:17 PM, Anthony Liguori wrote:
>> +static void memory_map_init(void)
>> +{
>> +    system_memory = qemu_malloc(sizeof(*system_memory));
>> +    memory_region_init(system_memory, "system", UINT64_MAX);
>
>
> Would be nice to #define MEM_REG_SIZE_ALL UINT64_MAX
>
> Without reading the docs, it seems like an odd bit of code otherwise.

It's really temporary.  It should come from the machine description and 
specify the processor's system bus width.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 15/23] exec.c: initialize memory map
@ 2011-07-26 10:55       ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 10:55 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 10:17 PM, Anthony Liguori wrote:
>> +static void memory_map_init(void)
>> +{
>> +    system_memory = qemu_malloc(sizeof(*system_memory));
>> +    memory_region_init(system_memory, "system", UINT64_MAX);
>
>
> Would be nice to #define MEM_REG_SIZE_ALL UINT64_MAX
>
> Without reading the docs, it seems like an odd bit of code otherwise.

It's really temporary.  It should come from the machine description and 
specify the processor's system bus width.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 16/23] ioport: register ranges by byte aligned addresses always
  2011-07-25 19:20   ` Anthony Liguori
@ 2011-07-26 10:59     ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 10:59 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 10:20 PM, Anthony Liguori wrote:
> On 07/25/2011 09:02 AM, Avi Kivity wrote:
>> The I/O port space is byte addressable, even for word and long accesses.
>>
>> An example is the VMware svga card, which has long ports on offsets 0,
>> 1, and 2.
>>
>> Signed-off-by: Avi Kivity<avi@redhat.com>
>
> I've always thought this was odd but didn't know of a specific 
> circumstance where it broke a device.
>
> This was a big problem with the old API.  Devices don't register their 
> interest in specific sizes.  They may ignore certain size accesses but 
> that's a device specific behavior.

In fact there's on counterexample - 440FX consumes dword accesses on 
port cf8 but forwards byte and word accesses to the PCI bus.  This 
cannot be implemented with the current API (it requires the opaque to be 
equal for all word sizes).  The new API doesn't support it either; if we 
need to, we can re-issue the access but using the PCI address space 
instead of the root I/O address space.

(of course this is purely theoretical)

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 19/23] pc: move global memory map out of pc_init1() and into its callers
  2011-07-25 20:02   ` Anthony Liguori
@ 2011-07-26 11:02     ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 11:02 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 11:02 PM, Anthony Liguori wrote:
> On 07/25/2011 09:03 AM, Avi Kivity wrote:
>> Signed-off-by: Avi Kivity<avi@redhat.com>
>
> What's the rationale here?

Removing globals and making dependencies explicit.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH 21/23] pci: add MemoryRegion based BAR management API
  2011-07-25 20:20     ` [Qemu-devel] " Anthony Liguori
@ 2011-07-26 11:06       ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 11:06 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 11:20 PM, Anthony Liguori wrote:
> On 07/25/2011 09:03 AM, Avi Kivity wrote:
>> Allow registering a BAR using a MemoryRegion.  Once all users are 
>> converted,
>> pci_register_bar() and pci_register_bar_simple() will be removed.
>>
>> Signed-off-by: Avi Kivity<avi@redhat.com>
>
>> diff --git a/hw/pci.h b/hw/pci.h
>> index cfeb042..c51156d 100644
>> --- a/hw/pci.h
>> +++ b/hw/pci.h
>> @@ -94,6 +94,7 @@ typedef struct PCIIORegion {
>>       uint8_t type;
>>       PCIMapIORegionFunc *map_func;
>>       ram_addr_t ram_addr;
>> +    MemoryRegion *memory;
>>   } PCIIORegion;
>>
>>   #define PCI_ROM_SLOT 6
>> @@ -204,6 +205,8 @@ void pci_register_bar(PCIDevice *pci_dev, int 
>> region_num,
>>                               PCIMapIORegionFunc *map_func);
>>   void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
>>                                pcibus_t size, uint8_t attr, 
>> ram_addr_t ram_addr);
>> +void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
>> +                             uint8_t attr, MemoryRegion *memory);
>
> This ends up being a very nice API.  I had always thought this should 
> be a PCI specific set of callbacks but I do see the benefits of having 
> the callbacks be generic.
>
> Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
>
> One thing I'm curious about, what's the symmetric view of this API?
>
> Would you see a device doing something like:
>
> memory_region_read(&dev->pci_bus->memory, addr, &data, sizeof(data))
>

I haven't really considered this, but it makes sense to consider the 
initiating point for DMA.  This allows us to do IOMMU transformations 
naturally.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 21/23] pci: add MemoryRegion based BAR management API
@ 2011-07-26 11:06       ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 11:06 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 11:20 PM, Anthony Liguori wrote:
> On 07/25/2011 09:03 AM, Avi Kivity wrote:
>> Allow registering a BAR using a MemoryRegion.  Once all users are 
>> converted,
>> pci_register_bar() and pci_register_bar_simple() will be removed.
>>
>> Signed-off-by: Avi Kivity<avi@redhat.com>
>
>> diff --git a/hw/pci.h b/hw/pci.h
>> index cfeb042..c51156d 100644
>> --- a/hw/pci.h
>> +++ b/hw/pci.h
>> @@ -94,6 +94,7 @@ typedef struct PCIIORegion {
>>       uint8_t type;
>>       PCIMapIORegionFunc *map_func;
>>       ram_addr_t ram_addr;
>> +    MemoryRegion *memory;
>>   } PCIIORegion;
>>
>>   #define PCI_ROM_SLOT 6
>> @@ -204,6 +205,8 @@ void pci_register_bar(PCIDevice *pci_dev, int 
>> region_num,
>>                               PCIMapIORegionFunc *map_func);
>>   void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
>>                                pcibus_t size, uint8_t attr, 
>> ram_addr_t ram_addr);
>> +void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
>> +                             uint8_t attr, MemoryRegion *memory);
>
> This ends up being a very nice API.  I had always thought this should 
> be a PCI specific set of callbacks but I do see the benefits of having 
> the callbacks be generic.
>
> Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
>
> One thing I'm curious about, what's the symmetric view of this API?
>
> Would you see a device doing something like:
>
> memory_region_read(&dev->pci_bus->memory, addr, &data, sizeof(data))
>

I haven't really considered this, but it makes sense to consider the 
initiating point for DMA.  This allows us to do IOMMU transformations 
naturally.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 00/23] Memory API, batch 1
  2011-07-25 20:23   ` [Qemu-devel] " Anthony Liguori
  (?)
@ 2011-07-26 11:32   ` Avi Kivity
  -1 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 11:32 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/25/2011 11:23 PM, Anthony Liguori wrote:
>
> Very nice series.
>
> Despite my lack of exciting over ioeventfd and coalescing, if you fix 
> the few minor comments, this should be a no brainer to merge.

Thanks; v2 posted.

Note that this patchset has a logical dependency on my "[PATCH] 
CODING_STYLE: explicitly allow braceless 'else if'" patch.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [Qemu-devel] [PATCH 14/23] memory: transaction API
  2011-07-26 10:48     ` Avi Kivity
@ 2011-07-26 11:39       ` Avi Kivity
  0 siblings, 0 replies; 100+ messages in thread
From: Avi Kivity @ 2011-07-26 11:39 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 07/26/2011 01:48 PM, Avi Kivity wrote:
> On 07/25/2011 10:16 PM, Anthony Liguori wrote:
>> On 07/25/2011 09:02 AM, Avi Kivity wrote:
>>> Allow changes to the memory hierarchy to be accumulated and
>>> made visible all at once.  This reduces computational effort,
>>> especially when an accelerator (e.g. kvm) is involved.
>>>
>>> Useful when a single register update causes multiple changes
>>> to an address space.
>>>
>>> Signed-off-by: Avi Kivity<avi@redhat.com>
>>
>> What's the motivation for this?  Was this just because it seemed neat 
>> to do or did you run into a performance issue you were trying to solve?
>
> Both cirrus and 440fx need this; look at 
> i440fx_update_memory_mappings() for example, it blindly updates 
> mappings even for PAMs which haven't changed.
>
> These issues can be also solved by more care on the caller's side, or 
> by making the API richer, but it's good to have a no-thought-required 
> solution, particularly as it's so easy to do.
>

I should note that updating the memory map is relatively slow with kvm 
due to the need to wait for an rcu grace period; though recent kernels 
are faster.  So any saving here has a large effect.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 100+ messages in thread

end of thread, other threads:[~2011-07-26 11:39 UTC | newest]

Thread overview: 100+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-25 14:02 [PATCH 00/23] Memory API, batch 1 Avi Kivity
2011-07-25 14:02 ` [Qemu-devel] " Avi Kivity
2011-07-25 14:02 ` [PATCH 01/23] Hierarchical memory region API Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 18:41   ` Anthony Liguori
2011-07-26  9:35     ` Avi Kivity
2011-07-25 14:02 ` [PATCH 02/23] memory: implement dirty tracking Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 18:43   ` Anthony Liguori
2011-07-25 18:43     ` [Qemu-devel] " Anthony Liguori
2011-07-25 14:02 ` [PATCH 03/23] memory: merge adjacent segments of a single memory region Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 18:48   ` Anthony Liguori
2011-07-26  9:55     ` Avi Kivity
2011-07-25 14:02 ` [PATCH 04/23] Internal interfaces for memory API Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 18:49   ` Anthony Liguori
2011-07-25 14:02 ` [PATCH 05/23] memory: abstract address space operations Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 18:51   ` Anthony Liguori
2011-07-25 14:02 ` [PATCH 06/23] memory: rename MemoryRegion::has_ram_addr to ::terminates Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 18:56   ` Anthony Liguori
2011-07-26  9:59     ` Avi Kivity
2011-07-25 14:02 ` [PATCH 07/23] memory: late initialization of ram_addr Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 14:02 ` [PATCH 08/23] memory: I/O address space support Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 19:00   ` Anthony Liguori
2011-07-25 14:02 ` [PATCH 09/23] memory: add backward compatibility for old portio registration Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 19:01   ` Anthony Liguori
2011-07-25 14:02 ` [PATCH 10/23] memory: add backward compatibility for old mmio registration Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 19:02   ` Anthony Liguori
2011-07-25 14:02 ` [PATCH 11/23] memory: add ioeventfd support Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 15:16   ` malc
2011-07-25 15:17     ` Avi Kivity
2011-07-25 15:17       ` [Qemu-devel] " Avi Kivity
2011-07-25 15:22       ` malc
2011-07-25 15:22         ` [Qemu-devel] " malc
2011-07-25 15:28         ` Avi Kivity
2011-07-25 15:38           ` malc
2011-07-25 15:43             ` Avi Kivity
2011-07-25 19:08   ` Anthony Liguori
2011-07-26 10:08     ` Avi Kivity
2011-07-25 14:02 ` [PATCH 12/23] memory: separate building the final memory map into two steps Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 19:12   ` Anthony Liguori
2011-07-26 10:43     ` Avi Kivity
2011-07-26 10:43       ` [Qemu-devel] " Avi Kivity
2011-07-25 14:02 ` [PATCH 13/23] memory: document the memory API Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 19:15   ` Anthony Liguori
2011-07-26 10:44     ` Avi Kivity
2011-07-25 14:02 ` [PATCH 14/23] memory: transaction API Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 19:16   ` Anthony Liguori
2011-07-26 10:48     ` Avi Kivity
2011-07-26 11:39       ` Avi Kivity
2011-07-25 14:02 ` [PATCH 15/23] exec.c: initialize memory map Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 19:17   ` Anthony Liguori
2011-07-26 10:55     ` Avi Kivity
2011-07-26 10:55       ` [Qemu-devel] " Avi Kivity
2011-07-25 14:02 ` [PATCH 16/23] ioport: register ranges by byte aligned addresses always Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 19:20   ` Anthony Liguori
2011-07-26 10:59     ` Avi Kivity
2011-07-25 14:02 ` [PATCH 17/23] pc: grab system_memory Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 19:22   ` Anthony Liguori
2011-07-25 14:02 ` [PATCH 18/23] pc: convert pc_memory_init() to memory API Avi Kivity
2011-07-25 14:02   ` [Qemu-devel] " Avi Kivity
2011-07-25 19:23   ` Anthony Liguori
2011-07-25 14:03 ` [PATCH 19/23] pc: move global memory map out of pc_init1() and into its callers Avi Kivity
2011-07-25 14:03   ` [Qemu-devel] " Avi Kivity
2011-07-25 20:02   ` Anthony Liguori
2011-07-26 11:02     ` Avi Kivity
2011-07-25 14:03 ` [PATCH 20/23] pci: pass address space to pci bus when created Avi Kivity
2011-07-25 14:03   ` [Qemu-devel] " Avi Kivity
2011-07-25 20:03   ` Anthony Liguori
2011-07-25 20:03     ` [Qemu-devel] " Anthony Liguori
2011-07-25 14:03 ` [PATCH 21/23] pci: add MemoryRegion based BAR management API Avi Kivity
2011-07-25 14:03   ` [Qemu-devel] " Avi Kivity
2011-07-25 20:20   ` Anthony Liguori
2011-07-25 20:20     ` [Qemu-devel] " Anthony Liguori
2011-07-26 11:06     ` Avi Kivity
2011-07-26 11:06       ` [Qemu-devel] " Avi Kivity
2011-07-25 14:03 ` [PATCH 22/23] sysbus: add MemoryRegion based memory " Avi Kivity
2011-07-25 14:03   ` [Qemu-devel] " Avi Kivity
2011-07-25 20:21   ` Anthony Liguori
2011-07-25 20:21     ` [Qemu-devel] " Anthony Liguori
2011-07-25 14:03 ` [PATCH 23/23] usb-ohci: convert to MemoryRegion Avi Kivity
2011-07-25 14:03   ` [Qemu-devel] " Avi Kivity
2011-07-25 20:22   ` Anthony Liguori
2011-07-25 20:23 ` [PATCH 00/23] Memory API, batch 1 Anthony Liguori
2011-07-25 20:23   ` [Qemu-devel] " Anthony Liguori
2011-07-26 11:32   ` Avi Kivity

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.