On 10/27/07, Blue Swirl <[EMAIL PROTECTED]> wrote: > I changed Slirp output to use vectored IO to avoid the slowdown from > memcpy (see the patch for the work in progress, gives a small > performance improvement). But then I got the idea that using AIO would > be nice at the outgoing end of the network IO processing. In fact, > vectored AIO model could even be used for the generic DMA! The benefit > is that no buffering or copying should be needed.
I made a sketch of the API, please have a look at the patch. > Each stage would translate the IO list and callback as needed and only > the final stage would perform the IO or memcpy. This would be used in > each stage of the chain memory<->IOMMU<->device<->SLIRP<->host network > device. Of course some kind of host support for vectored AIO for these > devices is required. On target side, devices that can do > scatter/gather DMA would benefit most. Inside Qemu the vectors would use target physical addresses (struct qemu_iovec), but at some point the addresses would change to host pointers suitable for real AIO.
Index: qemu/vl.h =================================================================== --- qemu.orig/vl.h 2007-10-27 14:58:09.000000000 +0000 +++ qemu/vl.h 2007-10-27 16:51:40.000000000 +0000 @@ -746,6 +746,85 @@ #include "hw/irq.h" +/* Generic DMA API */ + +typedef void DMADriverCompletionFunc(void *opaque, int ret); + +struct qemu_iovec { + target_phys_addr_t iov_base; + size_t iov_len; +}; + +typedef struct qemu_bus qemu_bus; + +typedef struct DMADriverAIOCB { + void *opaque; + int type; + int nent; + struct aiocb **aiocb; + DMADriverCompletionFunc *cb; + struct DMADriverAIOCB *next; +} DMADriverAIOCB; + +typedef void DMARWHandler(void *opaque, + const struct qemu_iovec *dst_vector, + int dst_count, + const struct qemu_iovec *src_vector, + int src_count); + +qemu_bus *bus_init(unsigned int bus_bits, DMARWHandler north_handler, + void *north_handler_opaque, DMARWHandler south_handler, + void *south_handler_opaque); + +/* Direction CPU->bridge->device/memory */ +void bus_rw_south(qemu_bus *bus, + const struct qemu_iovec *dst_vector, + int dst_count, + const struct qemu_iovec *src_vector, + int src_count, + int is_write); + +static inline void bus_read_south(qemu_bus *bus, + const struct qemu_iovec *dst_vector, + int dst_count, + const struct qemu_iovec *src_vector, + int src_count) +{ + bus_rw_south(bus, dst_vector, dst_count, src_vector, src_count, 0); +} +static inline void bus_write_south(qemu_bus *bus, + const struct qemu_iovec *dst_vector, + int dst_count, + const struct qemu_iovec *src_vector, + int src_count) +{ + bus_rw_south(bus, dst_vector, dst_count, src_vector, src_count, 1); +} +/* From device towards CPU/memory (DMA) */ +void bus_rw_north(qemu_bus *bus, + const struct qemu_iovec *dst_vector, + int dst_count, + const struct qemu_iovec *src_vector, + int src_count, + int is_write); + +static inline void bus_read_north(qemu_bus *bus, + const struct qemu_iovec *dst_vector, + int dst_count, + const struct qemu_iovec *src_vector, + int src_count) +{ + bus_rw_north(bus, dst_vector, dst_count, src_vector, src_count, 0); +} +static inline void bus_write_north(qemu_bus *bus, + const struct qemu_iovec *dst_vector, + int dst_count, + const struct qemu_iovec *src_vector, + int src_count) +{ + bus_rw_north(bus, dst_vector, dst_count, src_vector, src_count, 1); +} + /* ISA bus */ extern target_phys_addr_t isa_mem_base;