All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v2 00/20] Memory API
@ 2011-06-27 13:21 ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

As expected, this is taking longer than expected, so I'm releasing something
less complete than I'd have liked.  Not even all of the PC machine is
converted, but the difficult parts are (cirrus).  It appears to work well.

The major change compared to v1 is the introduction of
memory_region_init_alias(), which defines a memory region in terms of another.
With the current API, the ability to alias is provided by address arithmetic
on ram_addr_t:

  ram_addr = qemu_ram_alloc(...);
  cpu_register_physical_memory(..., ram_addr, size, ...);
  /* alias: */
  cpu_register_physical_memory(..., ram_addr + offset, another_size, ...);

With the new API, you have to create an alias:

  memory_region_init_ram(&mem, ...);
  memory_region_register_subregion(..., &mem);
  /* alias: */
  memory_region_init_alias(&alias, ..., &mem, offset, another_size);
  memory_region_register_subregion(..., &alias);

The patchset is somewhat churny.  One of the reasons is that we move from a
handle/pointer scheme in ram_addr_t to an object constructor/destructor scheme.
Another is that region size becomes a property of a region instead of being
maintained externally.  Also, container memory regions must be passed around,
though we don't do that as well as we should.

Todo:
  - eliminate calls to get_system_memory() (where we ignore the bus hierarchy)
  - add PCI APIs for the VGA window
  - support the PIO address space using the memory API (allowing simplified
    PCI BAR registration)
  - convert 440FX
  - convert everything else

Also available in

  git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git memory-region

with a complementary pair of noisy debug patches.

Avi Kivity (20):
  Hierarchical memory region API
  memory: implement dirty tracking
  memory: merge adjacent segments of a single memory region
  Internal interfaces for memory API
  exec.c: initialize memory map
  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
  pci: add API to get a BAR's mapped address
  vmsvga: don't remember pci BAR address in callback any more
  vga: convert vga and its derivatives to the memory API
  cirrus: simplify mmio BAR access functions
  cirrus: simplify bitblt BAR access functions
  cirrus: simplify vga window mmio access functions
  vga: simplify vga window mmio access functions
  cirrus: simplify linear framebuffer access functions

 Makefile.target    |    1 +
 exec-memory.h      |   17 ++
 exec.c             |   19 ++
 hw/apb_pci.c       |    2 +
 hw/bonito.c        |    4 +-
 hw/cirrus_vga.c    |  476 ++++++++++++------------------------
 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           |   68 ++++-
 hw/pci.h           |   16 +-
 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 +
 hw/vga-isa-mm.c    |   66 ++++--
 hw/vga-isa.c       |   13 +-
 hw/vga-pci.c       |   28 +--
 hw/vga.c           |  178 +++++---------
 hw/vga_int.h       |   24 +-
 hw/vmware_vga.c    |   94 +++++---
 memory.c           |  704 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory.h           |  202 +++++++++++++++
 38 files changed, 1525 insertions(+), 629 deletions(-)
 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] 79+ messages in thread

* [Qemu-devel] [RFC v2 00/20] Memory API
@ 2011-06-27 13:21 ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

As expected, this is taking longer than expected, so I'm releasing something
less complete than I'd have liked.  Not even all of the PC machine is
converted, but the difficult parts are (cirrus).  It appears to work well.

The major change compared to v1 is the introduction of
memory_region_init_alias(), which defines a memory region in terms of another.
With the current API, the ability to alias is provided by address arithmetic
on ram_addr_t:

  ram_addr = qemu_ram_alloc(...);
  cpu_register_physical_memory(..., ram_addr, size, ...);
  /* alias: */
  cpu_register_physical_memory(..., ram_addr + offset, another_size, ...);

With the new API, you have to create an alias:

  memory_region_init_ram(&mem, ...);
  memory_region_register_subregion(..., &mem);
  /* alias: */
  memory_region_init_alias(&alias, ..., &mem, offset, another_size);
  memory_region_register_subregion(..., &alias);

The patchset is somewhat churny.  One of the reasons is that we move from a
handle/pointer scheme in ram_addr_t to an object constructor/destructor scheme.
Another is that region size becomes a property of a region instead of being
maintained externally.  Also, container memory regions must be passed around,
though we don't do that as well as we should.

Todo:
  - eliminate calls to get_system_memory() (where we ignore the bus hierarchy)
  - add PCI APIs for the VGA window
  - support the PIO address space using the memory API (allowing simplified
    PCI BAR registration)
  - convert 440FX
  - convert everything else

Also available in

  git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git memory-region

with a complementary pair of noisy debug patches.

Avi Kivity (20):
  Hierarchical memory region API
  memory: implement dirty tracking
  memory: merge adjacent segments of a single memory region
  Internal interfaces for memory API
  exec.c: initialize memory map
  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
  pci: add API to get a BAR's mapped address
  vmsvga: don't remember pci BAR address in callback any more
  vga: convert vga and its derivatives to the memory API
  cirrus: simplify mmio BAR access functions
  cirrus: simplify bitblt BAR access functions
  cirrus: simplify vga window mmio access functions
  vga: simplify vga window mmio access functions
  cirrus: simplify linear framebuffer access functions

 Makefile.target    |    1 +
 exec-memory.h      |   17 ++
 exec.c             |   19 ++
 hw/apb_pci.c       |    2 +
 hw/bonito.c        |    4 +-
 hw/cirrus_vga.c    |  476 ++++++++++++------------------------
 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           |   68 ++++-
 hw/pci.h           |   16 +-
 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 +
 hw/vga-isa-mm.c    |   66 ++++--
 hw/vga-isa.c       |   13 +-
 hw/vga-pci.c       |   28 +--
 hw/vga.c           |  178 +++++---------
 hw/vga_int.h       |   24 +-
 hw/vmware_vga.c    |   94 +++++---
 memory.c           |  704 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory.h           |  202 +++++++++++++++
 38 files changed, 1525 insertions(+), 629 deletions(-)
 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] 79+ messages in thread

* [RFC v2 01/20] Hierarchical memory region API
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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        |  659 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory.h        |  201 +++++++++++++++++
 3 files changed, 861 insertions(+), 0 deletions(-)
 create mode 100644 memory.c
 create mode 100644 memory.h

diff --git a/Makefile.target b/Makefile.target
index 03d3646..5b24bd7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -194,6 +194,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..43499c3
--- /dev/null
+++ b/memory.c
@@ -0,0 +1,659 @@
+/*
+ * 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.max_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, 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.max_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, 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,
+                           const char *name,
+                           uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->ops = ops;
+    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();
+}
+
+void set_system_memory_map(MemoryRegion *mr)
+{
+    root_memory_region = mr;
+    memory_region_update_topology();
+}
diff --git a/memory.h b/memory.h
new file mode 100644
index 0000000..a67ff94
--- /dev/null
+++ b/memory.h
@@ -0,0 +1,201 @@
+#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)(MemoryRegion *mr,
+                     target_phys_addr_t addr,
+                     unsigned size);
+    /* Write to the memory region. @addr is relative to @mr; @size is
+     * in bytes. */
+    void (*write)(MemoryRegion *mr,
+                  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;
+    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,
+                           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);
+
+/* Set the root memory region.  This region is the system memory map. */
+void set_system_memory_map(MemoryRegion *mr);
+
+#endif
+
+#endif
-- 
1.7.5.3


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

* [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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        |  659 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory.h        |  201 +++++++++++++++++
 3 files changed, 861 insertions(+), 0 deletions(-)
 create mode 100644 memory.c
 create mode 100644 memory.h

diff --git a/Makefile.target b/Makefile.target
index 03d3646..5b24bd7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -194,6 +194,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..43499c3
--- /dev/null
+++ b/memory.c
@@ -0,0 +1,659 @@
+/*
+ * 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.max_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, 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.max_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, 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,
+                           const char *name,
+                           uint64_t size)
+{
+    memory_region_init(mr, name, size);
+    mr->ops = ops;
+    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();
+}
+
+void set_system_memory_map(MemoryRegion *mr)
+{
+    root_memory_region = mr;
+    memory_region_update_topology();
+}
diff --git a/memory.h b/memory.h
new file mode 100644
index 0000000..a67ff94
--- /dev/null
+++ b/memory.h
@@ -0,0 +1,201 @@
+#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)(MemoryRegion *mr,
+                     target_phys_addr_t addr,
+                     unsigned size);
+    /* Write to the memory region. @addr is relative to @mr; @size is
+     * in bytes. */
+    void (*write)(MemoryRegion *mr,
+                  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;
+    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,
+                           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);
+
+/* Set the root memory region.  This region is the system memory map. */
+void set_system_memory_map(MemoryRegion *mr);
+
+#endif
+
+#endif
-- 
1.7.5.3

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

* [RFC v2 02/20] memory: implement dirty tracking
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 43499c3..d962fff 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,
@@ -494,24 +503,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)
@@ -522,7 +542,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 a67ff94..2bf9625 100644
--- a/memory.h
+++ b/memory.h
@@ -85,6 +85,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] 79+ messages in thread

* [Qemu-devel] [RFC v2 02/20] memory: implement dirty tracking
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 43499c3..d962fff 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,
@@ -494,24 +503,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)
@@ -522,7 +542,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 a67ff94..2bf9625 100644
--- a/memory.h
+++ b/memory.h
@@ -85,6 +85,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] 79+ messages in thread

* [RFC v2 03/20] memory: merge adjacent segments of a single memory region
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 d962fff..f136714 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] 79+ messages in thread

* [Qemu-devel] [RFC v2 03/20] memory: merge adjacent segments of a single memory region
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 d962fff..f136714 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] 79+ messages in thread

* [RFC v2 04/20] Internal interfaces for memory API
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 |   17 +++++++++++++++++
 1 files changed, 17 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..2722f7e
--- /dev/null
+++ b/exec-memory.h
@@ -0,0 +1,17 @@
+#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
+
+MemoryRegion *get_system_memory(void);
+
+#endif
+
+#endif
-- 
1.7.5.3


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

* [Qemu-devel] [RFC v2 04/20] Internal interfaces for memory API
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 |   17 +++++++++++++++++
 1 files changed, 17 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..2722f7e
--- /dev/null
+++ b/exec-memory.h
@@ -0,0 +1,17 @@
+#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
+
+MemoryRegion *get_system_memory(void);
+
+#endif
+
+#endif
-- 
1.7.5.3

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

* [RFC v2 05/20] exec.c: initialize memory map
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 b03b5be..9b894b9 100644
--- a/exec.c
+++ b/exec.c
@@ -34,6 +34,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__)
@@ -110,6 +112,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;
@@ -198,6 +203,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];
@@ -572,6 +578,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)
@@ -3802,6 +3809,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] 79+ messages in thread

* [Qemu-devel] [RFC v2 05/20] exec.c: initialize memory map
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 b03b5be..9b894b9 100644
--- a/exec.c
+++ b/exec.c
@@ -34,6 +34,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__)
@@ -110,6 +112,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;
@@ -198,6 +203,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];
@@ -572,6 +578,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)
@@ -3802,6 +3809,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] 79+ messages in thread

* [RFC v2 06/20] pc: grab system_memory
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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] 79+ messages in thread

* [Qemu-devel] [RFC v2 06/20] pc: grab system_memory
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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] 79+ messages in thread

* [RFC v2 07/20] pc: convert pc_memory_init() to memory API
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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] 79+ messages in thread

* [Qemu-devel] [RFC v2 07/20] pc: convert pc_memory_init() to memory API
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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] 79+ messages in thread

* [RFC v2 08/20] pc: move global memory map out of pc_init1() and into its callers
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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] 79+ messages in thread

* [Qemu-devel] [RFC v2 08/20] pc: move global memory map out of pc_init1() and into its callers
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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] 79+ messages in thread

* [RFC v2 09/20] pci: pass address space to pci bus when created
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 26ce904..445c6cb 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 ea87593..1733876 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
 
@@ -53,11 +55,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 86f1cfb..6302755 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
@@ -310,10 +311,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 75a3127..65a8de5 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
@@ -226,7 +227,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 8e75ffc..6b693df 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] 79+ messages in thread

* [Qemu-devel] [RFC v2 09/20] pci: pass address space to pci bus when created
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 26ce904..445c6cb 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 ea87593..1733876 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
 
@@ -53,11 +55,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 86f1cfb..6302755 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
@@ -310,10 +311,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 75a3127..65a8de5 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
@@ -226,7 +227,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 8e75ffc..6b693df 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] 79+ messages in thread

* [RFC v2 10/20] pci: add MemoryRegion based BAR management API
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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] 79+ messages in thread

* [Qemu-devel] [RFC v2 10/20] pci: add MemoryRegion based BAR management API
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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] 79+ messages in thread

* [RFC v2 11/20] sysbus: add MemoryRegion based memory management API
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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] 79+ messages in thread

* [Qemu-devel] [RFC v2 11/20] sysbus: add MemoryRegion based memory management API
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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] 79+ messages in thread

* [RFC v2 12/20] usb-ohci: convert to MemoryRegion
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:21   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 5d2ae01..e6a901f 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;
 
@@ -1415,13 +1415,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(MemoryRegion *mem,
+                              target_phys_addr_t addr,
+                              unsigned size)
 {
-    OHCIState *ohci = ptr;
+    OHCIState *ohci = container_of(mem, OHCIState, mem);
     uint32_t retval;
 
-    addr &= 0xff;
-
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
         fprintf(stderr, "usb-ohci: Mis-aligned read\n");
@@ -1538,11 +1538,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(MemoryRegion *mem,
+                           target_phys_addr_t addr,
+                           uint64_t val,
+                           unsigned size)
 {
-    OHCIState *ohci = ptr;
-
-    addr &= 0xff;
+    OHCIState *ohci = container_of(mem, OHCIState, mem);
 
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
@@ -1674,18 +1675,10 @@ static void ohci_device_destroy(USBBus *bus, 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 = {
@@ -1720,8 +1713,7 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
                 usb_frame_time, usb_bit_time);
     }
 
-    ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci,
-                                       DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&ohci->mem, &ohci_mem_ops, "ohci", 256);
     ohci->localmem_base = localmem_base;
 
     ohci->name = dev->info->name;
@@ -1756,7 +1748,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;
 }
 
@@ -1778,7 +1770,7 @@ static int ohci_init_pxa(SysBusDevice *dev)
 
     usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset);
     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] 79+ messages in thread

* [Qemu-devel] [RFC v2 12/20] usb-ohci: convert to MemoryRegion
@ 2011-06-27 13:21   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:21 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 5d2ae01..e6a901f 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;
 
@@ -1415,13 +1415,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(MemoryRegion *mem,
+                              target_phys_addr_t addr,
+                              unsigned size)
 {
-    OHCIState *ohci = ptr;
+    OHCIState *ohci = container_of(mem, OHCIState, mem);
     uint32_t retval;
 
-    addr &= 0xff;
-
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
         fprintf(stderr, "usb-ohci: Mis-aligned read\n");
@@ -1538,11 +1538,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(MemoryRegion *mem,
+                           target_phys_addr_t addr,
+                           uint64_t val,
+                           unsigned size)
 {
-    OHCIState *ohci = ptr;
-
-    addr &= 0xff;
+    OHCIState *ohci = container_of(mem, OHCIState, mem);
 
     /* Only aligned reads are allowed on OHCI */
     if (addr & 3) {
@@ -1674,18 +1675,10 @@ static void ohci_device_destroy(USBBus *bus, 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 = {
@@ -1720,8 +1713,7 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
                 usb_frame_time, usb_bit_time);
     }
 
-    ohci->mem = cpu_register_io_memory(ohci_readfn, ohci_writefn, ohci,
-                                       DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&ohci->mem, &ohci_mem_ops, "ohci", 256);
     ohci->localmem_base = localmem_base;
 
     ohci->name = dev->info->name;
@@ -1756,7 +1748,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;
 }
 
@@ -1778,7 +1770,7 @@ static int ohci_init_pxa(SysBusDevice *dev)
 
     usb_ohci_init(&s->ohci, &dev->qdev, s->num_ports, s->dma_offset);
     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] 79+ messages in thread

* [RFC v2 13/20] pci: add API to get a BAR's mapped address
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:22   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

This is a hack, for devices that have a back-channel to read this
address back outside the normal configuration mechanisms, such
as VMware svga.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/pci.c |    5 +++++
 hw/pci.h |    1 +
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 36db58b..912f849 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -952,6 +952,11 @@ void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
     pci_dev->io_regions[region_num].memory = memory;
 }
 
+pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num)
+{
+    return pci_dev->io_regions[region_num].addr;
+}
+
 static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
                               uint8_t type)
 {
diff --git a/hw/pci.h b/hw/pci.h
index c51156d..64282ad 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -207,6 +207,7 @@ 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);
+pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
 
 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] 79+ messages in thread

* [Qemu-devel] [RFC v2 13/20] pci: add API to get a BAR's mapped address
@ 2011-06-27 13:22   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

This is a hack, for devices that have a back-channel to read this
address back outside the normal configuration mechanisms, such
as VMware svga.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/pci.c |    5 +++++
 hw/pci.h |    1 +
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 36db58b..912f849 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -952,6 +952,11 @@ void pci_register_bar_region(PCIDevice *pci_dev, int region_num,
     pci_dev->io_regions[region_num].memory = memory;
 }
 
+pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num)
+{
+    return pci_dev->io_regions[region_num].addr;
+}
+
 static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size,
                               uint8_t type)
 {
diff --git a/hw/pci.h b/hw/pci.h
index c51156d..64282ad 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -207,6 +207,7 @@ 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);
+pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num);
 
 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] 79+ messages in thread

* [RFC v2 14/20] vmsvga: don't remember pci BAR address in callback any more
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:22   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

We're going to remove the callback, so we can't use it to save the
address.  Use the pci API instead.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/vmware_vga.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 354c221..190b005 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -52,8 +52,6 @@ struct vmsvga_state_s {
         int on;
     } cursor;
 
-    target_phys_addr_t vram_base;
-
     int index;
     int scratch_size;
     uint32_t *scratch;
@@ -761,8 +759,11 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
     case SVGA_REG_BYTES_PER_LINE:
         return ((s->depth + 7) >> 3) * s->new_width;
 
-    case SVGA_REG_FB_START:
-        return s->vram_base;
+    case SVGA_REG_FB_START: {
+        struct pci_vmsvga_state_s *pci_vmsvga
+            = container_of(s, struct pci_vmsvga_state_s, chip);
+        return pci_get_bar_addr(&pci_vmsvga->card, 1);
+    }
 
     case SVGA_REG_FB_OFFSET:
         return 0x0;
@@ -1247,14 +1248,13 @@ static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
     struct vmsvga_state_s *s = &d->chip;
     ram_addr_t iomemtype;
 
-    s->vram_base = addr;
 #ifdef DIRECT_VRAM
     iomemtype = cpu_register_io_memory(vmsvga_vram_read,
                     vmsvga_vram_write, s, DEVICE_NATIVE_ENDIAN);
 #else
     iomemtype = s->vga.vram_offset | IO_MEM_RAM;
 #endif
-    cpu_register_physical_memory(s->vram_base, s->vga.vram_size,
+    cpu_register_physical_memory(addr, s->vga.vram_size,
                     iomemtype);
 
     s->vga.map_addr = addr;
-- 
1.7.5.3


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

* [Qemu-devel] [RFC v2 14/20] vmsvga: don't remember pci BAR address in callback any more
@ 2011-06-27 13:22   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

We're going to remove the callback, so we can't use it to save the
address.  Use the pci API instead.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/vmware_vga.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 354c221..190b005 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -52,8 +52,6 @@ struct vmsvga_state_s {
         int on;
     } cursor;
 
-    target_phys_addr_t vram_base;
-
     int index;
     int scratch_size;
     uint32_t *scratch;
@@ -761,8 +759,11 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
     case SVGA_REG_BYTES_PER_LINE:
         return ((s->depth + 7) >> 3) * s->new_width;
 
-    case SVGA_REG_FB_START:
-        return s->vram_base;
+    case SVGA_REG_FB_START: {
+        struct pci_vmsvga_state_s *pci_vmsvga
+            = container_of(s, struct pci_vmsvga_state_s, chip);
+        return pci_get_bar_addr(&pci_vmsvga->card, 1);
+    }
 
     case SVGA_REG_FB_OFFSET:
         return 0x0;
@@ -1247,14 +1248,13 @@ static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
     struct vmsvga_state_s *s = &d->chip;
     ram_addr_t iomemtype;
 
-    s->vram_base = addr;
 #ifdef DIRECT_VRAM
     iomemtype = cpu_register_io_memory(vmsvga_vram_read,
                     vmsvga_vram_write, s, DEVICE_NATIVE_ENDIAN);
 #else
     iomemtype = s->vga.vram_offset | IO_MEM_RAM;
 #endif
-    cpu_register_physical_memory(s->vram_base, s->vga.vram_size,
+    cpu_register_physical_memory(addr, s->vga.vram_size,
                     iomemtype);
 
     s->vga.map_addr = addr;
-- 
1.7.5.3

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

* [RFC v2 15/20] vga: convert vga and its derivatives to the memory API
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:22   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Convert all vga memory to the memory API.  Note we need to fall back to
get_system_memory(), since the various buses don't pass the vga window
as a memory region.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |  346 +++++++++++++++++++++++++++++++++----------------------
 hw/vga-isa-mm.c |   66 ++++++++---
 hw/vga-isa.c    |   13 ++-
 hw/vga-pci.c    |   28 +----
 hw/vga.c        |  146 +++++++++++-------------
 hw/vga_int.h    |   20 ++--
 hw/vmware_vga.c |   84 ++++++++-----
 7 files changed, 395 insertions(+), 308 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index f39d1f8..0cce453 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -200,9 +200,14 @@ typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
 typedef struct CirrusVGAState {
     VGACommonState vga;
 
-    int cirrus_linear_io_addr;
-    int cirrus_linear_bitblt_io_addr;
-    int cirrus_mmio_io_addr;
+    MemoryRegion cirrus_linear_io;
+    MemoryRegion cirrus_linear_bitblt_io;
+    MemoryRegion cirrus_mmio_io;
+    MemoryRegion pci_bar;
+    bool linear_vram;  /* vga.vram mapped over cirrus_linear_io */
+    MemoryRegion low_mem_container; /* container for 0xa0000-0xc0000 */
+    MemoryRegion low_mem;           /* always mapped, overridden by: */
+    MemoryRegion *cirrus_bank[2];   /*   aliases at 0xa0000-0xb0000  */
     uint32_t cirrus_addr_mask;
     uint32_t linear_mmio_mask;
     uint8_t cirrus_shadow_gr0;
@@ -612,7 +617,7 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
 	off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
 	off_cur &= TARGET_PAGE_MASK;
 	while (off_cur < off_cur_end) {
-	    cpu_physical_memory_set_dirty(s->vga.vram_offset + off_cur);
+	    memory_region_set_dirty(&s->vga.vram, off_cur);
 	    off_cur += TARGET_PAGE_SIZE;
 	}
 	off_begin += off_pitch;
@@ -1177,12 +1182,6 @@ static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
     }
 
     if (limit > 0) {
-        /* Thinking about changing bank base? First, drop the dirty bitmap information
-         * on the current location, otherwise we lose this pointer forever */
-        if (s->vga.lfb_vram_mapped) {
-            target_phys_addr_t base_addr = isa_mem_base + 0xa0000 + bank_index * 0x8000;
-            cpu_physical_sync_dirty_bitmap(base_addr, base_addr + 0x8000);
-        }
 	s->cirrus_bank_base[bank_index] = offset;
 	s->cirrus_bank_limit[bank_index] = limit;
     } else {
@@ -1921,8 +1920,8 @@ static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
 	val <<= 1;
 	dst++;
     }
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset);
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset + 7);
+    memory_region_set_dirty(&s->vga.vram, offset);
+    memory_region_set_dirty(&s->vga.vram, offset + 7);
 }
 
 static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
@@ -1946,8 +1945,8 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
 	val <<= 1;
 	dst += 2;
     }
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset);
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset + 15);
+    memory_region_set_dirty(&s->vga.vram, offset);
+    memory_region_set_dirty(&s->vga.vram, offset + 15);
 }
 
 /***************************************
@@ -2057,8 +2056,7 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
 		mode = s->vga.gr[0x05] & 0x7;
 		if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
 		    *(s->vga.vram_ptr + bank_offset) = mem_value;
-		    cpu_physical_memory_set_dirty(s->vga.vram_offset +
-						  bank_offset);
+		    memory_region_set_dirty(&s->vga.vram, bank_offset);
 		} else {
 		    if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
 			cirrus_mem_writeb_mode4and5_8bpp(s, mode,
@@ -2099,16 +2097,37 @@ static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_
     cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
 }
 
-static CPUReadMemoryFunc * const cirrus_vga_mem_read[3] = {
-    cirrus_vga_mem_readb,
-    cirrus_vga_mem_readw,
-    cirrus_vga_mem_readl,
+static uint64_t cirrus_vga_mem_read(MemoryRegion *mr,
+                                    target_phys_addr_t addr,
+                                    uint32_t size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
+
+    switch (size) {
+    case 1: return cirrus_vga_mem_readb(s, addr);
+    case 2: return cirrus_vga_mem_readw(s, addr);
+    case 4: return cirrus_vga_mem_readl(s, addr);
+    default: abort();
+    }
+}
+
+static void cirrus_vga_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
+                                 uint64_t data, unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
+
+    switch (size) {
+    case 1: return cirrus_vga_mem_writeb(s, addr, data);
+    case 2: return cirrus_vga_mem_writew(s, addr, data);
+    case 4: return cirrus_vga_mem_writel(s, addr, data);
+    default: abort();
+    }
 };
 
-static CPUWriteMemoryFunc * const cirrus_vga_mem_write[3] = {
-    cirrus_vga_mem_writeb,
-    cirrus_vga_mem_writew,
-    cirrus_vga_mem_writel,
+static MemoryRegionOps cirrus_vga_mem_ops = {
+    .read = cirrus_vga_mem_read,
+    .write = cirrus_vga_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 /***************************************
@@ -2365,7 +2384,7 @@ static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
 	mode = s->vga.gr[0x05] & 0x7;
 	if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
 	    *(s->vga.vram_ptr + addr) = (uint8_t) val;
-	    cpu_physical_memory_set_dirty(s->vga.vram_offset + addr);
+	    memory_region_set_dirty(&s->vga.vram, addr);
 	} else {
 	    if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
 		cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
@@ -2393,17 +2412,31 @@ static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
 }
 
 
-static CPUReadMemoryFunc * const cirrus_linear_read[3] = {
-    cirrus_linear_readb,
-    cirrus_linear_readw,
-    cirrus_linear_readl,
-};
+static uint64_t cirrus_linear_read(MemoryRegion *mr, target_phys_addr_t addr,
+                                   unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
 
-static CPUWriteMemoryFunc * const cirrus_linear_write[3] = {
-    cirrus_linear_writeb,
-    cirrus_linear_writew,
-    cirrus_linear_writel,
-};
+    switch (size) {
+    case 1: return cirrus_linear_readb(s, addr);
+    case 2: return cirrus_linear_readw(s, addr);
+    case 4: return cirrus_linear_readl(s, addr);
+    default: abort();
+    }
+}
+
+static void cirrus_linear_write(MemoryRegion *mr, target_phys_addr_t addr,
+                                uint64_t data, unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
+
+    switch (size) {
+    case 1: return cirrus_linear_writeb(s, addr, data);
+    case 2: return cirrus_linear_writew(s, addr, data);
+    case 4: return cirrus_linear_writel(s, addr, data);
+    default: abort();
+    }
+}
 
 /***************************************
  *
@@ -2471,67 +2504,99 @@ static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
     cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
 }
 
+static uint64_t cirrus_linear_bitblt_read(MemoryRegion *mr,
+                                          target_phys_addr_t addr,
+                                          unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState,
+                                     cirrus_linear_bitblt_io);
 
-static CPUReadMemoryFunc * const cirrus_linear_bitblt_read[3] = {
-    cirrus_linear_bitblt_readb,
-    cirrus_linear_bitblt_readw,
-    cirrus_linear_bitblt_readl,
+    switch (size) {
+    case 1: return cirrus_linear_bitblt_readb(s, addr);
+    case 2: return cirrus_linear_bitblt_readw(s, addr);
+    case 4: return cirrus_linear_bitblt_readl(s, addr);
+    default: abort();
+    }
 };
 
-static CPUWriteMemoryFunc * const cirrus_linear_bitblt_write[3] = {
-    cirrus_linear_bitblt_writeb,
-    cirrus_linear_bitblt_writew,
-    cirrus_linear_bitblt_writel,
+static void cirrus_linear_bitblt_write(MemoryRegion *mr,
+                                       target_phys_addr_t addr,
+                                       uint64_t data,
+                                       unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState,
+                                     cirrus_linear_bitblt_io);
+
+    switch (size) {
+    case 1: return cirrus_linear_bitblt_writeb(s, addr, data);
+    case 2: return cirrus_linear_bitblt_writew(s, addr, data);
+    case 4: return cirrus_linear_bitblt_writel(s, addr, data);
+    default: abort();
+    }
 };
 
-static void map_linear_vram(CirrusVGAState *s)
+static MemoryRegionOps cirrus_linear_bitblt_io_ops = {
+    .read = cirrus_linear_bitblt_read,
+    .write = cirrus_linear_bitblt_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+#include "exec-memory.h"
+
+static void unmap_bank(CirrusVGAState *s, unsigned bank)
 {
-    if (!s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
-        s->vga.map_addr = s->vga.lfb_addr;
-        s->vga.map_end = s->vga.lfb_end;
-        cpu_register_physical_memory_log(s->vga.map_addr,
-					 s->vga.map_end - s->vga.map_addr,
-					 s->vga.vram_offset, 0, true);
+    if (s->cirrus_bank[bank]) {
+        memory_region_del_subregion(&s->low_mem_container,
+                                    s->cirrus_bank[bank]);
+        memory_region_destroy(s->cirrus_bank[bank]);
+        qemu_free(s->cirrus_bank[bank]);
+        s->cirrus_bank[bank] = NULL;
     }
+}
 
-    if (!s->vga.map_addr)
-        return;
-
-    s->vga.lfb_vram_mapped = 0;
+static void map_linear_vram_bank(CirrusVGAState *s, unsigned bank)
+{
+    MemoryRegion *mr;
+    static const char *names[] = { "vga.bank0", "vga.bank1" };
 
     if (!(s->cirrus_srcptr != s->cirrus_srcptr_end)
         && !((s->vga.sr[0x07] & 0x01) == 0)
         && !((s->vga.gr[0x0B] & 0x14) == 0x14)
         && !(s->vga.gr[0x0B] & 0x02)) {
 
-        cpu_register_physical_memory_log(isa_mem_base + 0xa0000, 0x8000,
-					 (s->vga.vram_offset +
-					  s->cirrus_bank_base[0]) |
-					 IO_MEM_RAM, 0, true);
-        cpu_register_physical_memory_log(isa_mem_base + 0xa8000, 0x8000,
-					 (s->vga.vram_offset +
-					  s->cirrus_bank_base[1]) |
-					 IO_MEM_RAM, 0, true);
-
-        s->vga.lfb_vram_mapped = 1;
-    }
-    else {
-        cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
-                                     s->vga.vga_io_memory);
+        mr = qemu_malloc(sizeof(*mr));
+        memory_region_init_alias(mr, names[bank], &s->vga.vram,
+                                 s->cirrus_bank_base[bank], 0x8000);
+        memory_region_add_subregion_overlap(
+            &s->low_mem_container,
+            0x8000 * bank,
+            mr,
+            1);
+        unmap_bank(s, bank);
+        s->cirrus_bank[bank] = mr;
+    } else {
+        unmap_bank(s, bank);
     }
+}
 
-    vga_dirty_log_start(&s->vga);
+static void map_linear_vram(CirrusVGAState *s)
+{
+    if (!s->linear_vram) {
+        s->linear_vram = true;
+        memory_region_add_subregion_overlap(&s->pci_bar, 0, &s->vga.vram, 1);
+    }
+    map_linear_vram_bank(s, 0);
+    map_linear_vram_bank(s, 1);
 }
 
 static void unmap_linear_vram(CirrusVGAState *s)
 {
-    if (s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
-        s->vga.map_addr = s->vga.map_end = 0;
-         cpu_register_physical_memory(s->vga.lfb_addr, s->vga.vram_size,
-                                      s->cirrus_linear_io_addr);
+    if (s->linear_vram) {
+        s->linear_vram = false;
+        memory_region_del_subregion(&s->pci_bar, &s->vga.vram);
     }
-    cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
-                                 s->vga.vga_io_memory);
+    unmap_bank(s, 0);
+    unmap_bank(s, 1);
 }
 
 /* Compute the memory access functions */
@@ -2829,16 +2894,36 @@ static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
 }
 
 
-static CPUReadMemoryFunc * const cirrus_mmio_read[3] = {
-    cirrus_mmio_readb,
-    cirrus_mmio_readw,
-    cirrus_mmio_readl,
+static uint64_t cirrus_mmio_read(MemoryRegion *mr, target_phys_addr_t addr,
+                                 unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
+
+    switch (size) {
+    case 1: return cirrus_mmio_readb(s, addr);
+    case 2: return cirrus_mmio_readw(s, addr);
+    case 4: return cirrus_mmio_readl(s, addr);
+    default: abort();
+    }
 };
 
-static CPUWriteMemoryFunc * const cirrus_mmio_write[3] = {
-    cirrus_mmio_writeb,
-    cirrus_mmio_writew,
-    cirrus_mmio_writel,
+static void cirrus_mmio_write(MemoryRegion *mr, target_phys_addr_t addr,
+                              uint64_t data, unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
+
+    switch (size) {
+    case 1: return cirrus_mmio_writeb(s, addr, data);
+    case 2: return cirrus_mmio_writew(s, addr, data);
+    case 4: return cirrus_mmio_writel(s, addr, data);
+    default: abort();
+    }
+};
+
+static MemoryRegionOps cirrus_mmio_io_ops = {
+    .read = cirrus_mmio_read,
+    .write = cirrus_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 /* load/save state */
@@ -2947,6 +3032,12 @@ static void cirrus_reset(void *opaque)
     s->cirrus_hidden_dac_data = 0;
 }
 
+static MemoryRegionOps cirrus_linear_io_ops = {
+    .read = cirrus_linear_read,
+    .write = cirrus_linear_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
 {
     int i;
@@ -2993,28 +3084,32 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
     register_ioport_read(0x3ba, 1, 1, cirrus_vga_ioport_read, s);
     register_ioport_read(0x3da, 1, 1, cirrus_vga_ioport_read, s);
 
-    s->vga.vga_io_memory = cpu_register_io_memory(cirrus_vga_mem_read,
-                                                  cirrus_vga_mem_write, s,
-                                                  DEVICE_LITTLE_ENDIAN);
-    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
-                                 s->vga.vga_io_memory);
-    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
+    memory_region_init(&s->low_mem_container,
+                       "cirrus-lowmem-container",
+                       0x20000);
+
+    memory_region_init_io(&s->low_mem, &cirrus_vga_mem_ops,
+                          "cirrus-low-memory", 0x20000);
+    memory_region_add_subregion(&s->low_mem_container, 0, &s->low_mem);
+    memory_region_add_subregion_overlap(get_system_memory(),
+                                        isa_mem_base + 0x000a0000,
+                                        &s->low_mem_container,
+                                        1);
+    memory_region_set_coalescing(&s->low_mem);
 
     /* I/O handler for LFB */
-    s->cirrus_linear_io_addr =
-        cpu_register_io_memory(cirrus_linear_read, cirrus_linear_write, s,
-                               DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&s->cirrus_linear_io, &cirrus_linear_io_ops,
+                          "cirrus-linear-io", VGA_RAM_SIZE);
 
     /* I/O handler for LFB */
-    s->cirrus_linear_bitblt_io_addr =
-        cpu_register_io_memory(cirrus_linear_bitblt_read,
-                               cirrus_linear_bitblt_write, s,
-                               DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&s->cirrus_linear_bitblt_io,
+                          &cirrus_linear_bitblt_io_ops,
+                          "cirrus-bitblt-mmio",
+                          0x400000);
 
     /* I/O handler for memory-mapped I/O */
-    s->cirrus_mmio_io_addr =
-        cpu_register_io_memory(cirrus_mmio_read, cirrus_mmio_write, s,
-                               DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&s->cirrus_mmio_io, &cirrus_mmio_io_ops,
+                          "cirrus-mmio", CIRRUS_PNPMMIO_SIZE);
 
     s->real_vram_size =
         (s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024;
@@ -3060,42 +3155,6 @@ void isa_cirrus_vga_init(void)
  *
  ***************************************/
 
-static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
-			       pcibus_t addr, pcibus_t size, int type)
-{
-    CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
-
-    /* XXX: add byte swapping apertures */
-    cpu_register_physical_memory(addr, s->vga.vram_size,
-				 s->cirrus_linear_io_addr);
-    cpu_register_physical_memory(addr + 0x1000000, 0x400000,
-				 s->cirrus_linear_bitblt_io_addr);
-
-    s->vga.map_addr = s->vga.map_end = 0;
-    s->vga.lfb_addr = addr & TARGET_PAGE_MASK;
-    s->vga.lfb_end = ((addr + VGA_RAM_SIZE) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
-    /* account for overflow */
-    if (s->vga.lfb_end < addr + VGA_RAM_SIZE)
-        s->vga.lfb_end = addr + VGA_RAM_SIZE;
-
-    vga_dirty_log_start(&s->vga);
-}
-
-static void pci_cirrus_write_config(PCIDevice *d,
-                                    uint32_t address, uint32_t val, int len)
-{
-    PCICirrusVGAState *pvs = DO_UPCAST(PCICirrusVGAState, dev, d);
-    CirrusVGAState *s = &pvs->cirrus_vga;
-
-    pci_default_write_config(d, address, val, len);
-    if (s->vga.map_addr && d->io_regions[0].addr == PCI_BAR_UNMAPPED) {
-        s->vga.map_addr = 0;
-        s->vga.lfb_addr = 0;
-        s->vga.lfb_end = 0;
-    }
-    cirrus_update_memory_access(s);
-}
-
 static int pci_cirrus_vga_initfn(PCIDevice *dev)
 {
      PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev);
@@ -3112,15 +3171,23 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
 
      /* setup PCI */
 
+    memory_region_init(&s->pci_bar, "cirrus-pci-bar0", 0x2000000);
+
+    /* XXX: add byte swapping apertures */
+    memory_region_add_subregion(&s->pci_bar, 0, &s->cirrus_linear_io);
+    memory_region_add_subregion(&s->pci_bar, 0x1000000,
+                                &s->cirrus_linear_bitblt_io);
+
+    vga_dirty_log_start(&s->vga);
+
      /* setup memory space */
      /* memory #0 LFB */
      /* memory #1 memory-mapped I/O */
      /* XXX: s->vga.vram_size must be a power of two */
-     pci_register_bar(&d->dev, 0, 0x2000000,
-                      PCI_BASE_ADDRESS_MEM_PREFETCH, cirrus_pci_lfb_map);
+     pci_register_bar_region(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH,
+                             &s->pci_bar);
      if (device_id == CIRRUS_ID_CLGD5446) {
-         pci_register_bar_simple(&d->dev, 1, CIRRUS_PNPMMIO_SIZE, 0,
-                                 s->cirrus_mmio_io_addr);
+         pci_register_bar_region(&d->dev, 1, 0, &s->cirrus_mmio_io);
      }
      return 0;
 }
@@ -3138,7 +3205,6 @@ static PCIDeviceInfo cirrus_vga_info = {
     .no_hotplug   = 1,
     .init         = pci_cirrus_vga_initfn,
     .romfile      = VGABIOS_CIRRUS_FILENAME,
-    .config_write = pci_cirrus_write_config,
     .vendor_id    = PCI_VENDOR_ID_CIRRUS,
     .device_id    = CIRRUS_ID_CLGD5446,
     .class_id     = PCI_CLASS_DISPLAY_VGA,
diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 4954bb1..2d6bedc 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -79,35 +79,67 @@ static void vga_mm_writel (void *opaque,
     vga_ioport_write(&s->vga, addr >> s->it_shift, value);
 }
 
-static CPUReadMemoryFunc * const vga_mm_read_ctrl[] = {
-    &vga_mm_readb,
-    &vga_mm_readw,
-    &vga_mm_readl,
-};
+static uint64_t vga_mm_read_ctrl(MemoryRegion *mr, target_phys_addr_t addr,
+                                 unsigned size)
+{
+    VGACommonState *vs = container_of(mr, VGAMemoryRegion, mem)->s;
+    ISAVGAMMState *s = container_of(vs, ISAVGAMMState, vga);
+
+    switch (size) {
+    case 1: return vga_mm_readb(s, addr);
+    case 2: return vga_mm_readw(s, addr);
+    case 4: return vga_mm_readl(s, addr);
+    default: abort();
+    }
+}
+
+static void vga_mm_write_ctrl(MemoryRegion *mr, target_phys_addr_t addr,
+                              uint64_t data, unsigned size)
+{
+    VGACommonState *vs = container_of(mr, VGAMemoryRegion, mem)->s;
+    ISAVGAMMState *s = container_of(vs, ISAVGAMMState, vga);
+
+    switch (size) {
+    case 1: return vga_mm_writeb(s, addr, data);
+    case 2: return vga_mm_writew(s, addr, data);
+    case 4: return vga_mm_writel(s, addr, data);
+    default: abort();
+    }
+}
 
-static CPUWriteMemoryFunc * const vga_mm_write_ctrl[] = {
-    &vga_mm_writeb,
-    &vga_mm_writew,
-    &vga_mm_writel,
+static MemoryRegionOps vga_mm_ctrl_ops = {
+    .read = vga_mm_read_ctrl,
+    .write = vga_mm_write_ctrl,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
+#include "exec-memory.h"
+
 static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base,
                         target_phys_addr_t ctrl_base, int it_shift)
 {
-    int s_ioport_ctrl, vga_io_memory;
+    VGAMemoryRegion *s_ioport_ctrl, *vga_io_memory;
 
     s->it_shift = it_shift;
-    s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
+    s_ioport_ctrl = qemu_malloc(sizeof(*s_ioport_ctrl));
+    memory_region_init_io(&s_ioport_ctrl->mem, &vga_mm_ctrl_ops, "vga-mm-ctrl",
+                          0x100000);
+    s_ioport_ctrl->s = &s->vga;
+
+    vga_io_memory = qemu_malloc(sizeof(*vga_io_memory));
+    /* XXX: endianness? */
+    memory_region_init_io(&vga_io_memory->mem, &vga_mem_ops, "vga-mem",
+                          0x20000);
+    vga_io_memory->s = &s->vga;
 
     vmstate_register(NULL, 0, &vmstate_vga_common, s);
 
-    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
+    memory_region_add_subregion(get_system_memory(), ctrl_base,
+                                &s_ioport_ctrl->mem);
     s->vga.bank_offset = 0;
-    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
-    qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
+    memory_region_add_subregion(get_system_memory(),
+                                vram_base + 0x000a0000, &vga_io_memory->mem);
+    memory_region_set_coalescing(&vga_io_memory->mem);
 }
 
 int isa_vga_mm_init(target_phys_addr_t vram_base,
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index 245841f..9fd282a 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -42,17 +42,22 @@ static void vga_reset_isa(DeviceState *dev)
     vga_common_reset(s);
 }
 
+#include "exec-memory.h"
+
 static int vga_initfn(ISADevice *dev)
 {
     ISAVGAState *d = DO_UPCAST(ISAVGAState, dev, dev);
     VGACommonState *s = &d->state;
-    int vga_io_memory;
+    VGAMemoryRegion *vga_io_memory;
 
     vga_common_init(s, VGA_RAM_SIZE);
     vga_io_memory = vga_init_io(s);
-    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
-                                 vga_io_memory);
-    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
+    memory_region_add_subregion_overlap(
+        get_system_memory(),
+        isa_mem_base + 0x000a0000,
+        &vga_io_memory->mem,
+        1);
+    memory_region_set_coalescing(&vga_io_memory->mem);
     isa_init_ioport(dev, 0x3c0);
     isa_init_ioport(dev, 0x3b4);
     isa_init_ioport(dev, 0x3ba);
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 481f448..7062c4d 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -47,29 +47,6 @@ static const VMStateDescription vmstate_vga_pci = {
     }
 };
 
-static void vga_map(PCIDevice *pci_dev, int region_num,
-                    pcibus_t addr, pcibus_t size, int type)
-{
-    PCIVGAState *d = (PCIVGAState *)pci_dev;
-    VGACommonState *s = &d->vga;
-
-    cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
-    s->map_addr = addr;
-    s->map_end = addr + s->vram_size;
-    vga_dirty_log_start(s);
-}
-
-static void pci_vga_write_config(PCIDevice *d,
-                                 uint32_t address, uint32_t val, int len)
-{
-    PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
-    VGACommonState *s = &pvs->vga;
-
-    pci_default_write_config(d, address, val, len);
-    if (s->map_addr && pvs->dev.io_regions[0].addr == -1)
-        s->map_addr = 0;
-}
-
 static int pci_vga_initfn(PCIDevice *dev)
 {
      PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
@@ -83,8 +60,8 @@ static int pci_vga_initfn(PCIDevice *dev)
                                   s->screen_dump, s->text_update, s);
 
      /* XXX: VGA_RAM_SIZE must be a power of two */
-     pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
-                      PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
+     pci_register_bar_region(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH,
+                             &s->vram);
 
      if (!dev->rom_bar) {
          /* compatibility with pc-0.13 and older */
@@ -106,7 +83,6 @@ static PCIDeviceInfo vga_info = {
     .qdev.vmsd    = &vmstate_vga_pci,
     .no_hotplug   = 1,
     .init         = pci_vga_initfn,
-    .config_write = pci_vga_write_config,
     .romfile      = "vgabios-stdvga.bin",
 
     /* dummy VGA (same as Bochs ID) */
diff --git a/hw/vga.c b/hw/vga.c
index 0f54734..7f7aeb1 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -825,7 +825,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
 #endif
             s->plane_updated |= mask; /* only used to detect font change */
-            cpu_physical_memory_set_dirty(s->vram_offset + addr);
+            memory_region_set_dirty(&s->vram, addr);
         }
     } else if (s->gr[5] & 0x10) {
         /* odd/even mode (aka text mode mapping) */
@@ -838,7 +838,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
 #endif
             s->plane_updated |= mask; /* only used to detect font change */
-            cpu_physical_memory_set_dirty(s->vram_offset + addr);
+            memory_region_set_dirty(&s->vram, addr);
         }
     } else {
         /* standard VGA latched access */
@@ -912,7 +912,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
         printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
                addr * 4, write_mask, val);
 #endif
-        cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
+        memory_region_set_dirty(&s->vram, addr << 2);
     }
 }
 
@@ -1553,57 +1553,17 @@ void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
 
 static void vga_sync_dirty_bitmap(VGACommonState *s)
 {
-    if (s->map_addr)
-        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
-
-    if (s->lfb_vram_mapped) {
-        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
-        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
-    }
-
-#ifdef CONFIG_BOCHS_VBE
-    if (s->vbe_mapped) {
-        cpu_physical_sync_dirty_bitmap(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
-                                       VBE_DISPI_LFB_PHYSICAL_ADDRESS + s->vram_size);
-    }
-#endif
-
+    memory_region_sync_dirty_bitmap(&s->vram);
 }
 
 void vga_dirty_log_start(VGACommonState *s)
 {
-    if (s->map_addr) {
-        cpu_physical_log_start(s->map_addr, s->map_end - s->map_addr);
-    }
-
-    if (s->lfb_vram_mapped) {
-        cpu_physical_log_start(isa_mem_base + 0xa0000, 0x8000);
-        cpu_physical_log_start(isa_mem_base + 0xa8000, 0x8000);
-    }
-
-#ifdef CONFIG_BOCHS_VBE
-    if (s->vbe_mapped) {
-        cpu_physical_log_start(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
-    }
-#endif
+    memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
 }
 
 void vga_dirty_log_stop(VGACommonState *s)
 {
-    if (s->map_addr) {
-        cpu_physical_log_stop(s->map_addr, s->map_end - s->map_addr);
-    }
-
-    if (s->lfb_vram_mapped) {
-        cpu_physical_log_stop(isa_mem_base + 0xa0000, 0x8000);
-        cpu_physical_log_stop(isa_mem_base + 0xa8000, 0x8000);
-    }
-
-#ifdef CONFIG_BOCHS_VBE
-    if (s->vbe_mapped) {
-        cpu_physical_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
-    }
-#endif
+    memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
 }
 
 void vga_dirty_log_restart(VGACommonState *s)
@@ -1773,15 +1733,16 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         if (!(s->cr[0x17] & 2)) {
             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
         }
-        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
-        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
+        page0 = addr & TARGET_PAGE_MASK;
+        page1 = (addr + bwidth - 1) & TARGET_PAGE_MASK;
         update = full_update |
-            cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
-            cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
+            memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
+            memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
         if ((page1 - page0) > TARGET_PAGE_SIZE) {
             /* if wide line, can use another page */
-            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
-                                                    VGA_DIRTY_FLAG);
+            update |= memory_region_get_dirty(&s->vram,
+                                              page0 + TARGET_PAGE_SIZE,
+                                              DIRTY_MEMORY_VGA);
         }
         /* explicit invalidation for the hardware cursor */
         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
@@ -1826,8 +1787,10 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     }
     /* reset modified pages */
     if (page_max >= page_min) {
-        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
-                                        VGA_DIRTY_FLAG);
+        memory_region_reset_dirty(&s->vram,
+                                  page_min,
+                                  page_max + TARGET_PAGE_SIZE - page_min,
+                                  DIRTY_MEMORY_VGA);
     }
     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
 }
@@ -1906,11 +1869,6 @@ static void vga_invalidate_display(void *opaque)
 
 void vga_common_reset(VGACommonState *s)
 {
-    s->lfb_addr = 0;
-    s->lfb_end = 0;
-    s->map_addr = 0;
-    s->map_end = 0;
-    s->lfb_vram_mapped = 0;
     s->sr_index = 0;
     memset(s->sr, '\0', sizeof(s->sr));
     s->gr_index = 0;
@@ -2141,16 +2099,36 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
     dpy_update(s->ds, 0, 0, s->last_width, height);
 }
 
-CPUReadMemoryFunc * const vga_mem_read[3] = {
-    vga_mem_readb,
-    vga_mem_readw,
-    vga_mem_readl,
-};
+static uint64_t vga_mem_read(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned size)
+{
+    VGACommonState *s = container_of(mr, VGAMemoryRegion, mem)->s;
+
+    switch (size) {
+    case 1: return vga_mem_readb(s, addr);
+    case 2: return vga_mem_readw(s, addr);
+    case 4: return vga_mem_readl(s, addr);
+    default: abort();
+    }
+}
 
-CPUWriteMemoryFunc * const vga_mem_write[3] = {
-    vga_mem_writeb,
-    vga_mem_writew,
-    vga_mem_writel,
+static void vga_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
+                          uint64_t data, unsigned size)
+{
+    VGACommonState *s = container_of(mr, VGAMemoryRegion, mem)->s;
+
+    switch (size) {
+    case 1: return vga_mem_writeb(s, addr, data);
+    case 2: return vga_mem_writew(s, addr, data);
+    case 4: return vga_mem_writel(s, addr, data);
+    default: abort();
+    }
+}
+
+MemoryRegionOps vga_mem_ops = {
+    .read = vga_mem_read,
+    .write = vga_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static int vga_common_post_load(void *opaque, int version_id)
@@ -2236,8 +2214,8 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
 #else
     s->is_vbe_vmstate = 0;
 #endif
-    s->vram_offset = qemu_ram_alloc(NULL, "vga.vram", vga_ram_size);
-    s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
+    memory_region_init_ram(&s->vram, NULL, "vga.vram", vga_ram_size);
+    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
     s->vram_size = vga_ram_size;
     s->get_bpp = vga_get_bpp;
     s->get_offsets = vga_get_offsets;
@@ -2260,8 +2238,10 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
 }
 
 /* used by both ISA and PCI */
-int vga_init_io(VGACommonState *s)
+VGAMemoryRegion *vga_init_io(VGACommonState *s)
 {
+    VGAMemoryRegion *vga_mem;
+
     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
 
     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
@@ -2292,30 +2272,38 @@ int vga_init_io(VGACommonState *s)
 #endif
 #endif /* CONFIG_BOCHS_VBE */
 
-    return cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
-                                  DEVICE_LITTLE_ENDIAN);
+    vga_mem = qemu_malloc(sizeof(*vga_mem));
+    memory_region_init_io(&vga_mem->mem, &vga_mem_ops, "vga-lowmem", 0x20000);
+    vga_mem->s = s;
+
+    return vga_mem;
 }
 
+#include "exec-memory.h"
+
 void vga_init(VGACommonState *s)
 {
-    int vga_io_memory;
+    VGAMemoryRegion *vga_io_memory;
 
     qemu_register_reset(vga_reset, s);
 
     s->bank_offset = 0;
 
     vga_io_memory = vga_init_io(s);
-    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
-                                 vga_io_memory);
-    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
+    memory_region_add_subregion_overlap(get_system_memory(),
+                                        isa_mem_base + 0x000a0000,
+                                        &vga_io_memory->mem,
+                                        1);
+    memory_region_set_coalescing(&vga_io_memory->mem);
 }
 
 void vga_init_vbe(VGACommonState *s)
 {
 #ifdef CONFIG_BOCHS_VBE
     /* XXX: use optimized standard vga accesses */
-    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
-                                 VGA_RAM_SIZE, s->vram_offset);
+    memory_region_add_subregion(get_system_memory(),
+                                VBE_DISPI_LFB_PHYSICAL_ADDRESS,
+                                &s->vram);
     s->vbe_mapped = 1;
 #endif 
 }
diff --git a/hw/vga_int.h b/hw/vga_int.h
index d2811bd..0ef9962 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -23,6 +23,7 @@
  */
 
 #include <hw/hw.h>
+#include "memory.h"
 
 #define MSR_COLOR_EMULATION 0x01
 #define MSR_PAGE_SELECT     0x20
@@ -103,15 +104,15 @@ struct VGACommonState;
 typedef uint8_t (* vga_retrace_fn)(struct VGACommonState *s);
 typedef void (* vga_update_retrace_info_fn)(struct VGACommonState *s);
 
+typedef struct VGAMemoryRegion {
+    MemoryRegion mem;
+    struct VGACommonState *s;
+} VGAMemoryRegion;
+
 typedef struct VGACommonState {
     uint8_t *vram_ptr;
-    ram_addr_t vram_offset;
+    MemoryRegion vram;
     uint32_t vram_size;
-    uint32_t lfb_addr;
-    uint32_t lfb_end;
-    uint32_t map_addr;
-    uint32_t map_end;
-    uint32_t lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */
     uint32_t latch;
     uint8_t sr_index;
     uint8_t sr[256];
@@ -134,7 +135,7 @@ typedef struct VGACommonState {
     int dac_8bit;
     uint8_t palette[768];
     int32_t bank_offset;
-    int vga_io_memory;
+    VGAMemoryRegion *vga_io_memory;
     int (*get_bpp)(struct VGACommonState *s);
     void (*get_offsets)(struct VGACommonState *s,
                         uint32_t *pline_offset,
@@ -191,7 +192,7 @@ static inline int c6_to_8(int v)
 
 void vga_common_init(VGACommonState *s, int vga_ram_size);
 void vga_init(VGACommonState *s);
-int vga_init_io(VGACommonState *s);
+VGAMemoryRegion *vga_init_io(VGACommonState *s);
 void vga_common_reset(VGACommonState *s);
 
 void vga_dirty_log_start(VGACommonState *s);
@@ -229,5 +230,4 @@ extern const uint8_t gr_mask[16];
 #define VGABIOS_FILENAME "vgabios.bin"
 #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
 
-extern CPUReadMemoryFunc * const vga_mem_read[3];
-extern CPUWriteMemoryFunc * const vga_mem_write[3];
+extern MemoryRegionOps vga_mem_ops;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 190b005..cd7c508 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1135,17 +1135,45 @@ static void vmsvga_vram_writel(void *opaque, target_phys_addr_t addr,
         *(uint32_t *) (s->vram_ptr + addr) = value;
 }
 
-static CPUReadMemoryFunc * const vmsvga_vram_read[] = {
-    vmsvga_vram_readb,
-    vmsvga_vram_readw,
-    vmsvga_vram_readl,
-};
+typedef struct DirectMem DirectMem;
 
-static CPUWriteMemoryFunc * const vmsvga_vram_write[] = {
-    vmsvga_vram_writeb,
-    vmsvga_vram_writew,
-    vmsvga_vram_writel,
+struct DirectMem {
+    MemoryRegion mr;
+    struct vmsvga_state_s *chip;
 };
+
+static uint64_t vmsvga_vram_read(MemoryRegion *mr, target_phys_addr_t addr,
+                                 unsigned size)
+{
+    struct vmsvga_state_s *s = container_of(mr, DirectMem, iomem)->chip;
+
+    switch (size) {
+    case 1: return vmsvga_vram_readb(s, addr);
+    case 2: return vmsvga_vram_readw(s, addr);
+    case 4: return vmsvga_vram_readl(s, addr);
+    default: abort();
+    }
+}
+
+static void vmsvga_vram_read(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned size, uint64_t data)
+{
+    struct vmsvga_state_s *s = container_of(mr, DirectMem, iomem)->chip;
+
+    switch (size) {
+    case 1: return vmsvga_vram_writeb(s, addr, data);
+    case 2: return vmsvga_vram_writew(s, addr, data);
+    case 4: return vmsvga_vram_writel(s, addr, data);
+    default: abort();
+    }
+}
+
+static MemoryRegionOps vmsvga_vram_io_ops = {
+    .read = vmsvga_vram_read,
+    .write = vmsvga_vram_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+}
+
 #endif
 
 static int vmsvga_post_load(void *opaque, int version_id)
@@ -1241,27 +1269,6 @@ static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
                     1, 4, vmsvga_bios_write, s);
 }
 
-static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
-                pcibus_t addr, pcibus_t size, int type)
-{
-    struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
-    struct vmsvga_state_s *s = &d->chip;
-    ram_addr_t iomemtype;
-
-#ifdef DIRECT_VRAM
-    iomemtype = cpu_register_io_memory(vmsvga_vram_read,
-                    vmsvga_vram_write, s, DEVICE_NATIVE_ENDIAN);
-#else
-    iomemtype = s->vga.vram_offset | IO_MEM_RAM;
-#endif
-    cpu_register_physical_memory(addr, s->vga.vram_size,
-                    iomemtype);
-
-    s->vga.map_addr = addr;
-    s->vga.map_end = addr + s->vga.vram_size;
-    vga_dirty_log_restart(&s->vga);
-}
-
 static void pci_vmsvga_map_fifo(PCIDevice *pci_dev, int region_num,
                 pcibus_t addr, pcibus_t size, int type)
 {
@@ -1279,6 +1286,20 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
 {
     struct pci_vmsvga_state_s *s =
         DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
+    MemoryRegion *iomem;
+
+#ifdef DIRECT_VRAM
+    DirectMem *directmem = qemu_malloc(sizeof(*directmem));
+
+    directmem->chip = &s->chip;
+    iomem = &directmem->mr;
+    memory_region_init_io(iomem, &vmsvga_vram_io_ops, "vmsvga",
+                          memory_region_size(&s->chip.vga.vram));
+#else
+    iomem = &s->chip.vga.vram;
+#endif
+
+    vga_dirty_log_restart(&s->chip.vga);
 
     s->card.config[PCI_CACHE_LINE_SIZE]	= 0x08;		/* Cache line size */
     s->card.config[PCI_LATENCY_TIMER] = 0x40;		/* Latency timer */
@@ -1286,8 +1307,7 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
 
     pci_register_bar(&s->card, 0, 0x10,
                     PCI_BASE_ADDRESS_SPACE_IO, pci_vmsvga_map_ioport);
-    pci_register_bar(&s->card, 1, VGA_RAM_SIZE,
-                    PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_mem);
+    pci_register_bar_region(&s->card, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, iomem);
 
     pci_register_bar(&s->card, 2, SVGA_FIFO_SIZE,
                     PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_fifo);
-- 
1.7.5.3


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

* [Qemu-devel] [RFC v2 15/20] vga: convert vga and its derivatives to the memory API
@ 2011-06-27 13:22   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Convert all vga memory to the memory API.  Note we need to fall back to
get_system_memory(), since the various buses don't pass the vga window
as a memory region.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |  346 +++++++++++++++++++++++++++++++++----------------------
 hw/vga-isa-mm.c |   66 ++++++++---
 hw/vga-isa.c    |   13 ++-
 hw/vga-pci.c    |   28 +----
 hw/vga.c        |  146 +++++++++++-------------
 hw/vga_int.h    |   20 ++--
 hw/vmware_vga.c |   84 ++++++++-----
 7 files changed, 395 insertions(+), 308 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index f39d1f8..0cce453 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -200,9 +200,14 @@ typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
 typedef struct CirrusVGAState {
     VGACommonState vga;
 
-    int cirrus_linear_io_addr;
-    int cirrus_linear_bitblt_io_addr;
-    int cirrus_mmio_io_addr;
+    MemoryRegion cirrus_linear_io;
+    MemoryRegion cirrus_linear_bitblt_io;
+    MemoryRegion cirrus_mmio_io;
+    MemoryRegion pci_bar;
+    bool linear_vram;  /* vga.vram mapped over cirrus_linear_io */
+    MemoryRegion low_mem_container; /* container for 0xa0000-0xc0000 */
+    MemoryRegion low_mem;           /* always mapped, overridden by: */
+    MemoryRegion *cirrus_bank[2];   /*   aliases at 0xa0000-0xb0000  */
     uint32_t cirrus_addr_mask;
     uint32_t linear_mmio_mask;
     uint8_t cirrus_shadow_gr0;
@@ -612,7 +617,7 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
 	off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
 	off_cur &= TARGET_PAGE_MASK;
 	while (off_cur < off_cur_end) {
-	    cpu_physical_memory_set_dirty(s->vga.vram_offset + off_cur);
+	    memory_region_set_dirty(&s->vga.vram, off_cur);
 	    off_cur += TARGET_PAGE_SIZE;
 	}
 	off_begin += off_pitch;
@@ -1177,12 +1182,6 @@ static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
     }
 
     if (limit > 0) {
-        /* Thinking about changing bank base? First, drop the dirty bitmap information
-         * on the current location, otherwise we lose this pointer forever */
-        if (s->vga.lfb_vram_mapped) {
-            target_phys_addr_t base_addr = isa_mem_base + 0xa0000 + bank_index * 0x8000;
-            cpu_physical_sync_dirty_bitmap(base_addr, base_addr + 0x8000);
-        }
 	s->cirrus_bank_base[bank_index] = offset;
 	s->cirrus_bank_limit[bank_index] = limit;
     } else {
@@ -1921,8 +1920,8 @@ static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
 	val <<= 1;
 	dst++;
     }
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset);
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset + 7);
+    memory_region_set_dirty(&s->vga.vram, offset);
+    memory_region_set_dirty(&s->vga.vram, offset + 7);
 }
 
 static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
@@ -1946,8 +1945,8 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
 	val <<= 1;
 	dst += 2;
     }
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset);
-    cpu_physical_memory_set_dirty(s->vga.vram_offset + offset + 15);
+    memory_region_set_dirty(&s->vga.vram, offset);
+    memory_region_set_dirty(&s->vga.vram, offset + 15);
 }
 
 /***************************************
@@ -2057,8 +2056,7 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
 		mode = s->vga.gr[0x05] & 0x7;
 		if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
 		    *(s->vga.vram_ptr + bank_offset) = mem_value;
-		    cpu_physical_memory_set_dirty(s->vga.vram_offset +
-						  bank_offset);
+		    memory_region_set_dirty(&s->vga.vram, bank_offset);
 		} else {
 		    if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
 			cirrus_mem_writeb_mode4and5_8bpp(s, mode,
@@ -2099,16 +2097,37 @@ static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_
     cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
 }
 
-static CPUReadMemoryFunc * const cirrus_vga_mem_read[3] = {
-    cirrus_vga_mem_readb,
-    cirrus_vga_mem_readw,
-    cirrus_vga_mem_readl,
+static uint64_t cirrus_vga_mem_read(MemoryRegion *mr,
+                                    target_phys_addr_t addr,
+                                    uint32_t size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
+
+    switch (size) {
+    case 1: return cirrus_vga_mem_readb(s, addr);
+    case 2: return cirrus_vga_mem_readw(s, addr);
+    case 4: return cirrus_vga_mem_readl(s, addr);
+    default: abort();
+    }
+}
+
+static void cirrus_vga_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
+                                 uint64_t data, unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
+
+    switch (size) {
+    case 1: return cirrus_vga_mem_writeb(s, addr, data);
+    case 2: return cirrus_vga_mem_writew(s, addr, data);
+    case 4: return cirrus_vga_mem_writel(s, addr, data);
+    default: abort();
+    }
 };
 
-static CPUWriteMemoryFunc * const cirrus_vga_mem_write[3] = {
-    cirrus_vga_mem_writeb,
-    cirrus_vga_mem_writew,
-    cirrus_vga_mem_writel,
+static MemoryRegionOps cirrus_vga_mem_ops = {
+    .read = cirrus_vga_mem_read,
+    .write = cirrus_vga_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 /***************************************
@@ -2365,7 +2384,7 @@ static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
 	mode = s->vga.gr[0x05] & 0x7;
 	if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
 	    *(s->vga.vram_ptr + addr) = (uint8_t) val;
-	    cpu_physical_memory_set_dirty(s->vga.vram_offset + addr);
+	    memory_region_set_dirty(&s->vga.vram, addr);
 	} else {
 	    if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
 		cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
@@ -2393,17 +2412,31 @@ static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
 }
 
 
-static CPUReadMemoryFunc * const cirrus_linear_read[3] = {
-    cirrus_linear_readb,
-    cirrus_linear_readw,
-    cirrus_linear_readl,
-};
+static uint64_t cirrus_linear_read(MemoryRegion *mr, target_phys_addr_t addr,
+                                   unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
 
-static CPUWriteMemoryFunc * const cirrus_linear_write[3] = {
-    cirrus_linear_writeb,
-    cirrus_linear_writew,
-    cirrus_linear_writel,
-};
+    switch (size) {
+    case 1: return cirrus_linear_readb(s, addr);
+    case 2: return cirrus_linear_readw(s, addr);
+    case 4: return cirrus_linear_readl(s, addr);
+    default: abort();
+    }
+}
+
+static void cirrus_linear_write(MemoryRegion *mr, target_phys_addr_t addr,
+                                uint64_t data, unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
+
+    switch (size) {
+    case 1: return cirrus_linear_writeb(s, addr, data);
+    case 2: return cirrus_linear_writew(s, addr, data);
+    case 4: return cirrus_linear_writel(s, addr, data);
+    default: abort();
+    }
+}
 
 /***************************************
  *
@@ -2471,67 +2504,99 @@ static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
     cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
 }
 
+static uint64_t cirrus_linear_bitblt_read(MemoryRegion *mr,
+                                          target_phys_addr_t addr,
+                                          unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState,
+                                     cirrus_linear_bitblt_io);
 
-static CPUReadMemoryFunc * const cirrus_linear_bitblt_read[3] = {
-    cirrus_linear_bitblt_readb,
-    cirrus_linear_bitblt_readw,
-    cirrus_linear_bitblt_readl,
+    switch (size) {
+    case 1: return cirrus_linear_bitblt_readb(s, addr);
+    case 2: return cirrus_linear_bitblt_readw(s, addr);
+    case 4: return cirrus_linear_bitblt_readl(s, addr);
+    default: abort();
+    }
 };
 
-static CPUWriteMemoryFunc * const cirrus_linear_bitblt_write[3] = {
-    cirrus_linear_bitblt_writeb,
-    cirrus_linear_bitblt_writew,
-    cirrus_linear_bitblt_writel,
+static void cirrus_linear_bitblt_write(MemoryRegion *mr,
+                                       target_phys_addr_t addr,
+                                       uint64_t data,
+                                       unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState,
+                                     cirrus_linear_bitblt_io);
+
+    switch (size) {
+    case 1: return cirrus_linear_bitblt_writeb(s, addr, data);
+    case 2: return cirrus_linear_bitblt_writew(s, addr, data);
+    case 4: return cirrus_linear_bitblt_writel(s, addr, data);
+    default: abort();
+    }
 };
 
-static void map_linear_vram(CirrusVGAState *s)
+static MemoryRegionOps cirrus_linear_bitblt_io_ops = {
+    .read = cirrus_linear_bitblt_read,
+    .write = cirrus_linear_bitblt_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+#include "exec-memory.h"
+
+static void unmap_bank(CirrusVGAState *s, unsigned bank)
 {
-    if (!s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
-        s->vga.map_addr = s->vga.lfb_addr;
-        s->vga.map_end = s->vga.lfb_end;
-        cpu_register_physical_memory_log(s->vga.map_addr,
-					 s->vga.map_end - s->vga.map_addr,
-					 s->vga.vram_offset, 0, true);
+    if (s->cirrus_bank[bank]) {
+        memory_region_del_subregion(&s->low_mem_container,
+                                    s->cirrus_bank[bank]);
+        memory_region_destroy(s->cirrus_bank[bank]);
+        qemu_free(s->cirrus_bank[bank]);
+        s->cirrus_bank[bank] = NULL;
     }
+}
 
-    if (!s->vga.map_addr)
-        return;
-
-    s->vga.lfb_vram_mapped = 0;
+static void map_linear_vram_bank(CirrusVGAState *s, unsigned bank)
+{
+    MemoryRegion *mr;
+    static const char *names[] = { "vga.bank0", "vga.bank1" };
 
     if (!(s->cirrus_srcptr != s->cirrus_srcptr_end)
         && !((s->vga.sr[0x07] & 0x01) == 0)
         && !((s->vga.gr[0x0B] & 0x14) == 0x14)
         && !(s->vga.gr[0x0B] & 0x02)) {
 
-        cpu_register_physical_memory_log(isa_mem_base + 0xa0000, 0x8000,
-					 (s->vga.vram_offset +
-					  s->cirrus_bank_base[0]) |
-					 IO_MEM_RAM, 0, true);
-        cpu_register_physical_memory_log(isa_mem_base + 0xa8000, 0x8000,
-					 (s->vga.vram_offset +
-					  s->cirrus_bank_base[1]) |
-					 IO_MEM_RAM, 0, true);
-
-        s->vga.lfb_vram_mapped = 1;
-    }
-    else {
-        cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
-                                     s->vga.vga_io_memory);
+        mr = qemu_malloc(sizeof(*mr));
+        memory_region_init_alias(mr, names[bank], &s->vga.vram,
+                                 s->cirrus_bank_base[bank], 0x8000);
+        memory_region_add_subregion_overlap(
+            &s->low_mem_container,
+            0x8000 * bank,
+            mr,
+            1);
+        unmap_bank(s, bank);
+        s->cirrus_bank[bank] = mr;
+    } else {
+        unmap_bank(s, bank);
     }
+}
 
-    vga_dirty_log_start(&s->vga);
+static void map_linear_vram(CirrusVGAState *s)
+{
+    if (!s->linear_vram) {
+        s->linear_vram = true;
+        memory_region_add_subregion_overlap(&s->pci_bar, 0, &s->vga.vram, 1);
+    }
+    map_linear_vram_bank(s, 0);
+    map_linear_vram_bank(s, 1);
 }
 
 static void unmap_linear_vram(CirrusVGAState *s)
 {
-    if (s->vga.map_addr && s->vga.lfb_addr && s->vga.lfb_end) {
-        s->vga.map_addr = s->vga.map_end = 0;
-         cpu_register_physical_memory(s->vga.lfb_addr, s->vga.vram_size,
-                                      s->cirrus_linear_io_addr);
+    if (s->linear_vram) {
+        s->linear_vram = false;
+        memory_region_del_subregion(&s->pci_bar, &s->vga.vram);
     }
-    cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
-                                 s->vga.vga_io_memory);
+    unmap_bank(s, 0);
+    unmap_bank(s, 1);
 }
 
 /* Compute the memory access functions */
@@ -2829,16 +2894,36 @@ static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
 }
 
 
-static CPUReadMemoryFunc * const cirrus_mmio_read[3] = {
-    cirrus_mmio_readb,
-    cirrus_mmio_readw,
-    cirrus_mmio_readl,
+static uint64_t cirrus_mmio_read(MemoryRegion *mr, target_phys_addr_t addr,
+                                 unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
+
+    switch (size) {
+    case 1: return cirrus_mmio_readb(s, addr);
+    case 2: return cirrus_mmio_readw(s, addr);
+    case 4: return cirrus_mmio_readl(s, addr);
+    default: abort();
+    }
 };
 
-static CPUWriteMemoryFunc * const cirrus_mmio_write[3] = {
-    cirrus_mmio_writeb,
-    cirrus_mmio_writew,
-    cirrus_mmio_writel,
+static void cirrus_mmio_write(MemoryRegion *mr, target_phys_addr_t addr,
+                              uint64_t data, unsigned size)
+{
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
+
+    switch (size) {
+    case 1: return cirrus_mmio_writeb(s, addr, data);
+    case 2: return cirrus_mmio_writew(s, addr, data);
+    case 4: return cirrus_mmio_writel(s, addr, data);
+    default: abort();
+    }
+};
+
+static MemoryRegionOps cirrus_mmio_io_ops = {
+    .read = cirrus_mmio_read,
+    .write = cirrus_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 /* load/save state */
@@ -2947,6 +3032,12 @@ static void cirrus_reset(void *opaque)
     s->cirrus_hidden_dac_data = 0;
 }
 
+static MemoryRegionOps cirrus_linear_io_ops = {
+    .read = cirrus_linear_read,
+    .write = cirrus_linear_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
 static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
 {
     int i;
@@ -2993,28 +3084,32 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
     register_ioport_read(0x3ba, 1, 1, cirrus_vga_ioport_read, s);
     register_ioport_read(0x3da, 1, 1, cirrus_vga_ioport_read, s);
 
-    s->vga.vga_io_memory = cpu_register_io_memory(cirrus_vga_mem_read,
-                                                  cirrus_vga_mem_write, s,
-                                                  DEVICE_LITTLE_ENDIAN);
-    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
-                                 s->vga.vga_io_memory);
-    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
+    memory_region_init(&s->low_mem_container,
+                       "cirrus-lowmem-container",
+                       0x20000);
+
+    memory_region_init_io(&s->low_mem, &cirrus_vga_mem_ops,
+                          "cirrus-low-memory", 0x20000);
+    memory_region_add_subregion(&s->low_mem_container, 0, &s->low_mem);
+    memory_region_add_subregion_overlap(get_system_memory(),
+                                        isa_mem_base + 0x000a0000,
+                                        &s->low_mem_container,
+                                        1);
+    memory_region_set_coalescing(&s->low_mem);
 
     /* I/O handler for LFB */
-    s->cirrus_linear_io_addr =
-        cpu_register_io_memory(cirrus_linear_read, cirrus_linear_write, s,
-                               DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&s->cirrus_linear_io, &cirrus_linear_io_ops,
+                          "cirrus-linear-io", VGA_RAM_SIZE);
 
     /* I/O handler for LFB */
-    s->cirrus_linear_bitblt_io_addr =
-        cpu_register_io_memory(cirrus_linear_bitblt_read,
-                               cirrus_linear_bitblt_write, s,
-                               DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&s->cirrus_linear_bitblt_io,
+                          &cirrus_linear_bitblt_io_ops,
+                          "cirrus-bitblt-mmio",
+                          0x400000);
 
     /* I/O handler for memory-mapped I/O */
-    s->cirrus_mmio_io_addr =
-        cpu_register_io_memory(cirrus_mmio_read, cirrus_mmio_write, s,
-                               DEVICE_LITTLE_ENDIAN);
+    memory_region_init_io(&s->cirrus_mmio_io, &cirrus_mmio_io_ops,
+                          "cirrus-mmio", CIRRUS_PNPMMIO_SIZE);
 
     s->real_vram_size =
         (s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024;
@@ -3060,42 +3155,6 @@ void isa_cirrus_vga_init(void)
  *
  ***************************************/
 
-static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
-			       pcibus_t addr, pcibus_t size, int type)
-{
-    CirrusVGAState *s = &DO_UPCAST(PCICirrusVGAState, dev, d)->cirrus_vga;
-
-    /* XXX: add byte swapping apertures */
-    cpu_register_physical_memory(addr, s->vga.vram_size,
-				 s->cirrus_linear_io_addr);
-    cpu_register_physical_memory(addr + 0x1000000, 0x400000,
-				 s->cirrus_linear_bitblt_io_addr);
-
-    s->vga.map_addr = s->vga.map_end = 0;
-    s->vga.lfb_addr = addr & TARGET_PAGE_MASK;
-    s->vga.lfb_end = ((addr + VGA_RAM_SIZE) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
-    /* account for overflow */
-    if (s->vga.lfb_end < addr + VGA_RAM_SIZE)
-        s->vga.lfb_end = addr + VGA_RAM_SIZE;
-
-    vga_dirty_log_start(&s->vga);
-}
-
-static void pci_cirrus_write_config(PCIDevice *d,
-                                    uint32_t address, uint32_t val, int len)
-{
-    PCICirrusVGAState *pvs = DO_UPCAST(PCICirrusVGAState, dev, d);
-    CirrusVGAState *s = &pvs->cirrus_vga;
-
-    pci_default_write_config(d, address, val, len);
-    if (s->vga.map_addr && d->io_regions[0].addr == PCI_BAR_UNMAPPED) {
-        s->vga.map_addr = 0;
-        s->vga.lfb_addr = 0;
-        s->vga.lfb_end = 0;
-    }
-    cirrus_update_memory_access(s);
-}
-
 static int pci_cirrus_vga_initfn(PCIDevice *dev)
 {
      PCICirrusVGAState *d = DO_UPCAST(PCICirrusVGAState, dev, dev);
@@ -3112,15 +3171,23 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
 
      /* setup PCI */
 
+    memory_region_init(&s->pci_bar, "cirrus-pci-bar0", 0x2000000);
+
+    /* XXX: add byte swapping apertures */
+    memory_region_add_subregion(&s->pci_bar, 0, &s->cirrus_linear_io);
+    memory_region_add_subregion(&s->pci_bar, 0x1000000,
+                                &s->cirrus_linear_bitblt_io);
+
+    vga_dirty_log_start(&s->vga);
+
      /* setup memory space */
      /* memory #0 LFB */
      /* memory #1 memory-mapped I/O */
      /* XXX: s->vga.vram_size must be a power of two */
-     pci_register_bar(&d->dev, 0, 0x2000000,
-                      PCI_BASE_ADDRESS_MEM_PREFETCH, cirrus_pci_lfb_map);
+     pci_register_bar_region(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH,
+                             &s->pci_bar);
      if (device_id == CIRRUS_ID_CLGD5446) {
-         pci_register_bar_simple(&d->dev, 1, CIRRUS_PNPMMIO_SIZE, 0,
-                                 s->cirrus_mmio_io_addr);
+         pci_register_bar_region(&d->dev, 1, 0, &s->cirrus_mmio_io);
      }
      return 0;
 }
@@ -3138,7 +3205,6 @@ static PCIDeviceInfo cirrus_vga_info = {
     .no_hotplug   = 1,
     .init         = pci_cirrus_vga_initfn,
     .romfile      = VGABIOS_CIRRUS_FILENAME,
-    .config_write = pci_cirrus_write_config,
     .vendor_id    = PCI_VENDOR_ID_CIRRUS,
     .device_id    = CIRRUS_ID_CLGD5446,
     .class_id     = PCI_CLASS_DISPLAY_VGA,
diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 4954bb1..2d6bedc 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -79,35 +79,67 @@ static void vga_mm_writel (void *opaque,
     vga_ioport_write(&s->vga, addr >> s->it_shift, value);
 }
 
-static CPUReadMemoryFunc * const vga_mm_read_ctrl[] = {
-    &vga_mm_readb,
-    &vga_mm_readw,
-    &vga_mm_readl,
-};
+static uint64_t vga_mm_read_ctrl(MemoryRegion *mr, target_phys_addr_t addr,
+                                 unsigned size)
+{
+    VGACommonState *vs = container_of(mr, VGAMemoryRegion, mem)->s;
+    ISAVGAMMState *s = container_of(vs, ISAVGAMMState, vga);
+
+    switch (size) {
+    case 1: return vga_mm_readb(s, addr);
+    case 2: return vga_mm_readw(s, addr);
+    case 4: return vga_mm_readl(s, addr);
+    default: abort();
+    }
+}
+
+static void vga_mm_write_ctrl(MemoryRegion *mr, target_phys_addr_t addr,
+                              uint64_t data, unsigned size)
+{
+    VGACommonState *vs = container_of(mr, VGAMemoryRegion, mem)->s;
+    ISAVGAMMState *s = container_of(vs, ISAVGAMMState, vga);
+
+    switch (size) {
+    case 1: return vga_mm_writeb(s, addr, data);
+    case 2: return vga_mm_writew(s, addr, data);
+    case 4: return vga_mm_writel(s, addr, data);
+    default: abort();
+    }
+}
 
-static CPUWriteMemoryFunc * const vga_mm_write_ctrl[] = {
-    &vga_mm_writeb,
-    &vga_mm_writew,
-    &vga_mm_writel,
+static MemoryRegionOps vga_mm_ctrl_ops = {
+    .read = vga_mm_read_ctrl,
+    .write = vga_mm_write_ctrl,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
+#include "exec-memory.h"
+
 static void vga_mm_init(ISAVGAMMState *s, target_phys_addr_t vram_base,
                         target_phys_addr_t ctrl_base, int it_shift)
 {
-    int s_ioport_ctrl, vga_io_memory;
+    VGAMemoryRegion *s_ioport_ctrl, *vga_io_memory;
 
     s->it_shift = it_shift;
-    s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s,
-                                           DEVICE_NATIVE_ENDIAN);
-    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
-                                           DEVICE_NATIVE_ENDIAN);
+    s_ioport_ctrl = qemu_malloc(sizeof(*s_ioport_ctrl));
+    memory_region_init_io(&s_ioport_ctrl->mem, &vga_mm_ctrl_ops, "vga-mm-ctrl",
+                          0x100000);
+    s_ioport_ctrl->s = &s->vga;
+
+    vga_io_memory = qemu_malloc(sizeof(*vga_io_memory));
+    /* XXX: endianness? */
+    memory_region_init_io(&vga_io_memory->mem, &vga_mem_ops, "vga-mem",
+                          0x20000);
+    vga_io_memory->s = &s->vga;
 
     vmstate_register(NULL, 0, &vmstate_vga_common, s);
 
-    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
+    memory_region_add_subregion(get_system_memory(), ctrl_base,
+                                &s_ioport_ctrl->mem);
     s->vga.bank_offset = 0;
-    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
-    qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
+    memory_region_add_subregion(get_system_memory(),
+                                vram_base + 0x000a0000, &vga_io_memory->mem);
+    memory_region_set_coalescing(&vga_io_memory->mem);
 }
 
 int isa_vga_mm_init(target_phys_addr_t vram_base,
diff --git a/hw/vga-isa.c b/hw/vga-isa.c
index 245841f..9fd282a 100644
--- a/hw/vga-isa.c
+++ b/hw/vga-isa.c
@@ -42,17 +42,22 @@ static void vga_reset_isa(DeviceState *dev)
     vga_common_reset(s);
 }
 
+#include "exec-memory.h"
+
 static int vga_initfn(ISADevice *dev)
 {
     ISAVGAState *d = DO_UPCAST(ISAVGAState, dev, dev);
     VGACommonState *s = &d->state;
-    int vga_io_memory;
+    VGAMemoryRegion *vga_io_memory;
 
     vga_common_init(s, VGA_RAM_SIZE);
     vga_io_memory = vga_init_io(s);
-    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
-                                 vga_io_memory);
-    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
+    memory_region_add_subregion_overlap(
+        get_system_memory(),
+        isa_mem_base + 0x000a0000,
+        &vga_io_memory->mem,
+        1);
+    memory_region_set_coalescing(&vga_io_memory->mem);
     isa_init_ioport(dev, 0x3c0);
     isa_init_ioport(dev, 0x3b4);
     isa_init_ioport(dev, 0x3ba);
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 481f448..7062c4d 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -47,29 +47,6 @@ static const VMStateDescription vmstate_vga_pci = {
     }
 };
 
-static void vga_map(PCIDevice *pci_dev, int region_num,
-                    pcibus_t addr, pcibus_t size, int type)
-{
-    PCIVGAState *d = (PCIVGAState *)pci_dev;
-    VGACommonState *s = &d->vga;
-
-    cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
-    s->map_addr = addr;
-    s->map_end = addr + s->vram_size;
-    vga_dirty_log_start(s);
-}
-
-static void pci_vga_write_config(PCIDevice *d,
-                                 uint32_t address, uint32_t val, int len)
-{
-    PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
-    VGACommonState *s = &pvs->vga;
-
-    pci_default_write_config(d, address, val, len);
-    if (s->map_addr && pvs->dev.io_regions[0].addr == -1)
-        s->map_addr = 0;
-}
-
 static int pci_vga_initfn(PCIDevice *dev)
 {
      PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
@@ -83,8 +60,8 @@ static int pci_vga_initfn(PCIDevice *dev)
                                   s->screen_dump, s->text_update, s);
 
      /* XXX: VGA_RAM_SIZE must be a power of two */
-     pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
-                      PCI_BASE_ADDRESS_MEM_PREFETCH, vga_map);
+     pci_register_bar_region(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH,
+                             &s->vram);
 
      if (!dev->rom_bar) {
          /* compatibility with pc-0.13 and older */
@@ -106,7 +83,6 @@ static PCIDeviceInfo vga_info = {
     .qdev.vmsd    = &vmstate_vga_pci,
     .no_hotplug   = 1,
     .init         = pci_vga_initfn,
-    .config_write = pci_vga_write_config,
     .romfile      = "vgabios-stdvga.bin",
 
     /* dummy VGA (same as Bochs ID) */
diff --git a/hw/vga.c b/hw/vga.c
index 0f54734..7f7aeb1 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -825,7 +825,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
 #endif
             s->plane_updated |= mask; /* only used to detect font change */
-            cpu_physical_memory_set_dirty(s->vram_offset + addr);
+            memory_region_set_dirty(&s->vram, addr);
         }
     } else if (s->gr[5] & 0x10) {
         /* odd/even mode (aka text mode mapping) */
@@ -838,7 +838,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
 #endif
             s->plane_updated |= mask; /* only used to detect font change */
-            cpu_physical_memory_set_dirty(s->vram_offset + addr);
+            memory_region_set_dirty(&s->vram, addr);
         }
     } else {
         /* standard VGA latched access */
@@ -912,7 +912,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
         printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
                addr * 4, write_mask, val);
 #endif
-        cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
+        memory_region_set_dirty(&s->vram, addr << 2);
     }
 }
 
@@ -1553,57 +1553,17 @@ void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
 
 static void vga_sync_dirty_bitmap(VGACommonState *s)
 {
-    if (s->map_addr)
-        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
-
-    if (s->lfb_vram_mapped) {
-        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
-        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
-    }
-
-#ifdef CONFIG_BOCHS_VBE
-    if (s->vbe_mapped) {
-        cpu_physical_sync_dirty_bitmap(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
-                                       VBE_DISPI_LFB_PHYSICAL_ADDRESS + s->vram_size);
-    }
-#endif
-
+    memory_region_sync_dirty_bitmap(&s->vram);
 }
 
 void vga_dirty_log_start(VGACommonState *s)
 {
-    if (s->map_addr) {
-        cpu_physical_log_start(s->map_addr, s->map_end - s->map_addr);
-    }
-
-    if (s->lfb_vram_mapped) {
-        cpu_physical_log_start(isa_mem_base + 0xa0000, 0x8000);
-        cpu_physical_log_start(isa_mem_base + 0xa8000, 0x8000);
-    }
-
-#ifdef CONFIG_BOCHS_VBE
-    if (s->vbe_mapped) {
-        cpu_physical_log_start(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
-    }
-#endif
+    memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
 }
 
 void vga_dirty_log_stop(VGACommonState *s)
 {
-    if (s->map_addr) {
-        cpu_physical_log_stop(s->map_addr, s->map_end - s->map_addr);
-    }
-
-    if (s->lfb_vram_mapped) {
-        cpu_physical_log_stop(isa_mem_base + 0xa0000, 0x8000);
-        cpu_physical_log_stop(isa_mem_base + 0xa8000, 0x8000);
-    }
-
-#ifdef CONFIG_BOCHS_VBE
-    if (s->vbe_mapped) {
-        cpu_physical_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
-    }
-#endif
+    memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
 }
 
 void vga_dirty_log_restart(VGACommonState *s)
@@ -1773,15 +1733,16 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         if (!(s->cr[0x17] & 2)) {
             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
         }
-        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
-        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
+        page0 = addr & TARGET_PAGE_MASK;
+        page1 = (addr + bwidth - 1) & TARGET_PAGE_MASK;
         update = full_update |
-            cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
-            cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
+            memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
+            memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
         if ((page1 - page0) > TARGET_PAGE_SIZE) {
             /* if wide line, can use another page */
-            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
-                                                    VGA_DIRTY_FLAG);
+            update |= memory_region_get_dirty(&s->vram,
+                                              page0 + TARGET_PAGE_SIZE,
+                                              DIRTY_MEMORY_VGA);
         }
         /* explicit invalidation for the hardware cursor */
         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
@@ -1826,8 +1787,10 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     }
     /* reset modified pages */
     if (page_max >= page_min) {
-        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
-                                        VGA_DIRTY_FLAG);
+        memory_region_reset_dirty(&s->vram,
+                                  page_min,
+                                  page_max + TARGET_PAGE_SIZE - page_min,
+                                  DIRTY_MEMORY_VGA);
     }
     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
 }
@@ -1906,11 +1869,6 @@ static void vga_invalidate_display(void *opaque)
 
 void vga_common_reset(VGACommonState *s)
 {
-    s->lfb_addr = 0;
-    s->lfb_end = 0;
-    s->map_addr = 0;
-    s->map_end = 0;
-    s->lfb_vram_mapped = 0;
     s->sr_index = 0;
     memset(s->sr, '\0', sizeof(s->sr));
     s->gr_index = 0;
@@ -2141,16 +2099,36 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
     dpy_update(s->ds, 0, 0, s->last_width, height);
 }
 
-CPUReadMemoryFunc * const vga_mem_read[3] = {
-    vga_mem_readb,
-    vga_mem_readw,
-    vga_mem_readl,
-};
+static uint64_t vga_mem_read(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned size)
+{
+    VGACommonState *s = container_of(mr, VGAMemoryRegion, mem)->s;
+
+    switch (size) {
+    case 1: return vga_mem_readb(s, addr);
+    case 2: return vga_mem_readw(s, addr);
+    case 4: return vga_mem_readl(s, addr);
+    default: abort();
+    }
+}
 
-CPUWriteMemoryFunc * const vga_mem_write[3] = {
-    vga_mem_writeb,
-    vga_mem_writew,
-    vga_mem_writel,
+static void vga_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
+                          uint64_t data, unsigned size)
+{
+    VGACommonState *s = container_of(mr, VGAMemoryRegion, mem)->s;
+
+    switch (size) {
+    case 1: return vga_mem_writeb(s, addr, data);
+    case 2: return vga_mem_writew(s, addr, data);
+    case 4: return vga_mem_writel(s, addr, data);
+    default: abort();
+    }
+}
+
+MemoryRegionOps vga_mem_ops = {
+    .read = vga_mem_read,
+    .write = vga_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
 static int vga_common_post_load(void *opaque, int version_id)
@@ -2236,8 +2214,8 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
 #else
     s->is_vbe_vmstate = 0;
 #endif
-    s->vram_offset = qemu_ram_alloc(NULL, "vga.vram", vga_ram_size);
-    s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
+    memory_region_init_ram(&s->vram, NULL, "vga.vram", vga_ram_size);
+    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
     s->vram_size = vga_ram_size;
     s->get_bpp = vga_get_bpp;
     s->get_offsets = vga_get_offsets;
@@ -2260,8 +2238,10 @@ void vga_common_init(VGACommonState *s, int vga_ram_size)
 }
 
 /* used by both ISA and PCI */
-int vga_init_io(VGACommonState *s)
+VGAMemoryRegion *vga_init_io(VGACommonState *s)
 {
+    VGAMemoryRegion *vga_mem;
+
     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
 
     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
@@ -2292,30 +2272,38 @@ int vga_init_io(VGACommonState *s)
 #endif
 #endif /* CONFIG_BOCHS_VBE */
 
-    return cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
-                                  DEVICE_LITTLE_ENDIAN);
+    vga_mem = qemu_malloc(sizeof(*vga_mem));
+    memory_region_init_io(&vga_mem->mem, &vga_mem_ops, "vga-lowmem", 0x20000);
+    vga_mem->s = s;
+
+    return vga_mem;
 }
 
+#include "exec-memory.h"
+
 void vga_init(VGACommonState *s)
 {
-    int vga_io_memory;
+    VGAMemoryRegion *vga_io_memory;
 
     qemu_register_reset(vga_reset, s);
 
     s->bank_offset = 0;
 
     vga_io_memory = vga_init_io(s);
-    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
-                                 vga_io_memory);
-    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
+    memory_region_add_subregion_overlap(get_system_memory(),
+                                        isa_mem_base + 0x000a0000,
+                                        &vga_io_memory->mem,
+                                        1);
+    memory_region_set_coalescing(&vga_io_memory->mem);
 }
 
 void vga_init_vbe(VGACommonState *s)
 {
 #ifdef CONFIG_BOCHS_VBE
     /* XXX: use optimized standard vga accesses */
-    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
-                                 VGA_RAM_SIZE, s->vram_offset);
+    memory_region_add_subregion(get_system_memory(),
+                                VBE_DISPI_LFB_PHYSICAL_ADDRESS,
+                                &s->vram);
     s->vbe_mapped = 1;
 #endif 
 }
diff --git a/hw/vga_int.h b/hw/vga_int.h
index d2811bd..0ef9962 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -23,6 +23,7 @@
  */
 
 #include <hw/hw.h>
+#include "memory.h"
 
 #define MSR_COLOR_EMULATION 0x01
 #define MSR_PAGE_SELECT     0x20
@@ -103,15 +104,15 @@ struct VGACommonState;
 typedef uint8_t (* vga_retrace_fn)(struct VGACommonState *s);
 typedef void (* vga_update_retrace_info_fn)(struct VGACommonState *s);
 
+typedef struct VGAMemoryRegion {
+    MemoryRegion mem;
+    struct VGACommonState *s;
+} VGAMemoryRegion;
+
 typedef struct VGACommonState {
     uint8_t *vram_ptr;
-    ram_addr_t vram_offset;
+    MemoryRegion vram;
     uint32_t vram_size;
-    uint32_t lfb_addr;
-    uint32_t lfb_end;
-    uint32_t map_addr;
-    uint32_t map_end;
-    uint32_t lfb_vram_mapped; /* whether 0xa0000 is mapped as ram */
     uint32_t latch;
     uint8_t sr_index;
     uint8_t sr[256];
@@ -134,7 +135,7 @@ typedef struct VGACommonState {
     int dac_8bit;
     uint8_t palette[768];
     int32_t bank_offset;
-    int vga_io_memory;
+    VGAMemoryRegion *vga_io_memory;
     int (*get_bpp)(struct VGACommonState *s);
     void (*get_offsets)(struct VGACommonState *s,
                         uint32_t *pline_offset,
@@ -191,7 +192,7 @@ static inline int c6_to_8(int v)
 
 void vga_common_init(VGACommonState *s, int vga_ram_size);
 void vga_init(VGACommonState *s);
-int vga_init_io(VGACommonState *s);
+VGAMemoryRegion *vga_init_io(VGACommonState *s);
 void vga_common_reset(VGACommonState *s);
 
 void vga_dirty_log_start(VGACommonState *s);
@@ -229,5 +230,4 @@ extern const uint8_t gr_mask[16];
 #define VGABIOS_FILENAME "vgabios.bin"
 #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
 
-extern CPUReadMemoryFunc * const vga_mem_read[3];
-extern CPUWriteMemoryFunc * const vga_mem_write[3];
+extern MemoryRegionOps vga_mem_ops;
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 190b005..cd7c508 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1135,17 +1135,45 @@ static void vmsvga_vram_writel(void *opaque, target_phys_addr_t addr,
         *(uint32_t *) (s->vram_ptr + addr) = value;
 }
 
-static CPUReadMemoryFunc * const vmsvga_vram_read[] = {
-    vmsvga_vram_readb,
-    vmsvga_vram_readw,
-    vmsvga_vram_readl,
-};
+typedef struct DirectMem DirectMem;
 
-static CPUWriteMemoryFunc * const vmsvga_vram_write[] = {
-    vmsvga_vram_writeb,
-    vmsvga_vram_writew,
-    vmsvga_vram_writel,
+struct DirectMem {
+    MemoryRegion mr;
+    struct vmsvga_state_s *chip;
 };
+
+static uint64_t vmsvga_vram_read(MemoryRegion *mr, target_phys_addr_t addr,
+                                 unsigned size)
+{
+    struct vmsvga_state_s *s = container_of(mr, DirectMem, iomem)->chip;
+
+    switch (size) {
+    case 1: return vmsvga_vram_readb(s, addr);
+    case 2: return vmsvga_vram_readw(s, addr);
+    case 4: return vmsvga_vram_readl(s, addr);
+    default: abort();
+    }
+}
+
+static void vmsvga_vram_read(MemoryRegion *mr, target_phys_addr_t addr,
+                             unsigned size, uint64_t data)
+{
+    struct vmsvga_state_s *s = container_of(mr, DirectMem, iomem)->chip;
+
+    switch (size) {
+    case 1: return vmsvga_vram_writeb(s, addr, data);
+    case 2: return vmsvga_vram_writew(s, addr, data);
+    case 4: return vmsvga_vram_writel(s, addr, data);
+    default: abort();
+    }
+}
+
+static MemoryRegionOps vmsvga_vram_io_ops = {
+    .read = vmsvga_vram_read,
+    .write = vmsvga_vram_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+}
+
 #endif
 
 static int vmsvga_post_load(void *opaque, int version_id)
@@ -1241,27 +1269,6 @@ static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
                     1, 4, vmsvga_bios_write, s);
 }
 
-static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
-                pcibus_t addr, pcibus_t size, int type)
-{
-    struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
-    struct vmsvga_state_s *s = &d->chip;
-    ram_addr_t iomemtype;
-
-#ifdef DIRECT_VRAM
-    iomemtype = cpu_register_io_memory(vmsvga_vram_read,
-                    vmsvga_vram_write, s, DEVICE_NATIVE_ENDIAN);
-#else
-    iomemtype = s->vga.vram_offset | IO_MEM_RAM;
-#endif
-    cpu_register_physical_memory(addr, s->vga.vram_size,
-                    iomemtype);
-
-    s->vga.map_addr = addr;
-    s->vga.map_end = addr + s->vga.vram_size;
-    vga_dirty_log_restart(&s->vga);
-}
-
 static void pci_vmsvga_map_fifo(PCIDevice *pci_dev, int region_num,
                 pcibus_t addr, pcibus_t size, int type)
 {
@@ -1279,6 +1286,20 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
 {
     struct pci_vmsvga_state_s *s =
         DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
+    MemoryRegion *iomem;
+
+#ifdef DIRECT_VRAM
+    DirectMem *directmem = qemu_malloc(sizeof(*directmem));
+
+    directmem->chip = &s->chip;
+    iomem = &directmem->mr;
+    memory_region_init_io(iomem, &vmsvga_vram_io_ops, "vmsvga",
+                          memory_region_size(&s->chip.vga.vram));
+#else
+    iomem = &s->chip.vga.vram;
+#endif
+
+    vga_dirty_log_restart(&s->chip.vga);
 
     s->card.config[PCI_CACHE_LINE_SIZE]	= 0x08;		/* Cache line size */
     s->card.config[PCI_LATENCY_TIMER] = 0x40;		/* Latency timer */
@@ -1286,8 +1307,7 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
 
     pci_register_bar(&s->card, 0, 0x10,
                     PCI_BASE_ADDRESS_SPACE_IO, pci_vmsvga_map_ioport);
-    pci_register_bar(&s->card, 1, VGA_RAM_SIZE,
-                    PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_mem);
+    pci_register_bar_region(&s->card, 1, PCI_BASE_ADDRESS_MEM_PREFETCH, iomem);
 
     pci_register_bar(&s->card, 2, SVGA_FIFO_SIZE,
                     PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_fifo);
-- 
1.7.5.3

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

* [RFC v2 16/20] cirrus: simplify mmio BAR access functions
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:22   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Make use of the memory API's ability to satisfy multi-byte accesses via
multiple single-byte accesses.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |   82 +++++++------------------------------------------------
 1 files changed, 10 insertions(+), 72 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 0cce453..0cb34d9 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2830,11 +2830,10 @@ static void cirrus_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
  *
  ***************************************/
 
-static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_mmio_read(MemoryRegion *mr, target_phys_addr_t addr,
+                                 unsigned size)
 {
-    CirrusVGAState *s = opaque;
-
-    addr &= CIRRUS_PNPMMIO_SIZE - 1;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
 
     if (addr >= 0x100) {
         return cirrus_mmio_blt_read(s, addr - 0x100);
@@ -2843,32 +2842,10 @@ static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_mmio_readb(opaque, addr);
-    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_mmio_readb(opaque, addr);
-    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
-    v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
-    v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
-			       uint32_t val)
+static void cirrus_mmio_write(MemoryRegion *mr, target_phys_addr_t addr,
+                              uint64_t val, unsigned size)
 {
-    CirrusVGAState *s = opaque;
-
-    addr &= CIRRUS_PNPMMIO_SIZE - 1;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
 
     if (addr >= 0x100) {
 	cirrus_mmio_blt_write(s, addr - 0x100, val);
@@ -2877,53 +2854,14 @@ static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
-			       uint32_t val)
-{
-    cirrus_mmio_writeb(opaque, addr, val & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
-			       uint32_t val)
-{
-    cirrus_mmio_writeb(opaque, addr, val & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-
-static uint64_t cirrus_mmio_read(MemoryRegion *mr, target_phys_addr_t addr,
-                                 unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
-
-    switch (size) {
-    case 1: return cirrus_mmio_readb(s, addr);
-    case 2: return cirrus_mmio_readw(s, addr);
-    case 4: return cirrus_mmio_readl(s, addr);
-    default: abort();
-    }
-};
-
-static void cirrus_mmio_write(MemoryRegion *mr, target_phys_addr_t addr,
-                              uint64_t data, unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
-
-    switch (size) {
-    case 1: return cirrus_mmio_writeb(s, addr, data);
-    case 2: return cirrus_mmio_writew(s, addr, data);
-    case 4: return cirrus_mmio_writel(s, addr, data);
-    default: abort();
-    }
-};
-
 static MemoryRegionOps cirrus_mmio_io_ops = {
     .read = cirrus_mmio_read,
     .write = cirrus_mmio_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 /* load/save state */
-- 
1.7.5.3


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

* [Qemu-devel] [RFC v2 16/20] cirrus: simplify mmio BAR access functions
@ 2011-06-27 13:22   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Make use of the memory API's ability to satisfy multi-byte accesses via
multiple single-byte accesses.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |   82 +++++++------------------------------------------------
 1 files changed, 10 insertions(+), 72 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 0cce453..0cb34d9 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2830,11 +2830,10 @@ static void cirrus_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
  *
  ***************************************/
 
-static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_mmio_read(MemoryRegion *mr, target_phys_addr_t addr,
+                                 unsigned size)
 {
-    CirrusVGAState *s = opaque;
-
-    addr &= CIRRUS_PNPMMIO_SIZE - 1;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
 
     if (addr >= 0x100) {
         return cirrus_mmio_blt_read(s, addr - 0x100);
@@ -2843,32 +2842,10 @@ static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
     }
 }
 
-static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_mmio_readb(opaque, addr);
-    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_mmio_readb(opaque, addr);
-    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
-    v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
-    v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
-			       uint32_t val)
+static void cirrus_mmio_write(MemoryRegion *mr, target_phys_addr_t addr,
+                              uint64_t val, unsigned size)
 {
-    CirrusVGAState *s = opaque;
-
-    addr &= CIRRUS_PNPMMIO_SIZE - 1;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
 
     if (addr >= 0x100) {
 	cirrus_mmio_blt_write(s, addr - 0x100, val);
@@ -2877,53 +2854,14 @@ static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
-			       uint32_t val)
-{
-    cirrus_mmio_writeb(opaque, addr, val & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
-			       uint32_t val)
-{
-    cirrus_mmio_writeb(opaque, addr, val & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-
-static uint64_t cirrus_mmio_read(MemoryRegion *mr, target_phys_addr_t addr,
-                                 unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
-
-    switch (size) {
-    case 1: return cirrus_mmio_readb(s, addr);
-    case 2: return cirrus_mmio_readw(s, addr);
-    case 4: return cirrus_mmio_readl(s, addr);
-    default: abort();
-    }
-};
-
-static void cirrus_mmio_write(MemoryRegion *mr, target_phys_addr_t addr,
-                              uint64_t data, unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_mmio_io);
-
-    switch (size) {
-    case 1: return cirrus_mmio_writeb(s, addr, data);
-    case 2: return cirrus_mmio_writew(s, addr, data);
-    case 4: return cirrus_mmio_writel(s, addr, data);
-    default: abort();
-    }
-};
-
 static MemoryRegionOps cirrus_mmio_io_ops = {
     .read = cirrus_mmio_read,
     .write = cirrus_mmio_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 /* load/save state */
-- 
1.7.5.3

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

* [RFC v2 17/20] cirrus: simplify bitblt BAR access functions
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:22   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Make use of the memory API's ability to satisfy multi-byte accesses via
multiple single-byte accesses.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |   87 ++++++++++--------------------------------------------
 1 files changed, 16 insertions(+), 71 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 0cb34d9..6312c6e 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2445,39 +2445,27 @@ static void cirrus_linear_write(MemoryRegion *mr, target_phys_addr_t addr,
  ***************************************/
 
 
-static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_linear_bitblt_read(MemoryRegion *mr,
+                                          target_phys_addr_t addr,
+                                          unsigned size)
 {
+    CirrusVGAState *s = container_of(mr, CirrusVGAState,
+                                     cirrus_linear_bitblt_io);
     uint32_t ret;
 
     /* XXX handle bitblt */
+    (void)s;
     ret = 0xff;
     return ret;
 }
 
-static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_bitblt_readb(opaque, addr);
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_bitblt_readb(opaque, addr);
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
+static void cirrus_linear_bitblt_write(MemoryRegion *mr,
+                                       target_phys_addr_t addr,
+                                       uint64_t val,
+                                       unsigned size)
 {
-    CirrusVGAState *s = opaque;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState,
+                                     cirrus_linear_bitblt_io);
 
     if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
 	/* bitblt */
@@ -2488,57 +2476,14 @@ static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
-{
-    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
-{
-    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-static uint64_t cirrus_linear_bitblt_read(MemoryRegion *mr,
-                                          target_phys_addr_t addr,
-                                          unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState,
-                                     cirrus_linear_bitblt_io);
-
-    switch (size) {
-    case 1: return cirrus_linear_bitblt_readb(s, addr);
-    case 2: return cirrus_linear_bitblt_readw(s, addr);
-    case 4: return cirrus_linear_bitblt_readl(s, addr);
-    default: abort();
-    }
-};
-
-static void cirrus_linear_bitblt_write(MemoryRegion *mr,
-                                       target_phys_addr_t addr,
-                                       uint64_t data,
-                                       unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState,
-                                     cirrus_linear_bitblt_io);
-
-    switch (size) {
-    case 1: return cirrus_linear_bitblt_writeb(s, addr, data);
-    case 2: return cirrus_linear_bitblt_writew(s, addr, data);
-    case 4: return cirrus_linear_bitblt_writel(s, addr, data);
-    default: abort();
-    }
-};
-
 static MemoryRegionOps cirrus_linear_bitblt_io_ops = {
     .read = cirrus_linear_bitblt_read,
     .write = cirrus_linear_bitblt_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 #include "exec-memory.h"
-- 
1.7.5.3


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

* [Qemu-devel] [RFC v2 17/20] cirrus: simplify bitblt BAR access functions
@ 2011-06-27 13:22   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Make use of the memory API's ability to satisfy multi-byte accesses via
multiple single-byte accesses.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |   87 ++++++++++--------------------------------------------
 1 files changed, 16 insertions(+), 71 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 0cb34d9..6312c6e 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2445,39 +2445,27 @@ static void cirrus_linear_write(MemoryRegion *mr, target_phys_addr_t addr,
  ***************************************/
 
 
-static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_linear_bitblt_read(MemoryRegion *mr,
+                                          target_phys_addr_t addr,
+                                          unsigned size)
 {
+    CirrusVGAState *s = container_of(mr, CirrusVGAState,
+                                     cirrus_linear_bitblt_io);
     uint32_t ret;
 
     /* XXX handle bitblt */
+    (void)s;
     ret = 0xff;
     return ret;
 }
 
-static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_bitblt_readb(opaque, addr);
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_bitblt_readb(opaque, addr);
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
-    v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
+static void cirrus_linear_bitblt_write(MemoryRegion *mr,
+                                       target_phys_addr_t addr,
+                                       uint64_t val,
+                                       unsigned size)
 {
-    CirrusVGAState *s = opaque;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState,
+                                     cirrus_linear_bitblt_io);
 
     if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
 	/* bitblt */
@@ -2488,57 +2476,14 @@ static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
-{
-    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
-{
-    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-static uint64_t cirrus_linear_bitblt_read(MemoryRegion *mr,
-                                          target_phys_addr_t addr,
-                                          unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState,
-                                     cirrus_linear_bitblt_io);
-
-    switch (size) {
-    case 1: return cirrus_linear_bitblt_readb(s, addr);
-    case 2: return cirrus_linear_bitblt_readw(s, addr);
-    case 4: return cirrus_linear_bitblt_readl(s, addr);
-    default: abort();
-    }
-};
-
-static void cirrus_linear_bitblt_write(MemoryRegion *mr,
-                                       target_phys_addr_t addr,
-                                       uint64_t data,
-                                       unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState,
-                                     cirrus_linear_bitblt_io);
-
-    switch (size) {
-    case 1: return cirrus_linear_bitblt_writeb(s, addr, data);
-    case 2: return cirrus_linear_bitblt_writew(s, addr, data);
-    case 4: return cirrus_linear_bitblt_writel(s, addr, data);
-    default: abort();
-    }
-};
-
 static MemoryRegionOps cirrus_linear_bitblt_io_ops = {
     .read = cirrus_linear_bitblt_read,
     .write = cirrus_linear_bitblt_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 #include "exec-memory.h"
-- 
1.7.5.3

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

* [RFC v2 18/20] cirrus: simplify vga window mmio access functions
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:22   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Make use of the memory API's ability to satisfy multi-byte accesses via
multiple single-byte accesses.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |   83 ++++++++----------------------------------------------
 1 files changed, 13 insertions(+), 70 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 6312c6e..6e9e83d 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -1955,9 +1955,11 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
  *
  ***************************************/
 
-static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_vga_mem_read(MemoryRegion *mr,
+                                    target_phys_addr_t addr,
+                                    uint32_t size)
 {
-    CirrusVGAState *s = opaque;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
     unsigned bank_index;
     unsigned bank_offset;
     uint32_t val;
@@ -1966,8 +1968,6 @@ static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
 	return vga_mem_readb(s, addr);
     }
 
-    addr &= 0x1ffff;
-
     if (addr < 0x10000) {
 	/* XXX handle bitblt */
 	/* video memory */
@@ -1999,30 +1999,12 @@ static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
+static void cirrus_vga_mem_write(MemoryRegion *mr,
+                                 target_phys_addr_t addr,
+                                 uint64_t mem_value,
+                                 uint32_t size)
 {
-    uint32_t v;
-
-    v = cirrus_vga_mem_readb(opaque, addr);
-    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_vga_mem_readb(opaque, addr);
-    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
-    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
-    v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                  uint32_t mem_value)
-{
-    CirrusVGAState *s = opaque;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
     unsigned bank_index;
     unsigned bank_offset;
     unsigned mode;
@@ -2032,8 +2014,6 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
         return;
     }
 
-    addr &= 0x1ffff;
-
     if (addr < 0x10000) {
 	if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
 	    /* bitblt */
@@ -2083,51 +2063,14 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-static uint64_t cirrus_vga_mem_read(MemoryRegion *mr,
-                                    target_phys_addr_t addr,
-                                    uint32_t size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
-
-    switch (size) {
-    case 1: return cirrus_vga_mem_readb(s, addr);
-    case 2: return cirrus_vga_mem_readw(s, addr);
-    case 4: return cirrus_vga_mem_readl(s, addr);
-    default: abort();
-    }
-}
-
-static void cirrus_vga_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
-                                 uint64_t data, unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
-
-    switch (size) {
-    case 1: return cirrus_vga_mem_writeb(s, addr, data);
-    case 2: return cirrus_vga_mem_writew(s, addr, data);
-    case 4: return cirrus_vga_mem_writel(s, addr, data);
-    default: abort();
-    }
-};
-
 static MemoryRegionOps cirrus_vga_mem_ops = {
     .read = cirrus_vga_mem_read,
     .write = cirrus_vga_mem_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 /***************************************
-- 
1.7.5.3


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

* [Qemu-devel] [RFC v2 18/20] cirrus: simplify vga window mmio access functions
@ 2011-06-27 13:22   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Make use of the memory API's ability to satisfy multi-byte accesses via
multiple single-byte accesses.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |   83 ++++++++----------------------------------------------
 1 files changed, 13 insertions(+), 70 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 6312c6e..6e9e83d 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -1955,9 +1955,11 @@ static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
  *
  ***************************************/
 
-static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_vga_mem_read(MemoryRegion *mr,
+                                    target_phys_addr_t addr,
+                                    uint32_t size)
 {
-    CirrusVGAState *s = opaque;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
     unsigned bank_index;
     unsigned bank_offset;
     uint32_t val;
@@ -1966,8 +1968,6 @@ static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
 	return vga_mem_readb(s, addr);
     }
 
-    addr &= 0x1ffff;
-
     if (addr < 0x10000) {
 	/* XXX handle bitblt */
 	/* video memory */
@@ -1999,30 +1999,12 @@ static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
+static void cirrus_vga_mem_write(MemoryRegion *mr,
+                                 target_phys_addr_t addr,
+                                 uint64_t mem_value,
+                                 uint32_t size)
 {
-    uint32_t v;
-
-    v = cirrus_vga_mem_readb(opaque, addr);
-    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_vga_mem_readb(opaque, addr);
-    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
-    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
-    v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                  uint32_t mem_value)
-{
-    CirrusVGAState *s = opaque;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
     unsigned bank_index;
     unsigned bank_offset;
     unsigned mode;
@@ -2032,8 +2014,6 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
         return;
     }
 
-    addr &= 0x1ffff;
-
     if (addr < 0x10000) {
 	if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
 	    /* bitblt */
@@ -2083,51 +2063,14 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-static uint64_t cirrus_vga_mem_read(MemoryRegion *mr,
-                                    target_phys_addr_t addr,
-                                    uint32_t size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
-
-    switch (size) {
-    case 1: return cirrus_vga_mem_readb(s, addr);
-    case 2: return cirrus_vga_mem_readw(s, addr);
-    case 4: return cirrus_vga_mem_readl(s, addr);
-    default: abort();
-    }
-}
-
-static void cirrus_vga_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
-                                 uint64_t data, unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, low_mem);
-
-    switch (size) {
-    case 1: return cirrus_vga_mem_writeb(s, addr, data);
-    case 2: return cirrus_vga_mem_writew(s, addr, data);
-    case 4: return cirrus_vga_mem_writel(s, addr, data);
-    default: abort();
-    }
-};
-
 static MemoryRegionOps cirrus_vga_mem_ops = {
     .read = cirrus_vga_mem_read,
     .write = cirrus_vga_mem_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 /***************************************
-- 
1.7.5.3

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

* [RFC v2 19/20] vga: simplify vga window mmio access functions
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:22   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Make use of the memory API's ability to satisfy multi-byte accesses via
multiple single-byte accesses.

We have to keep vga_mem_{read,write}b() since they're used by cirrus.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |    4 +-
 hw/vga.c        |   56 +++++++-----------------------------------------------
 hw/vga_int.h    |    4 +-
 3 files changed, 12 insertions(+), 52 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 6e9e83d..1036eb2 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -1965,7 +1965,7 @@ static uint64_t cirrus_vga_mem_read(MemoryRegion *mr,
     uint32_t val;
 
     if ((s->vga.sr[0x07] & 0x01) == 0) {
-	return vga_mem_readb(s, addr);
+        return vga_mem_readb(&s->vga, addr);
     }
 
     if (addr < 0x10000) {
@@ -2010,7 +2010,7 @@ static void cirrus_vga_mem_write(MemoryRegion *mr,
     unsigned mode;
 
     if ((s->vga.sr[0x07] & 0x01) == 0) {
-	vga_mem_writeb(s, addr, mem_value);
+        vga_mem_writeb(&s->vga, addr, mem_value);
         return;
     }
 
diff --git a/hw/vga.c b/hw/vga.c
index 7f7aeb1..38e14cf 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -707,9 +707,8 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
 #endif
 
 /* called for accesses between 0xa0000 and 0xc0000 */
-uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
+uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
 {
-    VGACommonState *s = opaque;
     int memory_map_mode, plane;
     uint32_t ret;
 
@@ -763,28 +762,9 @@ uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-    v = vga_mem_readb(opaque, addr);
-    v |= vga_mem_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-    v = vga_mem_readb(opaque, addr);
-    v |= vga_mem_readb(opaque, addr + 1) << 8;
-    v |= vga_mem_readb(opaque, addr + 2) << 16;
-    v |= vga_mem_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
 /* called for accesses between 0xa0000 and 0xc0000 */
-void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
 {
-    VGACommonState *s = opaque;
     int memory_map_mode, plane, write_mode, b, func_select, mask;
     uint32_t write_mask, bit_mask, set_mask;
 
@@ -916,20 +896,6 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    vga_mem_writeb(opaque, addr, val & 0xff);
-    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    vga_mem_writeb(opaque, addr, val & 0xff);
-    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
                              const uint8_t *font_ptr, int h,
                              uint32_t fgcol, uint32_t bgcol);
@@ -2104,12 +2070,7 @@ static uint64_t vga_mem_read(MemoryRegion *mr, target_phys_addr_t addr,
 {
     VGACommonState *s = container_of(mr, VGAMemoryRegion, mem)->s;
 
-    switch (size) {
-    case 1: return vga_mem_readb(s, addr);
-    case 2: return vga_mem_readw(s, addr);
-    case 4: return vga_mem_readl(s, addr);
-    default: abort();
-    }
+    return vga_mem_readb(s, addr);
 }
 
 static void vga_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
@@ -2117,18 +2078,17 @@ static void vga_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
 {
     VGACommonState *s = container_of(mr, VGAMemoryRegion, mem)->s;
 
-    switch (size) {
-    case 1: return vga_mem_writeb(s, addr, data);
-    case 2: return vga_mem_writew(s, addr, data);
-    case 4: return vga_mem_writel(s, addr, data);
-    default: abort();
-    }
+    return vga_mem_writeb(s, addr, data);
 }
 
 MemoryRegionOps vga_mem_ops = {
     .read = vga_mem_read,
     .write = vga_mem_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static int vga_common_post_load(void *opaque, int version_id)
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 0ef9962..37b0a09 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -202,8 +202,8 @@ void vga_dirty_log_restart(VGACommonState *s);
 extern const VMStateDescription vmstate_vga_common;
 uint32_t vga_ioport_read(void *opaque, uint32_t addr);
 void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val);
-uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr);
-void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val);
+uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr);
+void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val);
 void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2);
 int ppm_save(const char *filename, struct DisplaySurface *ds);
 
-- 
1.7.5.3


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

* [Qemu-devel] [RFC v2 19/20] vga: simplify vga window mmio access functions
@ 2011-06-27 13:22   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Make use of the memory API's ability to satisfy multi-byte accesses via
multiple single-byte accesses.

We have to keep vga_mem_{read,write}b() since they're used by cirrus.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |    4 +-
 hw/vga.c        |   56 +++++++-----------------------------------------------
 hw/vga_int.h    |    4 +-
 3 files changed, 12 insertions(+), 52 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 6e9e83d..1036eb2 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -1965,7 +1965,7 @@ static uint64_t cirrus_vga_mem_read(MemoryRegion *mr,
     uint32_t val;
 
     if ((s->vga.sr[0x07] & 0x01) == 0) {
-	return vga_mem_readb(s, addr);
+        return vga_mem_readb(&s->vga, addr);
     }
 
     if (addr < 0x10000) {
@@ -2010,7 +2010,7 @@ static void cirrus_vga_mem_write(MemoryRegion *mr,
     unsigned mode;
 
     if ((s->vga.sr[0x07] & 0x01) == 0) {
-	vga_mem_writeb(s, addr, mem_value);
+        vga_mem_writeb(&s->vga, addr, mem_value);
         return;
     }
 
diff --git a/hw/vga.c b/hw/vga.c
index 7f7aeb1..38e14cf 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -707,9 +707,8 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
 #endif
 
 /* called for accesses between 0xa0000 and 0xc0000 */
-uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
+uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
 {
-    VGACommonState *s = opaque;
     int memory_map_mode, plane;
     uint32_t ret;
 
@@ -763,28 +762,9 @@ uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-    v = vga_mem_readb(opaque, addr);
-    v |= vga_mem_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-    v = vga_mem_readb(opaque, addr);
-    v |= vga_mem_readb(opaque, addr + 1) << 8;
-    v |= vga_mem_readb(opaque, addr + 2) << 16;
-    v |= vga_mem_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
 /* called for accesses between 0xa0000 and 0xc0000 */
-void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
 {
-    VGACommonState *s = opaque;
     int memory_map_mode, plane, write_mode, b, func_select, mask;
     uint32_t write_mask, bit_mask, set_mask;
 
@@ -916,20 +896,6 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
     }
 }
 
-static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    vga_mem_writeb(opaque, addr, val & 0xff);
-    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    vga_mem_writeb(opaque, addr, val & 0xff);
-    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
                              const uint8_t *font_ptr, int h,
                              uint32_t fgcol, uint32_t bgcol);
@@ -2104,12 +2070,7 @@ static uint64_t vga_mem_read(MemoryRegion *mr, target_phys_addr_t addr,
 {
     VGACommonState *s = container_of(mr, VGAMemoryRegion, mem)->s;
 
-    switch (size) {
-    case 1: return vga_mem_readb(s, addr);
-    case 2: return vga_mem_readw(s, addr);
-    case 4: return vga_mem_readl(s, addr);
-    default: abort();
-    }
+    return vga_mem_readb(s, addr);
 }
 
 static void vga_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
@@ -2117,18 +2078,17 @@ static void vga_mem_write(MemoryRegion *mr, target_phys_addr_t addr,
 {
     VGACommonState *s = container_of(mr, VGAMemoryRegion, mem)->s;
 
-    switch (size) {
-    case 1: return vga_mem_writeb(s, addr, data);
-    case 2: return vga_mem_writew(s, addr, data);
-    case 4: return vga_mem_writel(s, addr, data);
-    default: abort();
-    }
+    return vga_mem_writeb(s, addr, data);
 }
 
 MemoryRegionOps vga_mem_ops = {
     .read = vga_mem_read,
     .write = vga_mem_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static int vga_common_post_load(void *opaque, int version_id)
diff --git a/hw/vga_int.h b/hw/vga_int.h
index 0ef9962..37b0a09 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -202,8 +202,8 @@ void vga_dirty_log_restart(VGACommonState *s);
 extern const VMStateDescription vmstate_vga_common;
 uint32_t vga_ioport_read(void *opaque, uint32_t addr);
 void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val);
-uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr);
-void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val);
+uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr);
+void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val);
 void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2);
 int ppm_save(const char *filename, struct DisplaySurface *ds);
 
-- 
1.7.5.3

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

* [RFC v2 20/20] cirrus: simplify linear framebuffer access functions
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:22   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Make use of the memory API's ability to satisfy multi-byte accesses via
multiple single-byte accesses.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |   78 +++++++-----------------------------------------------
 1 files changed, 10 insertions(+), 68 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 1036eb2..88cb274 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2249,9 +2249,10 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
  *
  ***************************************/
 
-static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_linear_read(MemoryRegion *mr, target_phys_addr_t addr,
+                                   unsigned size)
 {
-    CirrusVGAState *s = opaque;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
     uint32_t ret;
 
     addr &= s->cirrus_addr_mask;
@@ -2277,30 +2278,10 @@ static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_readb(opaque, addr);
-    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_readb(opaque, addr);
-    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
-    v |= cirrus_linear_readb(opaque, addr + 2) << 16;
-    v |= cirrus_linear_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
+static void cirrus_linear_write(MemoryRegion *mr, target_phys_addr_t addr,
+                                uint64_t val, unsigned size)
 {
-    CirrusVGAState *s = opaque;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
     unsigned mode;
 
     addr &= s->cirrus_addr_mask;
@@ -2338,49 +2319,6 @@ static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
-{
-    cirrus_linear_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
-{
-    cirrus_linear_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-
-static uint64_t cirrus_linear_read(MemoryRegion *mr, target_phys_addr_t addr,
-                                   unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
-
-    switch (size) {
-    case 1: return cirrus_linear_readb(s, addr);
-    case 2: return cirrus_linear_readw(s, addr);
-    case 4: return cirrus_linear_readl(s, addr);
-    default: abort();
-    }
-}
-
-static void cirrus_linear_write(MemoryRegion *mr, target_phys_addr_t addr,
-                                uint64_t data, unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
-
-    switch (size) {
-    case 1: return cirrus_linear_writeb(s, addr, data);
-    case 2: return cirrus_linear_writew(s, addr, data);
-    case 4: return cirrus_linear_writel(s, addr, data);
-    default: abort();
-    }
-}
-
 /***************************************
  *
  *  system to screen memory access
@@ -2862,6 +2800,10 @@ static MemoryRegionOps cirrus_linear_io_ops = {
     .read = cirrus_linear_read,
     .write = cirrus_linear_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
-- 
1.7.5.3


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

* [Qemu-devel] [RFC v2 20/20] cirrus: simplify linear framebuffer access functions
@ 2011-06-27 13:22   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 13:22 UTC (permalink / raw)
  To: qemu-devel; +Cc: kvm

Make use of the memory API's ability to satisfy multi-byte accesses via
multiple single-byte accesses.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 hw/cirrus_vga.c |   78 +++++++-----------------------------------------------
 1 files changed, 10 insertions(+), 68 deletions(-)

diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 1036eb2..88cb274 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2249,9 +2249,10 @@ static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
  *
  ***************************************/
 
-static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t cirrus_linear_read(MemoryRegion *mr, target_phys_addr_t addr,
+                                   unsigned size)
 {
-    CirrusVGAState *s = opaque;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
     uint32_t ret;
 
     addr &= s->cirrus_addr_mask;
@@ -2277,30 +2278,10 @@ static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_readb(opaque, addr);
-    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
-    return v;
-}
-
-static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
-{
-    uint32_t v;
-
-    v = cirrus_linear_readb(opaque, addr);
-    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
-    v |= cirrus_linear_readb(opaque, addr + 2) << 16;
-    v |= cirrus_linear_readb(opaque, addr + 3) << 24;
-    return v;
-}
-
-static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
+static void cirrus_linear_write(MemoryRegion *mr, target_phys_addr_t addr,
+                                uint64_t val, unsigned size)
 {
-    CirrusVGAState *s = opaque;
+    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
     unsigned mode;
 
     addr &= s->cirrus_addr_mask;
@@ -2338,49 +2319,6 @@ static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
-{
-    cirrus_linear_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-}
-
-static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
-				 uint32_t val)
-{
-    cirrus_linear_writeb(opaque, addr, val & 0xff);
-    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-    cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
-    cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-}
-
-
-static uint64_t cirrus_linear_read(MemoryRegion *mr, target_phys_addr_t addr,
-                                   unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
-
-    switch (size) {
-    case 1: return cirrus_linear_readb(s, addr);
-    case 2: return cirrus_linear_readw(s, addr);
-    case 4: return cirrus_linear_readl(s, addr);
-    default: abort();
-    }
-}
-
-static void cirrus_linear_write(MemoryRegion *mr, target_phys_addr_t addr,
-                                uint64_t data, unsigned size)
-{
-    CirrusVGAState *s = container_of(mr, CirrusVGAState, cirrus_linear_io);
-
-    switch (size) {
-    case 1: return cirrus_linear_writeb(s, addr, data);
-    case 2: return cirrus_linear_writew(s, addr, data);
-    case 4: return cirrus_linear_writel(s, addr, data);
-    default: abort();
-    }
-}
-
 /***************************************
  *
  *  system to screen memory access
@@ -2862,6 +2800,10 @@ static MemoryRegionOps cirrus_linear_io_ops = {
     .read = cirrus_linear_read,
     .write = cirrus_linear_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
 };
 
 static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
-- 
1.7.5.3

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

* Re: [RFC v2 03/20] memory: merge adjacent segments of a single memory region
  2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 13:56     ` Jan Kiszka
  -1 siblings, 0 replies; 79+ messages in thread
From: Jan Kiszka @ 2011-06-27 13:56 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 2011-06-27 15:21, 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.

That reminds me of KVM_CAP_JOIN_MEMORY_REGIONS_WORKS. Have you checked
if things still work in the absence of the feature or if we need to lift
our requirements on the host kernel (would be 2.6.30, not that problematic)?

Jan

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux

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

* Re: [Qemu-devel] [RFC v2 03/20] memory: merge adjacent segments of a single memory region
@ 2011-06-27 13:56     ` Jan Kiszka
  0 siblings, 0 replies; 79+ messages in thread
From: Jan Kiszka @ 2011-06-27 13:56 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 2011-06-27 15:21, 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.

That reminds me of KVM_CAP_JOIN_MEMORY_REGIONS_WORKS. Have you checked
if things still work in the absence of the feature or if we need to lift
our requirements on the host kernel (would be 2.6.30, not that problematic)?

Jan

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux

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

* Re: [RFC v2 03/20] memory: merge adjacent segments of a single memory region
  2011-06-27 13:56     ` [Qemu-devel] " Jan Kiszka
@ 2011-06-27 14:11       ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 14:11 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel, kvm

On 06/27/2011 04:56 PM, Jan Kiszka wrote:
> On 2011-06-27 15:21, 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.
>
> That reminds me of KVM_CAP_JOIN_MEMORY_REGIONS_WORKS. Have you checked
> if things still work in the absence of the feature or if we need to lift
> our requirements on the host kernel (would be 2.6.30, not that problematic)?

Good catch.

We should probably disable merging if it doesn't work.  Or we should 
declare that a kernel bug should be fixed in the kernel, not userspace, 
and backport the fix to 2.6.27.whatever.

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


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

* Re: [Qemu-devel] [RFC v2 03/20] memory: merge adjacent segments of a single memory region
@ 2011-06-27 14:11       ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 14:11 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel, kvm

On 06/27/2011 04:56 PM, Jan Kiszka wrote:
> On 2011-06-27 15:21, 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.
>
> That reminds me of KVM_CAP_JOIN_MEMORY_REGIONS_WORKS. Have you checked
> if things still work in the absence of the feature or if we need to lift
> our requirements on the host kernel (would be 2.6.30, not that problematic)?

Good catch.

We should probably disable merging if it doesn't work.  Or we should 
declare that a kernel bug should be fixed in the kernel, not userspace, 
and backport the fix to 2.6.27.whatever.

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

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

* Re: [RFC v2 00/20] Memory API
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 15:13   ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 15:13 UTC (permalink / raw)
  To: qemu-devel, Michael S. Tsirkin; +Cc: kvm

On 06/27/2011 04:21 PM, Avi Kivity wrote:
> As expected, this is taking longer than expected, so I'm releasing something
> less complete than I'd have liked.  Not even all of the PC machine is
> converted, but the difficult parts are (cirrus).  It appears to work well.
>
> The major change compared to v1 is the introduction of
> memory_region_init_alias(), which defines a memory region in terms of another.
> With the current API, the ability to alias is provided by address arithmetic
> on ram_addr_t:
>
>    ram_addr = qemu_ram_alloc(...);
>    cpu_register_physical_memory(..., ram_addr, size, ...);
>    /* alias: */
>    cpu_register_physical_memory(..., ram_addr + offset, another_size, ...);
>
> With the new API, you have to create an alias:
>
>    memory_region_init_ram(&mem, ...);
>    memory_region_register_subregion(...,&mem);
>    /* alias: */
>    memory_region_init_alias(&alias, ...,&mem, offset, another_size);
>    memory_region_register_subregion(...,&alias);
>
> The patchset is somewhat churny.  One of the reasons is that we move from a
> handle/pointer scheme in ram_addr_t to an object constructor/destructor scheme.
> Another is that region size becomes a property of a region instead of being
> maintained externally.  Also, container memory regions must be passed around,
> though we don't do that as well as we should.
>
> Todo:
>    - eliminate calls to get_system_memory() (where we ignore the bus hierarchy)
>    - add PCI APIs for the VGA window
>    - support the PIO address space using the memory API (allowing simplified
>      PCI BAR registration)
>    - convert 440FX
>    - convert everything else

Michael, I'm looking at the pci bridge code, and it basically does the 
same thing - clip each BAR to the intersection of the decode window of 
all bridges it hides behind.

How does a PCI bridge behave wrt VGA?  is it a separate control?  If so 
I probably need to implement generalized clipping (i.e. decode between 
0xa0000-0xc0000 or between 0xc0000000-0xf0000000).

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


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

* Re: [Qemu-devel] [RFC v2 00/20] Memory API
@ 2011-06-27 15:13   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 15:13 UTC (permalink / raw)
  To: qemu-devel, Michael S. Tsirkin; +Cc: kvm

On 06/27/2011 04:21 PM, Avi Kivity wrote:
> As expected, this is taking longer than expected, so I'm releasing something
> less complete than I'd have liked.  Not even all of the PC machine is
> converted, but the difficult parts are (cirrus).  It appears to work well.
>
> The major change compared to v1 is the introduction of
> memory_region_init_alias(), which defines a memory region in terms of another.
> With the current API, the ability to alias is provided by address arithmetic
> on ram_addr_t:
>
>    ram_addr = qemu_ram_alloc(...);
>    cpu_register_physical_memory(..., ram_addr, size, ...);
>    /* alias: */
>    cpu_register_physical_memory(..., ram_addr + offset, another_size, ...);
>
> With the new API, you have to create an alias:
>
>    memory_region_init_ram(&mem, ...);
>    memory_region_register_subregion(...,&mem);
>    /* alias: */
>    memory_region_init_alias(&alias, ...,&mem, offset, another_size);
>    memory_region_register_subregion(...,&alias);
>
> The patchset is somewhat churny.  One of the reasons is that we move from a
> handle/pointer scheme in ram_addr_t to an object constructor/destructor scheme.
> Another is that region size becomes a property of a region instead of being
> maintained externally.  Also, container memory regions must be passed around,
> though we don't do that as well as we should.
>
> Todo:
>    - eliminate calls to get_system_memory() (where we ignore the bus hierarchy)
>    - add PCI APIs for the VGA window
>    - support the PIO address space using the memory API (allowing simplified
>      PCI BAR registration)
>    - convert 440FX
>    - convert everything else

Michael, I'm looking at the pci bridge code, and it basically does the 
same thing - clip each BAR to the intersection of the decode window of 
all bridges it hides behind.

How does a PCI bridge behave wrt VGA?  is it a separate control?  If so 
I probably need to implement generalized clipping (i.e. decode between 
0xa0000-0xc0000 or between 0xc0000000-0xf0000000).

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

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

* Re: [Qemu-devel] [RFC v2 00/20] Memory API
  2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
                   ` (21 preceding siblings ...)
  (?)
@ 2011-06-27 15:37 ` Anthony Liguori
  2011-06-27 15:44   ` Avi Kivity
  -1 siblings, 1 reply; 79+ messages in thread
From: Anthony Liguori @ 2011-06-27 15:37 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On 06/27/2011 08:21 AM, Avi Kivity wrote:
> As expected, this is taking longer than expected, so I'm releasing something
> less complete than I'd have liked.  Not even all of the PC machine is
> converted, but the difficult parts are (cirrus).  It appears to work well.
>
> The major change compared to v1 is the introduction of
> memory_region_init_alias(), which defines a memory region in terms of another.
> With the current API, the ability to alias is provided by address arithmetic
> on ram_addr_t:
>
>    ram_addr = qemu_ram_alloc(...);
>    cpu_register_physical_memory(..., ram_addr, size, ...);
>    /* alias: */
>    cpu_register_physical_memory(..., ram_addr + offset, another_size, ...);
>
> With the new API, you have to create an alias:
>
>    memory_region_init_ram(&mem, ...);
>    memory_region_register_subregion(...,&mem);
>    /* alias: */
>    memory_region_init_alias(&alias, ...,&mem, offset, another_size);
>    memory_region_register_subregion(...,&alias);

What's the rationale for explicit aliasing verses registering the same 
region to two different address spaces?

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] [RFC v2 00/20] Memory API
  2011-06-27 15:37 ` Anthony Liguori
@ 2011-06-27 15:44   ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 15:44 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, kvm

On 06/27/2011 06:37 PM, Anthony Liguori wrote:
> On 06/27/2011 08:21 AM, Avi Kivity wrote:
>> As expected, this is taking longer than expected, so I'm releasing 
>> something
>> less complete than I'd have liked.  Not even all of the PC machine is
>> converted, but the difficult parts are (cirrus).  It appears to work 
>> well.
>>
>> The major change compared to v1 is the introduction of
>> memory_region_init_alias(), which defines a memory region in terms of 
>> another.
>> With the current API, the ability to alias is provided by address 
>> arithmetic
>> on ram_addr_t:
>>
>>    ram_addr = qemu_ram_alloc(...);
>>    cpu_register_physical_memory(..., ram_addr, size, ...);
>>    /* alias: */
>>    cpu_register_physical_memory(..., ram_addr + offset, another_size, 
>> ...);
>>
>> With the new API, you have to create an alias:
>>
>>    memory_region_init_ram(&mem, ...);
>>    memory_region_register_subregion(...,&mem);
>>    /* alias: */
>>    memory_region_init_alias(&alias, ...,&mem, offset, another_size);
>>    memory_region_register_subregion(...,&alias);
>
> What's the rationale for explicit aliasing verses registering the same 
> region to two different address spaces?

Two:

- an alias is usually just a portion of the original region (vga 
windows; the two main RAM sections below and above 4GB); so we need an 
object to hold the differences
- easier for the implementation (a MemoryRegion object can be in just 
one child list instead of many)

While I can work around the implementation difficulties, there's no 
point since the alias is usually not identical to the origin, so we need 
a new object anyway.

(ram_addr_t works around that by carrying the offset in the handle, and 
letting the caller carry the size).

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


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

* Re: [RFC v2 00/20] Memory API
  2011-06-27 15:13   ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 15:52     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 79+ messages in thread
From: Michael S. Tsirkin @ 2011-06-27 15:52 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On Mon, Jun 27, 2011 at 06:13:03PM +0300, Avi Kivity wrote:
> On 06/27/2011 04:21 PM, Avi Kivity wrote:
> >As expected, this is taking longer than expected, so I'm releasing something
> >less complete than I'd have liked.  Not even all of the PC machine is
> >converted, but the difficult parts are (cirrus).  It appears to work well.
> >
> >The major change compared to v1 is the introduction of
> >memory_region_init_alias(), which defines a memory region in terms of another.
> >With the current API, the ability to alias is provided by address arithmetic
> >on ram_addr_t:
> >
> >   ram_addr = qemu_ram_alloc(...);
> >   cpu_register_physical_memory(..., ram_addr, size, ...);
> >   /* alias: */
> >   cpu_register_physical_memory(..., ram_addr + offset, another_size, ...);
> >
> >With the new API, you have to create an alias:
> >
> >   memory_region_init_ram(&mem, ...);
> >   memory_region_register_subregion(...,&mem);
> >   /* alias: */
> >   memory_region_init_alias(&alias, ...,&mem, offset, another_size);
> >   memory_region_register_subregion(...,&alias);
> >
> >The patchset is somewhat churny.  One of the reasons is that we move from a
> >handle/pointer scheme in ram_addr_t to an object constructor/destructor scheme.
> >Another is that region size becomes a property of a region instead of being
> >maintained externally.  Also, container memory regions must be passed around,
> >though we don't do that as well as we should.
> >
> >Todo:
> >   - eliminate calls to get_system_memory() (where we ignore the bus hierarchy)
> >   - add PCI APIs for the VGA window
> >   - support the PIO address space using the memory API (allowing simplified
> >     PCI BAR registration)
> >   - convert 440FX
> >   - convert everything else
> 
> Michael, I'm looking at the pci bridge code, and it basically does
> the same thing - clip each BAR to the intersection of the decode
> window of all bridges it hides behind.
> 
> How does a PCI bridge behave wrt VGA?  is it a separate control?  If
> so I probably need to implement generalized clipping (i.e. decode
> between 0xa0000-0xc0000 or between 0xc0000000-0xf0000000).

Per spec, VGA is special:
- bridges have VGA enable bit 

The VGA Enable bit in the Bridge Control register (see Section 3.2.5.18)
is used to control response by the bridge to both the VGA frame buffer
addresses and to the VGA register addresses. When a VGA compatible
device is located downstream of a PCI-to-PCI bridge, the VGA Enable bit
must be set. When set, the bridge will positively decode and forward
memory accesses to VGA frame buffer addresses and I/O accesses to VGA
registers from the primary to secondary interface and block forwarding
of these same accesses from the secondary to primary interface (see
Section 4.5.1).
VGA memory addresses:
0A 0000h through 0B FFFFh
VGA I/O addresses (including ISA aliases address - AD[15::10] are not
decoded):
AD[9::0] = 3B0h through 3BBh and 3C0h through 3DFh
The bridge does not decode or forward VGA BIOS memory addresses when the
VGA Enable bit is set. ROM code provided by PCI compatible devices may
be mapped to any address in PCI memory address space via the Expansion
ROM Base Address register in the device's configuration header and must
be copied to system memory before execution.


- bridges might also enable subtractive decoding
  (required for isa behind the bridge)


Both are currently unimplemented.

-- 
MST

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

* Re: [Qemu-devel] [RFC v2 00/20] Memory API
@ 2011-06-27 15:52     ` Michael S. Tsirkin
  0 siblings, 0 replies; 79+ messages in thread
From: Michael S. Tsirkin @ 2011-06-27 15:52 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On Mon, Jun 27, 2011 at 06:13:03PM +0300, Avi Kivity wrote:
> On 06/27/2011 04:21 PM, Avi Kivity wrote:
> >As expected, this is taking longer than expected, so I'm releasing something
> >less complete than I'd have liked.  Not even all of the PC machine is
> >converted, but the difficult parts are (cirrus).  It appears to work well.
> >
> >The major change compared to v1 is the introduction of
> >memory_region_init_alias(), which defines a memory region in terms of another.
> >With the current API, the ability to alias is provided by address arithmetic
> >on ram_addr_t:
> >
> >   ram_addr = qemu_ram_alloc(...);
> >   cpu_register_physical_memory(..., ram_addr, size, ...);
> >   /* alias: */
> >   cpu_register_physical_memory(..., ram_addr + offset, another_size, ...);
> >
> >With the new API, you have to create an alias:
> >
> >   memory_region_init_ram(&mem, ...);
> >   memory_region_register_subregion(...,&mem);
> >   /* alias: */
> >   memory_region_init_alias(&alias, ...,&mem, offset, another_size);
> >   memory_region_register_subregion(...,&alias);
> >
> >The patchset is somewhat churny.  One of the reasons is that we move from a
> >handle/pointer scheme in ram_addr_t to an object constructor/destructor scheme.
> >Another is that region size becomes a property of a region instead of being
> >maintained externally.  Also, container memory regions must be passed around,
> >though we don't do that as well as we should.
> >
> >Todo:
> >   - eliminate calls to get_system_memory() (where we ignore the bus hierarchy)
> >   - add PCI APIs for the VGA window
> >   - support the PIO address space using the memory API (allowing simplified
> >     PCI BAR registration)
> >   - convert 440FX
> >   - convert everything else
> 
> Michael, I'm looking at the pci bridge code, and it basically does
> the same thing - clip each BAR to the intersection of the decode
> window of all bridges it hides behind.
> 
> How does a PCI bridge behave wrt VGA?  is it a separate control?  If
> so I probably need to implement generalized clipping (i.e. decode
> between 0xa0000-0xc0000 or between 0xc0000000-0xf0000000).

Per spec, VGA is special:
- bridges have VGA enable bit 

The VGA Enable bit in the Bridge Control register (see Section 3.2.5.18)
is used to control response by the bridge to both the VGA frame buffer
addresses and to the VGA register addresses. When a VGA compatible
device is located downstream of a PCI-to-PCI bridge, the VGA Enable bit
must be set. When set, the bridge will positively decode and forward
memory accesses to VGA frame buffer addresses and I/O accesses to VGA
registers from the primary to secondary interface and block forwarding
of these same accesses from the secondary to primary interface (see
Section 4.5.1).
VGA memory addresses:
0A 0000h through 0B FFFFh
VGA I/O addresses (including ISA aliases address - AD[15::10] are not
decoded):
AD[9::0] = 3B0h through 3BBh and 3C0h through 3DFh
The bridge does not decode or forward VGA BIOS memory addresses when the
VGA Enable bit is set. ROM code provided by PCI compatible devices may
be mapped to any address in PCI memory address space via the Expansion
ROM Base Address register in the device's configuration header and must
be copied to system memory before execution.


- bridges might also enable subtractive decoding
  (required for isa behind the bridge)


Both are currently unimplemented.

-- 
MST

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

* Re: [RFC v2 00/20] Memory API
  2011-06-27 15:52     ` [Qemu-devel] " Michael S. Tsirkin
@ 2011-06-27 15:54       ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 15:54 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel, kvm

On 06/27/2011 06:52 PM, Michael S. Tsirkin wrote:
> On Mon, Jun 27, 2011 at 06:13:03PM +0300, Avi Kivity wrote:
> >  On 06/27/2011 04:21 PM, Avi Kivity wrote:
> >  >As expected, this is taking longer than expected, so I'm releasing something
> >  >less complete than I'd have liked.  Not even all of the PC machine is
> >  >converted, but the difficult parts are (cirrus).  It appears to work well.
> >  >
> >  >The major change compared to v1 is the introduction of
> >  >memory_region_init_alias(), which defines a memory region in terms of another.
> >  >With the current API, the ability to alias is provided by address arithmetic
> >  >on ram_addr_t:
> >  >
> >  >    ram_addr = qemu_ram_alloc(...);
> >  >    cpu_register_physical_memory(..., ram_addr, size, ...);
> >  >    /* alias: */
> >  >    cpu_register_physical_memory(..., ram_addr + offset, another_size, ...);
> >  >
> >  >With the new API, you have to create an alias:
> >  >
> >  >    memory_region_init_ram(&mem, ...);
> >  >    memory_region_register_subregion(...,&mem);
> >  >    /* alias: */
> >  >    memory_region_init_alias(&alias, ...,&mem, offset, another_size);
> >  >    memory_region_register_subregion(...,&alias);
> >  >
> >  >The patchset is somewhat churny.  One of the reasons is that we move from a
> >  >handle/pointer scheme in ram_addr_t to an object constructor/destructor scheme.
> >  >Another is that region size becomes a property of a region instead of being
> >  >maintained externally.  Also, container memory regions must be passed around,
> >  >though we don't do that as well as we should.
> >  >
> >  >Todo:
> >  >    - eliminate calls to get_system_memory() (where we ignore the bus hierarchy)
> >  >    - add PCI APIs for the VGA window
> >  >    - support the PIO address space using the memory API (allowing simplified
> >  >      PCI BAR registration)
> >  >    - convert 440FX
> >  >    - convert everything else
> >
> >  Michael, I'm looking at the pci bridge code, and it basically does
> >  the same thing - clip each BAR to the intersection of the decode
> >  window of all bridges it hides behind.
> >
> >  How does a PCI bridge behave wrt VGA?  is it a separate control?  If
> >  so I probably need to implement generalized clipping (i.e. decode
> >  between 0xa0000-0xc0000 or between 0xc0000000-0xf0000000).
>
> Per spec, VGA is special:
> - bridges have VGA enable bit
>
> The VGA Enable bit in the Bridge Control register (see Section 3.2.5.18)
> is used to control response by the bridge to both the VGA frame buffer
> addresses and to the VGA register addresses. When a VGA compatible
> device is located downstream of a PCI-to-PCI bridge, the VGA Enable bit
> must be set. When set, the bridge will positively decode and forward
> memory accesses to VGA frame buffer addresses and I/O accesses to VGA
> registers from the primary to secondary interface and block forwarding
> of these same accesses from the secondary to primary interface (see
> Section 4.5.1).
> VGA memory addresses:
> 0A 0000h through 0B FFFFh
> VGA I/O addresses (including ISA aliases address - AD[15::10] are not
> decoded):
> AD[9::0] = 3B0h through 3BBh and 3C0h through 3DFh
> The bridge does not decode or forward VGA BIOS memory addresses when the
> VGA Enable bit is set. ROM code provided by PCI compatible devices may
> be mapped to any address in PCI memory address space via the Expansion
> ROM Base Address register in the device's configuration header and must
> be copied to system memory before execution.
>

Okay, looks like generalized clipping is needed.  It's nice anyway and 
guarantees me a job for life as maintainer of memory.c.


> - bridges might also enable subtractive decoding
>    (required for isa behind the bridge)

What does that mean?

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


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

* Re: [Qemu-devel] [RFC v2 00/20] Memory API
@ 2011-06-27 15:54       ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 15:54 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel, kvm

On 06/27/2011 06:52 PM, Michael S. Tsirkin wrote:
> On Mon, Jun 27, 2011 at 06:13:03PM +0300, Avi Kivity wrote:
> >  On 06/27/2011 04:21 PM, Avi Kivity wrote:
> >  >As expected, this is taking longer than expected, so I'm releasing something
> >  >less complete than I'd have liked.  Not even all of the PC machine is
> >  >converted, but the difficult parts are (cirrus).  It appears to work well.
> >  >
> >  >The major change compared to v1 is the introduction of
> >  >memory_region_init_alias(), which defines a memory region in terms of another.
> >  >With the current API, the ability to alias is provided by address arithmetic
> >  >on ram_addr_t:
> >  >
> >  >    ram_addr = qemu_ram_alloc(...);
> >  >    cpu_register_physical_memory(..., ram_addr, size, ...);
> >  >    /* alias: */
> >  >    cpu_register_physical_memory(..., ram_addr + offset, another_size, ...);
> >  >
> >  >With the new API, you have to create an alias:
> >  >
> >  >    memory_region_init_ram(&mem, ...);
> >  >    memory_region_register_subregion(...,&mem);
> >  >    /* alias: */
> >  >    memory_region_init_alias(&alias, ...,&mem, offset, another_size);
> >  >    memory_region_register_subregion(...,&alias);
> >  >
> >  >The patchset is somewhat churny.  One of the reasons is that we move from a
> >  >handle/pointer scheme in ram_addr_t to an object constructor/destructor scheme.
> >  >Another is that region size becomes a property of a region instead of being
> >  >maintained externally.  Also, container memory regions must be passed around,
> >  >though we don't do that as well as we should.
> >  >
> >  >Todo:
> >  >    - eliminate calls to get_system_memory() (where we ignore the bus hierarchy)
> >  >    - add PCI APIs for the VGA window
> >  >    - support the PIO address space using the memory API (allowing simplified
> >  >      PCI BAR registration)
> >  >    - convert 440FX
> >  >    - convert everything else
> >
> >  Michael, I'm looking at the pci bridge code, and it basically does
> >  the same thing - clip each BAR to the intersection of the decode
> >  window of all bridges it hides behind.
> >
> >  How does a PCI bridge behave wrt VGA?  is it a separate control?  If
> >  so I probably need to implement generalized clipping (i.e. decode
> >  between 0xa0000-0xc0000 or between 0xc0000000-0xf0000000).
>
> Per spec, VGA is special:
> - bridges have VGA enable bit
>
> The VGA Enable bit in the Bridge Control register (see Section 3.2.5.18)
> is used to control response by the bridge to both the VGA frame buffer
> addresses and to the VGA register addresses. When a VGA compatible
> device is located downstream of a PCI-to-PCI bridge, the VGA Enable bit
> must be set. When set, the bridge will positively decode and forward
> memory accesses to VGA frame buffer addresses and I/O accesses to VGA
> registers from the primary to secondary interface and block forwarding
> of these same accesses from the secondary to primary interface (see
> Section 4.5.1).
> VGA memory addresses:
> 0A 0000h through 0B FFFFh
> VGA I/O addresses (including ISA aliases address - AD[15::10] are not
> decoded):
> AD[9::0] = 3B0h through 3BBh and 3C0h through 3DFh
> The bridge does not decode or forward VGA BIOS memory addresses when the
> VGA Enable bit is set. ROM code provided by PCI compatible devices may
> be mapped to any address in PCI memory address space via the Expansion
> ROM Base Address register in the device's configuration header and must
> be copied to system memory before execution.
>

Okay, looks like generalized clipping is needed.  It's nice anyway and 
guarantees me a job for life as maintainer of memory.c.


> - bridges might also enable subtractive decoding
>    (required for isa behind the bridge)

What does that mean?

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

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

* Re: [RFC v2 00/20] Memory API
  2011-06-27 15:54       ` [Qemu-devel] " Avi Kivity
@ 2011-06-27 15:59         ` Michael S. Tsirkin
  -1 siblings, 0 replies; 79+ messages in thread
From: Michael S. Tsirkin @ 2011-06-27 15:59 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On Mon, Jun 27, 2011 at 06:54:05PM +0300, Avi Kivity wrote:
> On 06/27/2011 06:52 PM, Michael S. Tsirkin wrote:
> >On Mon, Jun 27, 2011 at 06:13:03PM +0300, Avi Kivity wrote:
> >>  On 06/27/2011 04:21 PM, Avi Kivity wrote:
> >>  >As expected, this is taking longer than expected, so I'm releasing something
> >>  >less complete than I'd have liked.  Not even all of the PC machine is
> >>  >converted, but the difficult parts are (cirrus).  It appears to work well.
> >>  >
> >>  >The major change compared to v1 is the introduction of
> >>  >memory_region_init_alias(), which defines a memory region in terms of another.
> >>  >With the current API, the ability to alias is provided by address arithmetic
> >>  >on ram_addr_t:
> >>  >
> >>  >    ram_addr = qemu_ram_alloc(...);
> >>  >    cpu_register_physical_memory(..., ram_addr, size, ...);
> >>  >    /* alias: */
> >>  >    cpu_register_physical_memory(..., ram_addr + offset, another_size, ...);
> >>  >
> >>  >With the new API, you have to create an alias:
> >>  >
> >>  >    memory_region_init_ram(&mem, ...);
> >>  >    memory_region_register_subregion(...,&mem);
> >>  >    /* alias: */
> >>  >    memory_region_init_alias(&alias, ...,&mem, offset, another_size);
> >>  >    memory_region_register_subregion(...,&alias);
> >>  >
> >>  >The patchset is somewhat churny.  One of the reasons is that we move from a
> >>  >handle/pointer scheme in ram_addr_t to an object constructor/destructor scheme.
> >>  >Another is that region size becomes a property of a region instead of being
> >>  >maintained externally.  Also, container memory regions must be passed around,
> >>  >though we don't do that as well as we should.
> >>  >
> >>  >Todo:
> >>  >    - eliminate calls to get_system_memory() (where we ignore the bus hierarchy)
> >>  >    - add PCI APIs for the VGA window
> >>  >    - support the PIO address space using the memory API (allowing simplified
> >>  >      PCI BAR registration)
> >>  >    - convert 440FX
> >>  >    - convert everything else
> >>
> >>  Michael, I'm looking at the pci bridge code, and it basically does
> >>  the same thing - clip each BAR to the intersection of the decode
> >>  window of all bridges it hides behind.
> >>
> >>  How does a PCI bridge behave wrt VGA?  is it a separate control?  If
> >>  so I probably need to implement generalized clipping (i.e. decode
> >>  between 0xa0000-0xc0000 or between 0xc0000000-0xf0000000).
> >
> >Per spec, VGA is special:
> >- bridges have VGA enable bit
> >
> >The VGA Enable bit in the Bridge Control register (see Section 3.2.5.18)
> >is used to control response by the bridge to both the VGA frame buffer
> >addresses and to the VGA register addresses. When a VGA compatible
> >device is located downstream of a PCI-to-PCI bridge, the VGA Enable bit
> >must be set. When set, the bridge will positively decode and forward
> >memory accesses to VGA frame buffer addresses and I/O accesses to VGA
> >registers from the primary to secondary interface and block forwarding
> >of these same accesses from the secondary to primary interface (see
> >Section 4.5.1).
> >VGA memory addresses:
> >0A 0000h through 0B FFFFh
> >VGA I/O addresses (including ISA aliases address - AD[15::10] are not
> >decoded):
> >AD[9::0] = 3B0h through 3BBh and 3C0h through 3DFh
> >The bridge does not decode or forward VGA BIOS memory addresses when the
> >VGA Enable bit is set. ROM code provided by PCI compatible devices may
> >be mapped to any address in PCI memory address space via the Expansion
> >ROM Base Address register in the device's configuration header and must
> >be copied to system memory before execution.
> >
> 
> Okay, looks like generalized clipping is needed.  It's nice anyway
> and guarantees me a job for life as maintainer of memory.c.
> 
> 
> >- bridges might also enable subtractive decoding
> >   (required for isa behind the bridge)
> 
> What does that mean?

subtractive decoding is 
a method of address decoding in which a device accepts all
accesses not positively decoded by another agent.



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

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

* Re: [Qemu-devel] [RFC v2 00/20] Memory API
@ 2011-06-27 15:59         ` Michael S. Tsirkin
  0 siblings, 0 replies; 79+ messages in thread
From: Michael S. Tsirkin @ 2011-06-27 15:59 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On Mon, Jun 27, 2011 at 06:54:05PM +0300, Avi Kivity wrote:
> On 06/27/2011 06:52 PM, Michael S. Tsirkin wrote:
> >On Mon, Jun 27, 2011 at 06:13:03PM +0300, Avi Kivity wrote:
> >>  On 06/27/2011 04:21 PM, Avi Kivity wrote:
> >>  >As expected, this is taking longer than expected, so I'm releasing something
> >>  >less complete than I'd have liked.  Not even all of the PC machine is
> >>  >converted, but the difficult parts are (cirrus).  It appears to work well.
> >>  >
> >>  >The major change compared to v1 is the introduction of
> >>  >memory_region_init_alias(), which defines a memory region in terms of another.
> >>  >With the current API, the ability to alias is provided by address arithmetic
> >>  >on ram_addr_t:
> >>  >
> >>  >    ram_addr = qemu_ram_alloc(...);
> >>  >    cpu_register_physical_memory(..., ram_addr, size, ...);
> >>  >    /* alias: */
> >>  >    cpu_register_physical_memory(..., ram_addr + offset, another_size, ...);
> >>  >
> >>  >With the new API, you have to create an alias:
> >>  >
> >>  >    memory_region_init_ram(&mem, ...);
> >>  >    memory_region_register_subregion(...,&mem);
> >>  >    /* alias: */
> >>  >    memory_region_init_alias(&alias, ...,&mem, offset, another_size);
> >>  >    memory_region_register_subregion(...,&alias);
> >>  >
> >>  >The patchset is somewhat churny.  One of the reasons is that we move from a
> >>  >handle/pointer scheme in ram_addr_t to an object constructor/destructor scheme.
> >>  >Another is that region size becomes a property of a region instead of being
> >>  >maintained externally.  Also, container memory regions must be passed around,
> >>  >though we don't do that as well as we should.
> >>  >
> >>  >Todo:
> >>  >    - eliminate calls to get_system_memory() (where we ignore the bus hierarchy)
> >>  >    - add PCI APIs for the VGA window
> >>  >    - support the PIO address space using the memory API (allowing simplified
> >>  >      PCI BAR registration)
> >>  >    - convert 440FX
> >>  >    - convert everything else
> >>
> >>  Michael, I'm looking at the pci bridge code, and it basically does
> >>  the same thing - clip each BAR to the intersection of the decode
> >>  window of all bridges it hides behind.
> >>
> >>  How does a PCI bridge behave wrt VGA?  is it a separate control?  If
> >>  so I probably need to implement generalized clipping (i.e. decode
> >>  between 0xa0000-0xc0000 or between 0xc0000000-0xf0000000).
> >
> >Per spec, VGA is special:
> >- bridges have VGA enable bit
> >
> >The VGA Enable bit in the Bridge Control register (see Section 3.2.5.18)
> >is used to control response by the bridge to both the VGA frame buffer
> >addresses and to the VGA register addresses. When a VGA compatible
> >device is located downstream of a PCI-to-PCI bridge, the VGA Enable bit
> >must be set. When set, the bridge will positively decode and forward
> >memory accesses to VGA frame buffer addresses and I/O accesses to VGA
> >registers from the primary to secondary interface and block forwarding
> >of these same accesses from the secondary to primary interface (see
> >Section 4.5.1).
> >VGA memory addresses:
> >0A 0000h through 0B FFFFh
> >VGA I/O addresses (including ISA aliases address - AD[15::10] are not
> >decoded):
> >AD[9::0] = 3B0h through 3BBh and 3C0h through 3DFh
> >The bridge does not decode or forward VGA BIOS memory addresses when the
> >VGA Enable bit is set. ROM code provided by PCI compatible devices may
> >be mapped to any address in PCI memory address space via the Expansion
> >ROM Base Address register in the device's configuration header and must
> >be copied to system memory before execution.
> >
> 
> Okay, looks like generalized clipping is needed.  It's nice anyway
> and guarantees me a job for life as maintainer of memory.c.
> 
> 
> >- bridges might also enable subtractive decoding
> >   (required for isa behind the bridge)
> 
> What does that mean?

subtractive decoding is 
a method of address decoding in which a device accepts all
accesses not positively decoded by another agent.



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

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

* Re: [RFC v2 00/20] Memory API
  2011-06-27 15:59         ` [Qemu-devel] " Michael S. Tsirkin
@ 2011-06-27 16:10           ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 16:10 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel, kvm

On 06/27/2011 06:59 PM, Michael S. Tsirkin wrote:
> >
> >  >- bridges might also enable subtractive decoding
> >  >    (required for isa behind the bridge)
> >
> >  What does that mean?
>
> subtractive decoding is
> a method of address decoding in which a device accepts all
> accesses not positively decoded by another agent.
>

Okay, we implement that already via memory region priorities.

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


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

* Re: [Qemu-devel] [RFC v2 00/20] Memory API
@ 2011-06-27 16:10           ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-27 16:10 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel, kvm

On 06/27/2011 06:59 PM, Michael S. Tsirkin wrote:
> >
> >  >- bridges might also enable subtractive decoding
> >  >    (required for isa behind the bridge)
> >
> >  What does that mean?
>
> subtractive decoding is
> a method of address decoding in which a device accepts all
> accesses not positively decoded by another agent.
>

Okay, we implement that already via memory region priorities.

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

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

* Re: [Qemu-devel] [RFC v2 00/20] Memory API
  2011-06-27 15:59         ` [Qemu-devel] " Michael S. Tsirkin
@ 2011-06-27 20:28           ` Anthony Liguori
  -1 siblings, 0 replies; 79+ messages in thread
From: Anthony Liguori @ 2011-06-27 20:28 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Avi Kivity, qemu-devel, kvm

On 06/27/2011 10:59 AM, Michael S. Tsirkin wrote:
> On Mon, Jun 27, 2011 at 06:54:05PM +0300, Avi Kivity wrote:
>> On 06/27/2011 06:52 PM, Michael S. Tsirkin wrote:
>>> - bridges might also enable subtractive decoding
>>>    (required for isa behind the bridge)
>>
>> What does that mean?
>
> subtractive decoding is
> a method of address decoding in which a device accepts all
> accesses not positively decoded by another agent.

Subtractive decoding is very slow in real hardware so generally any well 
known devices are positively decoded (like anything on the Super I/O 
chip).  Unless we're dealing with very odd ISA devices, we probably 
don't need to worry about subtractive decoding.

The real key point is, each level may dispatch in subtly different ways. 
  You can get 95% of the way there with a generic memory API.  I think 
it's the 95% that actually matters but just realize that we can't model 
hardware exactly without true hierarchical dispatch.

Regards,

Anthony Liguori

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

* Re: [Qemu-devel] [RFC v2 00/20] Memory API
@ 2011-06-27 20:28           ` Anthony Liguori
  0 siblings, 0 replies; 79+ messages in thread
From: Anthony Liguori @ 2011-06-27 20:28 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Avi Kivity, kvm, qemu-devel

On 06/27/2011 10:59 AM, Michael S. Tsirkin wrote:
> On Mon, Jun 27, 2011 at 06:54:05PM +0300, Avi Kivity wrote:
>> On 06/27/2011 06:52 PM, Michael S. Tsirkin wrote:
>>> - bridges might also enable subtractive decoding
>>>    (required for isa behind the bridge)
>>
>> What does that mean?
>
> subtractive decoding is
> a method of address decoding in which a device accepts all
> accesses not positively decoded by another agent.

Subtractive decoding is very slow in real hardware so generally any well 
known devices are positively decoded (like anything on the Super I/O 
chip).  Unless we're dealing with very odd ISA devices, we probably 
don't need to worry about subtractive decoding.

The real key point is, each level may dispatch in subtly different ways. 
  You can get 95% of the way there with a generic memory API.  I think 
it's the 95% that actually matters but just realize that we can't model 
hardware exactly without true hierarchical dispatch.

Regards,

Anthony Liguori

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

* Re: [RFC v2 01/20] Hierarchical memory region API
  2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
@ 2011-06-28 10:03     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 79+ messages in thread
From: Michael S. Tsirkin @ 2011-06-28 10:03 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On Mon, Jun 27, 2011 at 04:21:48PM +0300, Avi Kivity wrote:

...

> +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.max_access_size;

min = max: Intentional? Cut&paste error?

> +    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;
> +    }

...

> diff --git a/memory.h b/memory.h
> new file mode 100644
> index 0000000..a67ff94
> --- /dev/null
> +++ b/memory.h
> @@ -0,0 +1,201 @@
> +#ifndef MEMORY_H
> +#define MEMORY_H
> +
> +#ifndef CONFIG_USER_ONLY

What's the story with this ifdef?
There are no stubs provided ...

> +
> +#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)(MemoryRegion *mr,
> +                     target_phys_addr_t addr,
> +                     unsigned size);
> +    /* Write to the memory region. @addr is relative to @mr; @size is
> +     * in bytes. */
> +    void (*write)(MemoryRegion *mr,
> +                  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;
> +    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;

I'm never completely sure whether these should be target addresses
or bus addresses or just uint64_t.
With pci on a 32 bit system you can stick a 64 bit address
in a BAR and the result will be that it is never accessed
from the CPU.

-- 
MST

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

* Re: [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
@ 2011-06-28 10:03     ` Michael S. Tsirkin
  0 siblings, 0 replies; 79+ messages in thread
From: Michael S. Tsirkin @ 2011-06-28 10:03 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm

On Mon, Jun 27, 2011 at 04:21:48PM +0300, Avi Kivity wrote:

...

> +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.max_access_size;

min = max: Intentional? Cut&paste error?

> +    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;
> +    }

...

> diff --git a/memory.h b/memory.h
> new file mode 100644
> index 0000000..a67ff94
> --- /dev/null
> +++ b/memory.h
> @@ -0,0 +1,201 @@
> +#ifndef MEMORY_H
> +#define MEMORY_H
> +
> +#ifndef CONFIG_USER_ONLY

What's the story with this ifdef?
There are no stubs provided ...

> +
> +#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)(MemoryRegion *mr,
> +                     target_phys_addr_t addr,
> +                     unsigned size);
> +    /* Write to the memory region. @addr is relative to @mr; @size is
> +     * in bytes. */
> +    void (*write)(MemoryRegion *mr,
> +                  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;
> +    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;

I'm never completely sure whether these should be target addresses
or bus addresses or just uint64_t.
With pci on a 32 bit system you can stick a 64 bit address
in a BAR and the result will be that it is never accessed
from the CPU.

-- 
MST

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

* Re: [RFC v2 01/20] Hierarchical memory region API
  2011-06-28 10:03     ` [Qemu-devel] " Michael S. Tsirkin
@ 2011-06-28 10:28       ` Jan Kiszka
  -1 siblings, 0 replies; 79+ messages in thread
From: Jan Kiszka @ 2011-06-28 10:28 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Avi Kivity, kvm, qemu-devel

On 2011-06-28 12:03, Michael S. Tsirkin wrote:
>> +struct MemoryRegion {
>> +    /* All fields are private - violators will be prosecuted */
>> +    const MemoryRegionOps *ops;
>> +    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;
> 
> I'm never completely sure whether these should be target addresses
> or bus addresses or just uint64_t.
> With pci on a 32 bit system you can stick a 64 bit address
> in a BAR and the result will be that it is never accessed
> from the CPU.
> 

Memory regions are not bound to any current or future PCI
specifications. Any fixed bit width would be wrong here, ie. size should
rather be target_phys_addr_t.

Jan

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux

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

* Re: [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
@ 2011-06-28 10:28       ` Jan Kiszka
  0 siblings, 0 replies; 79+ messages in thread
From: Jan Kiszka @ 2011-06-28 10:28 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Avi Kivity, kvm, qemu-devel

On 2011-06-28 12:03, Michael S. Tsirkin wrote:
>> +struct MemoryRegion {
>> +    /* All fields are private - violators will be prosecuted */
>> +    const MemoryRegionOps *ops;
>> +    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;
> 
> I'm never completely sure whether these should be target addresses
> or bus addresses or just uint64_t.
> With pci on a 32 bit system you can stick a 64 bit address
> in a BAR and the result will be that it is never accessed
> from the CPU.
> 

Memory regions are not bound to any current or future PCI
specifications. Any fixed bit width would be wrong here, ie. size should
rather be target_phys_addr_t.

Jan

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux

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

* Re: [RFC v2 01/20] Hierarchical memory region API
  2011-06-28 10:03     ` [Qemu-devel] " Michael S. Tsirkin
@ 2011-06-28 11:51       ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-28 11:51 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel, kvm

On 06/28/2011 01:03 PM, Michael S. Tsirkin wrote:
> On Mon, Jun 27, 2011 at 04:21:48PM +0300, Avi Kivity wrote:
>
> ...
>
> >  +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.max_access_size;
>
> min = max: Intentional? Cut&paste error?

Bug; thanks.

> >  diff --git a/memory.h b/memory.h
> >  new file mode 100644
> >  index 0000000..a67ff94
> >  --- /dev/null
> >  +++ b/memory.h
> >  @@ -0,0 +1,201 @@
> >  +#ifndef MEMORY_H
> >  +#define MEMORY_H
> >  +
> >  +#ifndef CONFIG_USER_ONLY
>
> What's the story with this ifdef?
> There are no stubs provided ...

No callers either - I build with a full configuration.  I prefer the 
#ifdef here rather than all call sites.

> >  +
> >  +struct MemoryRegion {
> >  +    /* All fields are private - violators will be prosecuted */
> >  +    const MemoryRegionOps *ops;
> >  +    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;
>
> I'm never completely sure whether these should be target addresses
> or bus addresses or just uint64_t.
> With pci on a 32 bit system you can stick a 64 bit address
> in a BAR and the result will be that it is never accessed
> from the CPU.
>

I agree.  Anyone objects to making the memory API 64-bit?

It will reduce performance slightly for 32-on-32, but these 
configurations are getting rarer, and the performance loss is quite small.

Maybe we should make t_p_a_t 64-bit unconditionally.  Note that sizes 
have to be 64-bit in any case, otherwise you can't express a 4G range 
without tricks.

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

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

* Re: [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
@ 2011-06-28 11:51       ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-28 11:51 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel, kvm

On 06/28/2011 01:03 PM, Michael S. Tsirkin wrote:
> On Mon, Jun 27, 2011 at 04:21:48PM +0300, Avi Kivity wrote:
>
> ...
>
> >  +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.max_access_size;
>
> min = max: Intentional? Cut&paste error?

Bug; thanks.

> >  diff --git a/memory.h b/memory.h
> >  new file mode 100644
> >  index 0000000..a67ff94
> >  --- /dev/null
> >  +++ b/memory.h
> >  @@ -0,0 +1,201 @@
> >  +#ifndef MEMORY_H
> >  +#define MEMORY_H
> >  +
> >  +#ifndef CONFIG_USER_ONLY
>
> What's the story with this ifdef?
> There are no stubs provided ...

No callers either - I build with a full configuration.  I prefer the 
#ifdef here rather than all call sites.

> >  +
> >  +struct MemoryRegion {
> >  +    /* All fields are private - violators will be prosecuted */
> >  +    const MemoryRegionOps *ops;
> >  +    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;
>
> I'm never completely sure whether these should be target addresses
> or bus addresses or just uint64_t.
> With pci on a 32 bit system you can stick a 64 bit address
> in a BAR and the result will be that it is never accessed
> from the CPU.
>

I agree.  Anyone objects to making the memory API 64-bit?

It will reduce performance slightly for 32-on-32, but these 
configurations are getting rarer, and the performance loss is quite small.

Maybe we should make t_p_a_t 64-bit unconditionally.  Note that sizes 
have to be 64-bit in any case, otherwise you can't express a 4G range 
without tricks.

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

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

* Re: [RFC v2 01/20] Hierarchical memory region API
  2011-06-28 10:28       ` [Qemu-devel] " Jan Kiszka
@ 2011-06-28 11:53         ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-28 11:53 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Michael S. Tsirkin, qemu-devel, kvm

On 06/28/2011 01:28 PM, Jan Kiszka wrote:
> On 2011-06-28 12:03, Michael S. Tsirkin wrote:
> >>  +struct MemoryRegion {
> >>  +    /* All fields are private - violators will be prosecuted */
> >>  +    const MemoryRegionOps *ops;
> >>  +    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;
> >
> >  I'm never completely sure whether these should be target addresses
> >  or bus addresses or just uint64_t.
> >  With pci on a 32 bit system you can stick a 64 bit address
> >  in a BAR and the result will be that it is never accessed
> >  from the CPU.
> >
>
> Memory regions are not bound to any current or future PCI
> specifications. Any fixed bit width would be wrong here, ie. size should
> rather be target_phys_addr_t.

The point is that different buses have different widths. 
target_phys_addr_t matches just one bus in the system.  It needs to be 
the maximum size of all buses present to be useful.

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


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

* Re: [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
@ 2011-06-28 11:53         ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-28 11:53 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel, kvm, Michael S. Tsirkin

On 06/28/2011 01:28 PM, Jan Kiszka wrote:
> On 2011-06-28 12:03, Michael S. Tsirkin wrote:
> >>  +struct MemoryRegion {
> >>  +    /* All fields are private - violators will be prosecuted */
> >>  +    const MemoryRegionOps *ops;
> >>  +    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;
> >
> >  I'm never completely sure whether these should be target addresses
> >  or bus addresses or just uint64_t.
> >  With pci on a 32 bit system you can stick a 64 bit address
> >  in a BAR and the result will be that it is never accessed
> >  from the CPU.
> >
>
> Memory regions are not bound to any current or future PCI
> specifications. Any fixed bit width would be wrong here, ie. size should
> rather be target_phys_addr_t.

The point is that different buses have different widths. 
target_phys_addr_t matches just one bus in the system.  It needs to be 
the maximum size of all buses present to be useful.

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

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

* Re: [RFC v2 01/20] Hierarchical memory region API
  2011-06-28 11:53         ` [Qemu-devel] " Avi Kivity
@ 2011-06-28 12:07           ` Jan Kiszka
  -1 siblings, 0 replies; 79+ messages in thread
From: Jan Kiszka @ 2011-06-28 12:07 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm, Michael S. Tsirkin

On 2011-06-28 13:53, Avi Kivity wrote:
> On 06/28/2011 01:28 PM, Jan Kiszka wrote:
>> On 2011-06-28 12:03, Michael S. Tsirkin wrote:
>>>>  +struct MemoryRegion {
>>>>  +    /* All fields are private - violators will be prosecuted */
>>>>  +    const MemoryRegionOps *ops;
>>>>  +    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;
>>>
>>>  I'm never completely sure whether these should be target addresses
>>>  or bus addresses or just uint64_t.
>>>  With pci on a 32 bit system you can stick a 64 bit address
>>>  in a BAR and the result will be that it is never accessed
>>>  from the CPU.
>>>
>>
>> Memory regions are not bound to any current or future PCI
>> specifications. Any fixed bit width would be wrong here, ie. size should
>> rather be target_phys_addr_t.
> 
> The point is that different buses have different widths. 
> target_phys_addr_t matches just one bus in the system.  It needs to be 
> the maximum size of all buses present to be useful.

Then we need a type for that. Or we need to demand that
target_phys_addr_t is defined large enough to support all buses that the
particular arch wants to address. Hardcoding 64 bit or anything is not
appropriate for a generic subsystem.

Jan

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux

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

* Re: [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
@ 2011-06-28 12:07           ` Jan Kiszka
  0 siblings, 0 replies; 79+ messages in thread
From: Jan Kiszka @ 2011-06-28 12:07 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm, Michael S. Tsirkin

On 2011-06-28 13:53, Avi Kivity wrote:
> On 06/28/2011 01:28 PM, Jan Kiszka wrote:
>> On 2011-06-28 12:03, Michael S. Tsirkin wrote:
>>>>  +struct MemoryRegion {
>>>>  +    /* All fields are private - violators will be prosecuted */
>>>>  +    const MemoryRegionOps *ops;
>>>>  +    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;
>>>
>>>  I'm never completely sure whether these should be target addresses
>>>  or bus addresses or just uint64_t.
>>>  With pci on a 32 bit system you can stick a 64 bit address
>>>  in a BAR and the result will be that it is never accessed
>>>  from the CPU.
>>>
>>
>> Memory regions are not bound to any current or future PCI
>> specifications. Any fixed bit width would be wrong here, ie. size should
>> rather be target_phys_addr_t.
> 
> The point is that different buses have different widths. 
> target_phys_addr_t matches just one bus in the system.  It needs to be 
> the maximum size of all buses present to be useful.

Then we need a type for that. Or we need to demand that
target_phys_addr_t is defined large enough to support all buses that the
particular arch wants to address. Hardcoding 64 bit or anything is not
appropriate for a generic subsystem.

Jan

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux

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

* Re: [RFC v2 01/20] Hierarchical memory region API
  2011-06-28 12:07           ` [Qemu-devel] " Jan Kiszka
@ 2011-06-28 12:09             ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-28 12:09 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Michael S. Tsirkin, qemu-devel, kvm

On 06/28/2011 03:07 PM, Jan Kiszka wrote:
> >
> >  The point is that different buses have different widths.
> >  target_phys_addr_t matches just one bus in the system.  It needs to be
> >  the maximum size of all buses present to be useful.
>
> Then we need a type for that. Or we need to demand that
> target_phys_addr_t is defined large enough to support all buses that the
> particular arch wants to address. Hardcoding 64 bit or anything is not
> appropriate for a generic subsystem.

Okay, let's make t_p_a_t max(bus size in system).  Do we have 32-bit 
targets that don't support pci (I guess, pc-isa with cpu < ppro?).  Do 
we want to support a 32-bit variant of pci?  It certainly existed at 
some point.

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


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

* Re: [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
@ 2011-06-28 12:09             ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-28 12:09 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel, kvm, Michael S. Tsirkin

On 06/28/2011 03:07 PM, Jan Kiszka wrote:
> >
> >  The point is that different buses have different widths.
> >  target_phys_addr_t matches just one bus in the system.  It needs to be
> >  the maximum size of all buses present to be useful.
>
> Then we need a type for that. Or we need to demand that
> target_phys_addr_t is defined large enough to support all buses that the
> particular arch wants to address. Hardcoding 64 bit or anything is not
> appropriate for a generic subsystem.

Okay, let's make t_p_a_t max(bus size in system).  Do we have 32-bit 
targets that don't support pci (I guess, pc-isa with cpu < ppro?).  Do 
we want to support a 32-bit variant of pci?  It certainly existed at 
some point.

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

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

* Re: [RFC v2 01/20] Hierarchical memory region API
  2011-06-28 12:09             ` [Qemu-devel] " Avi Kivity
@ 2011-06-28 12:46               ` Jan Kiszka
  -1 siblings, 0 replies; 79+ messages in thread
From: Jan Kiszka @ 2011-06-28 12:46 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Michael S. Tsirkin, qemu-devel, kvm

On 2011-06-28 14:09, Avi Kivity wrote:
> On 06/28/2011 03:07 PM, Jan Kiszka wrote:
>>>
>>>  The point is that different buses have different widths.
>>>  target_phys_addr_t matches just one bus in the system.  It needs to be
>>>  the maximum size of all buses present to be useful.
>>
>> Then we need a type for that. Or we need to demand that
>> target_phys_addr_t is defined large enough to support all buses that the
>> particular arch wants to address. Hardcoding 64 bit or anything is not
>> appropriate for a generic subsystem.
> 
> Okay, let's make t_p_a_t max(bus size in system).  Do we have 32-bit 
> targets that don't support pci (I guess, pc-isa with cpu < ppro?).

At least lm32 and microblaze appear to fall into that category.

> Do we want to support a 32-bit variant of pci?  It certainly existed at 
> some point.

As long as making everything 64 bit in the implementation of the device
models is not guest visible, I don't think that should be a problem.

Jan

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux

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

* Re: [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
@ 2011-06-28 12:46               ` Jan Kiszka
  0 siblings, 0 replies; 79+ messages in thread
From: Jan Kiszka @ 2011-06-28 12:46 UTC (permalink / raw)
  To: Avi Kivity; +Cc: qemu-devel, kvm, Michael S. Tsirkin

On 2011-06-28 14:09, Avi Kivity wrote:
> On 06/28/2011 03:07 PM, Jan Kiszka wrote:
>>>
>>>  The point is that different buses have different widths.
>>>  target_phys_addr_t matches just one bus in the system.  It needs to be
>>>  the maximum size of all buses present to be useful.
>>
>> Then we need a type for that. Or we need to demand that
>> target_phys_addr_t is defined large enough to support all buses that the
>> particular arch wants to address. Hardcoding 64 bit or anything is not
>> appropriate for a generic subsystem.
> 
> Okay, let's make t_p_a_t max(bus size in system).  Do we have 32-bit 
> targets that don't support pci (I guess, pc-isa with cpu < ppro?).

At least lm32 and microblaze appear to fall into that category.

> Do we want to support a 32-bit variant of pci?  It certainly existed at 
> some point.

As long as making everything 64 bit in the implementation of the device
models is not guest visible, I don't think that should be a problem.

Jan

-- 
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux

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

* Re: [RFC v2 01/20] Hierarchical memory region API
  2011-06-28 12:46               ` [Qemu-devel] " Jan Kiszka
@ 2011-06-28 12:53                 ` Avi Kivity
  -1 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-28 12:53 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Michael S. Tsirkin, qemu-devel, kvm

On 06/28/2011 03:46 PM, Jan Kiszka wrote:
>
> >  Do we want to support a 32-bit variant of pci?  It certainly existed at
> >  some point.
>
> As long as making everything 64 bit in the implementation of the device
> models is not guest visible, I don't think that should be a problem.
>

How would it become guest visible?

AFAICT the only implication is a very minor slowdown in the cases where 
it is not actually required.

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


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

* Re: [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
@ 2011-06-28 12:53                 ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-28 12:53 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: qemu-devel, kvm, Michael S. Tsirkin

On 06/28/2011 03:46 PM, Jan Kiszka wrote:
>
> >  Do we want to support a 32-bit variant of pci?  It certainly existed at
> >  some point.
>
> As long as making everything 64 bit in the implementation of the device
> models is not guest visible, I don't think that should be a problem.
>

How would it become guest visible?

AFAICT the only implication is a very minor slowdown in the cases where 
it is not actually required.

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

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

* Re: [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
  2011-06-28 12:09             ` [Qemu-devel] " Avi Kivity
  (?)
  (?)
@ 2011-06-28 13:25             ` Peter Maydell
  2011-06-28 13:36               ` Avi Kivity
  -1 siblings, 1 reply; 79+ messages in thread
From: Peter Maydell @ 2011-06-28 13:25 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Jan Kiszka, qemu-devel, kvm, Michael S. Tsirkin

On 28 June 2011 13:09, Avi Kivity <avi@redhat.com> wrote:
> Okay, let's make t_p_a_t max(bus size in system).

If you want a type for that, can't you give it a sensible (ie
different) name? target_phys_addr_t is pretty clearly "the type
of a physical address for this target" and having it actually
be something else is just going to be confusing.

> Do we have 32-bit targets
> that don't support pci (I guess, pc-isa with cpu < ppro?).  Do we want to
> support a 32-bit variant of pci?  It certainly existed at some point.

As a thought experiment, you could take an existing 32 bit
target and define a new board model that happens to have eg a
new pci controller on it. It doesn't seem right that that
should cause the system's idea of this type width to change,
it's just a new device model and board. So if you have this
type I think it ought to be max(bus size of widest bus qemu
supports).

-- PMM

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

* Re: [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
  2011-06-28 13:25             ` Peter Maydell
@ 2011-06-28 13:36               ` Avi Kivity
  0 siblings, 0 replies; 79+ messages in thread
From: Avi Kivity @ 2011-06-28 13:36 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Jan Kiszka, qemu-devel, kvm, Michael S. Tsirkin


On 06/28/2011 04:25 PM, Peter Maydell wrote:
> On 28 June 2011 13:09, Avi Kivity<avi@redhat.com>  wrote:
> >  Okay, let's make t_p_a_t max(bus size in system).
>
> If you want a type for that, can't you give it a sensible (ie
> different) name? target_phys_addr_t is pretty clearly "the type
> of a physical address for this target" and having it actually
> be something else is just going to be confusing.

"a physical address" is ambiguous.  There are many physical addresses 
flowing around.  Certainly it's most natural to think about the 
processor's physical address bus, but that's not always useful.

Since all *devices* use target_phys_addr_t, I think we should just adopt 
that to avoid major and pointless churn.

> >  Do we have 32-bit targets
> >  that don't support pci (I guess, pc-isa with cpu<  ppro?).  Do we want to
> >  support a 32-bit variant of pci?  It certainly existed at some point.
>
> As a thought experiment, you could take an existing 32 bit
> target and define a new board model that happens to have eg a
> new pci controller on it. It doesn't seem right that that
> should cause the system's idea of this type width to change,
> it's just a new device model and board. So if you have this
> type I think it ought to be max(bus size of widest bus qemu
> supports).

That indicates

   typedef uint64_t target_phys_addr_t;

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


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

* Re: [Qemu-devel] [RFC v2 01/20] Hierarchical memory region API
  2011-06-28 12:09             ` [Qemu-devel] " Avi Kivity
                               ` (2 preceding siblings ...)
  (?)
@ 2011-06-28 16:27             ` Olivier Galibert
  -1 siblings, 0 replies; 79+ messages in thread
From: Olivier Galibert @ 2011-06-28 16:27 UTC (permalink / raw)
  To: qemu-devel

On Tue, Jun 28, 2011 at 03:09:38PM +0300, Avi Kivity wrote:
> On 06/28/2011 03:07 PM, Jan Kiszka wrote:
> > >
> > >  The point is that different buses have different widths.
> > >  target_phys_addr_t matches just one bus in the system.  It needs to be
> > >  the maximum size of all buses present to be useful.
> >
> > Then we need a type for that. Or we need to demand that
> > target_phys_addr_t is defined large enough to support all buses that the
> > particular arch wants to address. Hardcoding 64 bit or anything is not
> > appropriate for a generic subsystem.
> 
> Okay, let's make t_p_a_t max(bus size in system).  Do we have 32-bit 
> targets that don't support pci (I guess, pc-isa with cpu < ppro?).  Do 
> we want to support a 32-bit variant of pci?  It certainly existed at 
> some point.

PCI always had a mechanism for 64-bits addresses even on 32-bits wide
bus, called Dual Address Cycle.  I'm not sure which was rarer: devices
which could handle it, or north bridges which could use it.  Probably
a tie.

But in theory, it was there.

  OG.

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

end of thread, other threads:[~2011-06-28 16:28 UTC | newest]

Thread overview: 79+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-27 13:21 [RFC v2 00/20] Memory API Avi Kivity
2011-06-27 13:21 ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 01/20] Hierarchical memory region API Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-28 10:03   ` Michael S. Tsirkin
2011-06-28 10:03     ` [Qemu-devel] " Michael S. Tsirkin
2011-06-28 10:28     ` Jan Kiszka
2011-06-28 10:28       ` [Qemu-devel] " Jan Kiszka
2011-06-28 11:53       ` Avi Kivity
2011-06-28 11:53         ` [Qemu-devel] " Avi Kivity
2011-06-28 12:07         ` Jan Kiszka
2011-06-28 12:07           ` [Qemu-devel] " Jan Kiszka
2011-06-28 12:09           ` Avi Kivity
2011-06-28 12:09             ` [Qemu-devel] " Avi Kivity
2011-06-28 12:46             ` Jan Kiszka
2011-06-28 12:46               ` [Qemu-devel] " Jan Kiszka
2011-06-28 12:53               ` Avi Kivity
2011-06-28 12:53                 ` [Qemu-devel] " Avi Kivity
2011-06-28 13:25             ` Peter Maydell
2011-06-28 13:36               ` Avi Kivity
2011-06-28 16:27             ` Olivier Galibert
2011-06-28 11:51     ` Avi Kivity
2011-06-28 11:51       ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 02/20] memory: implement dirty tracking Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 03/20] memory: merge adjacent segments of a single memory region Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:56   ` Jan Kiszka
2011-06-27 13:56     ` [Qemu-devel] " Jan Kiszka
2011-06-27 14:11     ` Avi Kivity
2011-06-27 14:11       ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 04/20] Internal interfaces for memory API Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 05/20] exec.c: initialize memory map Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 06/20] pc: grab system_memory Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 07/20] pc: convert pc_memory_init() to memory API Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 08/20] pc: move global memory map out of pc_init1() and into its callers Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 09/20] pci: pass address space to pci bus when created Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 10/20] pci: add MemoryRegion based BAR management API Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 11/20] sysbus: add MemoryRegion based memory " Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:21 ` [RFC v2 12/20] usb-ohci: convert to MemoryRegion Avi Kivity
2011-06-27 13:21   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:22 ` [RFC v2 13/20] pci: add API to get a BAR's mapped address Avi Kivity
2011-06-27 13:22   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:22 ` [RFC v2 14/20] vmsvga: don't remember pci BAR address in callback any more Avi Kivity
2011-06-27 13:22   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:22 ` [RFC v2 15/20] vga: convert vga and its derivatives to the memory API Avi Kivity
2011-06-27 13:22   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:22 ` [RFC v2 16/20] cirrus: simplify mmio BAR access functions Avi Kivity
2011-06-27 13:22   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:22 ` [RFC v2 17/20] cirrus: simplify bitblt " Avi Kivity
2011-06-27 13:22   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:22 ` [RFC v2 18/20] cirrus: simplify vga window mmio " Avi Kivity
2011-06-27 13:22   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:22 ` [RFC v2 19/20] vga: " Avi Kivity
2011-06-27 13:22   ` [Qemu-devel] " Avi Kivity
2011-06-27 13:22 ` [RFC v2 20/20] cirrus: simplify linear framebuffer " Avi Kivity
2011-06-27 13:22   ` [Qemu-devel] " Avi Kivity
2011-06-27 15:13 ` [RFC v2 00/20] Memory API Avi Kivity
2011-06-27 15:13   ` [Qemu-devel] " Avi Kivity
2011-06-27 15:52   ` Michael S. Tsirkin
2011-06-27 15:52     ` [Qemu-devel] " Michael S. Tsirkin
2011-06-27 15:54     ` Avi Kivity
2011-06-27 15:54       ` [Qemu-devel] " Avi Kivity
2011-06-27 15:59       ` Michael S. Tsirkin
2011-06-27 15:59         ` [Qemu-devel] " Michael S. Tsirkin
2011-06-27 16:10         ` Avi Kivity
2011-06-27 16:10           ` [Qemu-devel] " Avi Kivity
2011-06-27 20:28         ` Anthony Liguori
2011-06-27 20:28           ` Anthony Liguori
2011-06-27 15:37 ` Anthony Liguori
2011-06-27 15:44   ` 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.