Re: [PATCH 01/13] Generic DMA memory access interface

2011-02-06 Thread Michael S. Tsirkin
On Fri, Feb 04, 2011 at 01:32:55AM +0200, Eduard - Gabriel Munteanu wrote:
 This introduces replacements for memory access functions like
 cpu_physical_memory_read(). The new interface can handle address
 translation and access checking through an IOMMU.
 
 Signed-off-by: Eduard - Gabriel Munteanu eduard.munte...@linux360.ro
 ---
  Makefile.target |2 +-
  hw/dma_rw.c |  124 +++
  hw/dma_rw.h |  157 
 +++
  3 files changed, 282 insertions(+), 1 deletions(-)
  create mode 100644 hw/dma_rw.c
  create mode 100644 hw/dma_rw.h
 
 diff --git a/Makefile.target b/Makefile.target
 index e15b1c4..e5817ab 100644
 --- a/Makefile.target
 +++ b/Makefile.target
 @@ -218,7 +218,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
  obj-i386-y += vmmouse.o vmport.o hpet.o applesmc.o
  obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
  obj-i386-y += debugcon.o multiboot.o
 -obj-i386-y += pc_piix.o
 +obj-i386-y += pc_piix.o dma_rw.o
  obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
  
  # shared objects
 diff --git a/hw/dma_rw.c b/hw/dma_rw.c
 new file mode 100644
 index 000..ef8e7f8
 --- /dev/null
 +++ b/hw/dma_rw.c
 @@ -0,0 +1,124 @@
 +/*
 + * Generic DMA memory access interface.
 + *
 + * Copyright (c) 2011 Eduard - Gabriel Munteanu
 + *
 + * Permission is hereby granted, free of charge, to any person obtaining a 
 copy
 + * of this software and associated documentation files (the Software), to 
 deal
 + * in the Software without restriction, including without limitation the 
 rights
 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 + * copies of the Software, and to permit persons to whom the Software is
 + * furnished to do so, subject to the following conditions:
 + *
 + * The above copyright notice and this permission notice shall be included in
 + * all copies or substantial portions of the Software.
 + *
 + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 FROM,
 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 + * THE SOFTWARE.
 + */
 +
 +#include dma_rw.h
 +#include range.h
 +
 +static void dma_register_memory_map(DMADevice *dev,
 +dma_addr_t addr,
 +dma_addr_t len,
 +target_phys_addr_t paddr,
 +DMAInvalidateMapFunc *invalidate,
 +void *invalidate_opaque)
 +{
 +DMAMemoryMap *map;
 +
 +map = qemu_malloc(sizeof(DMAMemoryMap));
 +map-addr   = addr;
 +map-len= len;
 +map-paddr  = paddr;
 +map-invalidate = invalidate;
 +map-invalidate_opaque  = invalidate_opaque;
 +
 +QLIST_INSERT_HEAD(dev-mmu-memory_maps, map, list);
 +}
 +
 +static void dma_unregister_memory_map(DMADevice *dev,
 +  target_phys_addr_t paddr,
 +  dma_addr_t len)
 +{
 +DMAMemoryMap *map;
 +
 +QLIST_FOREACH(map, dev-mmu-memory_maps, list) {
 +if (map-paddr == paddr  map-len == len) {
 +QLIST_REMOVE(map, list);
 +free(map);
 +}
 +}
 +}
 +
 +void dma_invalidate_memory_range(DMADevice *dev,
 + dma_addr_t addr,
 + dma_addr_t len)
 +{
 +DMAMemoryMap *map;
 +
 +QLIST_FOREACH(map, dev-mmu-memory_maps, list) {
 +if (ranges_overlap(addr, len, map-addr, map-len)) {
 +map-invalidate(map-invalidate_opaque);
 +QLIST_REMOVE(map, list);
 +free(map);
 +}
 +}
 +}
 +
 +void *dma_memory_map(DMADevice *dev,
 + DMAInvalidateMapFunc *cb,
 + void *opaque,
 + dma_addr_t addr,
 + dma_addr_t *len,
 + int is_write)
 +{
 +int err;
 +target_phys_addr_t paddr, plen;
 +
 +if (!dev || !dev-mmu) {
 +return cpu_physical_memory_map(addr, len, is_write);
 +}
 +
 +plen = *len;
 +err = dev-mmu-translate(dev, addr, paddr, plen, is_write);
 +if (err) {
 +return NULL;
 +}
 +
 +/*
 + * If this is true, the virtual region is contiguous,
 + * but the translated physical region isn't. We just
 + * clamp *len, much like cpu_physical_memory_map() does.
 + */
 +if (plen  *len) {
 +*len = plen;
 +}
 +
 +/* We treat maps as remote TLBs to cope with stuff like AIO. */
 +if (cb) {
 + 

Re: [PATCH 01/13] Generic DMA memory access interface

2011-02-06 Thread Michael S. Tsirkin
On Fri, Feb 04, 2011 at 01:32:55AM +0200, Eduard - Gabriel Munteanu wrote:
 This introduces replacements for memory access functions like
 cpu_physical_memory_read(). The new interface can handle address
 translation and access checking through an IOMMU.
 
 Signed-off-by: Eduard - Gabriel Munteanu eduard.munte...@linux360.ro
 ---
  Makefile.target |2 +-
  hw/dma_rw.c |  124 +++
  hw/dma_rw.h |  157 
 +++
  3 files changed, 282 insertions(+), 1 deletions(-)
  create mode 100644 hw/dma_rw.c
  create mode 100644 hw/dma_rw.h
 
 diff --git a/Makefile.target b/Makefile.target
 index e15b1c4..e5817ab 100644
 --- a/Makefile.target
 +++ b/Makefile.target
 @@ -218,7 +218,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
  obj-i386-y += vmmouse.o vmport.o hpet.o applesmc.o
  obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
  obj-i386-y += debugcon.o multiboot.o
 -obj-i386-y += pc_piix.o
 +obj-i386-y += pc_piix.o dma_rw.o

Does this need to be target specific?

  obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
  
  # shared objects
 diff --git a/hw/dma_rw.c b/hw/dma_rw.c
 new file mode 100644
 index 000..ef8e7f8
 --- /dev/null
 +++ b/hw/dma_rw.c
 @@ -0,0 +1,124 @@
 +/*
 + * Generic DMA memory access interface.
 + *
 + * Copyright (c) 2011 Eduard - Gabriel Munteanu
 + *
 + * Permission is hereby granted, free of charge, to any person obtaining a 
 copy
 + * of this software and associated documentation files (the Software), to 
 deal
 + * in the Software without restriction, including without limitation the 
 rights
 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 + * copies of the Software, and to permit persons to whom the Software is
 + * furnished to do so, subject to the following conditions:
 + *
 + * The above copyright notice and this permission notice shall be included in
 + * all copies or substantial portions of the Software.
 + *
 + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 FROM,
 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 + * THE SOFTWARE.
 + */
 +
 +#include dma_rw.h
 +#include range.h
 +
 +static void dma_register_memory_map(DMADevice *dev,
 +dma_addr_t addr,
 +dma_addr_t len,
 +target_phys_addr_t paddr,
 +DMAInvalidateMapFunc *invalidate,
 +void *invalidate_opaque)
 +{
 +DMAMemoryMap *map;
 +
 +map = qemu_malloc(sizeof(DMAMemoryMap));
 +map-addr   = addr;
 +map-len= len;
 +map-paddr  = paddr;
 +map-invalidate = invalidate;
 +map-invalidate_opaque  = invalidate_opaque;
 +
 +QLIST_INSERT_HEAD(dev-mmu-memory_maps, map, list);
 +}
 +
 +static void dma_unregister_memory_map(DMADevice *dev,
 +  target_phys_addr_t paddr,
 +  dma_addr_t len)
 +{
 +DMAMemoryMap *map;
 +
 +QLIST_FOREACH(map, dev-mmu-memory_maps, list) {
 +if (map-paddr == paddr  map-len == len) {
 +QLIST_REMOVE(map, list);
 +free(map);
 +}
 +}
 +}
 +
 +void dma_invalidate_memory_range(DMADevice *dev,
 + dma_addr_t addr,
 + dma_addr_t len)
 +{
 +DMAMemoryMap *map;
 +
 +QLIST_FOREACH(map, dev-mmu-memory_maps, list) {
 +if (ranges_overlap(addr, len, map-addr, map-len)) {
 +map-invalidate(map-invalidate_opaque);
 +QLIST_REMOVE(map, list);
 +free(map);
 +}
 +}
 +}
 +
 +void *dma_memory_map(DMADevice *dev,
 + DMAInvalidateMapFunc *cb,
 + void *opaque,
 + dma_addr_t addr,
 + dma_addr_t *len,
 + int is_write)
 +{
 +int err;
 +target_phys_addr_t paddr, plen;
 +
 +if (!dev || !dev-mmu) {
 +return cpu_physical_memory_map(addr, len, is_write);
 +}
 +
 +plen = *len;
 +err = dev-mmu-translate(dev, addr, paddr, plen, is_write);
 +if (err) {
 +return NULL;
 +}
 +
 +/*
 + * If this is true, the virtual region is contiguous,
 + * but the translated physical region isn't. We just
 + * clamp *len, much like cpu_physical_memory_map() does.
 + */
 +if (plen  *len) {
 +*len = plen;
 +}
 +
 +/* We treat maps as remote TLBs to cope 

Re: [PATCH 01/13] Generic DMA memory access interface

2011-02-05 Thread Blue Swirl
On Thu, Feb 3, 2011 at 11:32 PM, Eduard - Gabriel Munteanu
eduard.munte...@linux360.ro wrote:
 This introduces replacements for memory access functions like
 cpu_physical_memory_read(). The new interface can handle address
 translation and access checking through an IOMMU.

 Signed-off-by: Eduard - Gabriel Munteanu eduard.munte...@linux360.ro
 ---
  Makefile.target |    2 +-
  hw/dma_rw.c     |  124 +++
  hw/dma_rw.h     |  157 
 +++
  3 files changed, 282 insertions(+), 1 deletions(-)
  create mode 100644 hw/dma_rw.c
  create mode 100644 hw/dma_rw.h

 diff --git a/Makefile.target b/Makefile.target
 index e15b1c4..e5817ab 100644
 --- a/Makefile.target
 +++ b/Makefile.target
 @@ -218,7 +218,7 @@ obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
  obj-i386-y += vmmouse.o vmport.o hpet.o applesmc.o
  obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
  obj-i386-y += debugcon.o multiboot.o
 -obj-i386-y += pc_piix.o
 +obj-i386-y += pc_piix.o dma_rw.o
  obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o

  # shared objects
 diff --git a/hw/dma_rw.c b/hw/dma_rw.c
 new file mode 100644
 index 000..ef8e7f8
 --- /dev/null
 +++ b/hw/dma_rw.c
 @@ -0,0 +1,124 @@
 +/*
 + * Generic DMA memory access interface.
 + *
 + * Copyright (c) 2011 Eduard - Gabriel Munteanu
 + *
 + * Permission is hereby granted, free of charge, to any person obtaining a 
 copy
 + * of this software and associated documentation files (the Software), to 
 deal
 + * in the Software without restriction, including without limitation the 
 rights
 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 + * copies of the Software, and to permit persons to whom the Software is
 + * furnished to do so, subject to the following conditions:
 + *
 + * The above copyright notice and this permission notice shall be included in
 + * all copies or substantial portions of the Software.
 + *
 + * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 FROM,
 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 + * THE SOFTWARE.
 + */
 +
 +#include dma_rw.h
 +#include range.h
 +
 +static void dma_register_memory_map(DMADevice *dev,
 +                                    dma_addr_t addr,
 +                                    dma_addr_t len,
 +                                    target_phys_addr_t paddr,
 +                                    DMAInvalidateMapFunc *invalidate,
 +                                    void *invalidate_opaque)
 +{
 +    DMAMemoryMap *map;
 +
 +    map = qemu_malloc(sizeof(DMAMemoryMap));
 +    map-addr               = addr;
 +    map-len                = len;
 +    map-paddr              = paddr;
 +    map-invalidate         = invalidate;
 +    map-invalidate_opaque  = invalidate_opaque;
 +
 +    QLIST_INSERT_HEAD(dev-mmu-memory_maps, map, list);
 +}
 +
 +static void dma_unregister_memory_map(DMADevice *dev,
 +                                      target_phys_addr_t paddr,
 +                                      dma_addr_t len)
 +{
 +    DMAMemoryMap *map;
 +
 +    QLIST_FOREACH(map, dev-mmu-memory_maps, list) {
 +        if (map-paddr == paddr  map-len == len) {
 +            QLIST_REMOVE(map, list);
 +            free(map);
 +        }
 +    }
 +}
 +
 +void dma_invalidate_memory_range(DMADevice *dev,
 +                                 dma_addr_t addr,
 +                                 dma_addr_t len)
 +{
 +    DMAMemoryMap *map;
 +
 +    QLIST_FOREACH(map, dev-mmu-memory_maps, list) {
 +        if (ranges_overlap(addr, len, map-addr, map-len)) {
 +            map-invalidate(map-invalidate_opaque);
 +            QLIST_REMOVE(map, list);
 +            free(map);
 +        }
 +    }
 +}
 +
 +void *dma_memory_map(DMADevice *dev,
 +                     DMAInvalidateMapFunc *cb,
 +                     void *opaque,
 +                     dma_addr_t addr,
 +                     dma_addr_t *len,
 +                     int is_write)
 +{
 +    int err;
 +    target_phys_addr_t paddr, plen;
 +
 +    if (!dev || !dev-mmu) {
 +        return cpu_physical_memory_map(addr, len, is_write);
 +    }
 +
 +    plen = *len;
 +    err = dev-mmu-translate(dev, addr, paddr, plen, is_write);
 +    if (err) {
 +        return NULL;
 +    }
 +
 +    /*
 +     * If this is true, the virtual region is contiguous,
 +     * but the translated physical region isn't. We just
 +     * clamp *len, much like cpu_physical_memory_map() does.
 +     */
 +    if (plen  *len) {
 +        *len = plen;
 +    }
 +
 +    /* We treat maps as remote TLBs to cope with stuff like AIO. */
 +