[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 11/11] Add a memory barrier to DMA functions
From: |
Blue Swirl |
Subject: |
Re: [Qemu-devel] [PATCH 11/11] Add a memory barrier to DMA functions |
Date: |
Sun, 24 Jun 2012 06:03:26 +0000 |
On Fri, Jun 22, 2012 at 3:29 AM, Benjamin Herrenschmidt
<address@hidden> wrote:
> The emulated devices can run simultaneously with the guest, so
> we need to be careful with ordering of load and stores done by
> them to the guest system memory, which need to be observed in
> the right order by the guest operating system.
>
> This adds a barrier call to the basic DMA read/write ops which
> is currently implemented as a smp_mb(), but could be later
> improved for more fine grained control of barriers.
>
> Additionally, a _relaxed() variant of the accessors is provided
> to easily convert devices who would be performance sensitive
> and negatively impacted by the change.
>
> Signed-off-by: Benjamin Herrenschmidt <address@hidden>
> ---
> dma-helpers.c | 2 ++
> dma.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 52 insertions(+), 2 deletions(-)
>
> diff --git a/dma-helpers.c b/dma-helpers.c
> index 2e09ceb..35cb500 100644
> --- a/dma-helpers.c
> +++ b/dma-helpers.c
> @@ -31,6 +31,8 @@ static void do_dma_memory_set(dma_addr_t addr, uint8_t c,
> dma_addr_t len)
>
> int dma_memory_set(DMAContext *dma, dma_addr_t addr, uint8_t c, dma_addr_t
> len)
> {
> + dma_barrier(dma, DMA_DIRECTION_FROM_DEVICE);
> +
> if (dma_has_iommu(dma)) {
> return iommu_dma_memory_set(dma, addr, c, len);
> }
> diff --git a/dma.h b/dma.h
> index f52a656..54cdd24 100644
> --- a/dma.h
> +++ b/dma.h
> @@ -13,6 +13,7 @@
> #include <stdio.h>
> #include "hw/hw.h"
> #include "block.h"
> +#include "kvm.h"
>
> typedef struct DMAContext DMAContext;
> typedef struct ScatterGatherEntry ScatterGatherEntry;
> @@ -65,6 +66,30 @@ struct DMAContext {
> DMAUnmapFunc *unmap;
> };
>
> +static inline void dma_barrier(DMAContext *dma, DMADirection dir)
> +{
> + /*
> + * This is called before DMA read and write operations
> + * unless the _relaxed form is used and is responsible
> + * for providing some sane ordering of accesses vs
> + * concurrently running VCPUs.
> + *
> + * Users of map(), unmap() or lower level st/ld_*
> + * operations are responsible for providing their own
> + * ordering via barriers.
> + *
> + * This primitive implementation does a simple smp_mb()
> + * before each operation which provides pretty much full
> + * ordering.
> + *
> + * A smarter implementation can be devised if needed to
> + * use lighter barriers based on the direction of the
> + * transfer, the DMA context, etc...
> + */
> + if (kvm_enabled())
> + smp_mb();
Missing braces. Please use checkpatch.pl to avoid issues like this.
> +}
> +
> static inline bool dma_has_iommu(DMAContext *dma)
> {
> return !!dma;
> @@ -88,8 +113,9 @@ static inline bool dma_memory_valid(DMAContext *dma,
>
> int iommu_dma_memory_rw(DMAContext *dma, dma_addr_t addr,
> void *buf, dma_addr_t len, DMADirection dir);
> -static inline int dma_memory_rw(DMAContext *dma, dma_addr_t addr,
> - void *buf, dma_addr_t len, DMADirection dir)
> +static inline int dma_memory_rw_relaxed(DMAContext *dma, dma_addr_t addr,
> + void *buf, dma_addr_t len,
> + DMADirection dir)
> {
> if (!dma_has_iommu(dma)) {
> /* Fast-path for no IOMMU */
> @@ -101,6 +127,28 @@ static inline int dma_memory_rw(DMAContext *dma,
> dma_addr_t addr,
> }
> }
>
> +static inline int dma_memory_read_relaxed(DMAContext *dma, dma_addr_t addr,
> + void *buf, dma_addr_t len)
> +{
> + return dma_memory_rw_relaxed(dma, addr, buf, len,
> DMA_DIRECTION_TO_DEVICE);
> +}
> +
> +static inline int dma_memory_write_relaxed(DMAContext *dma, dma_addr_t addr,
> + const void *buf, dma_addr_t len)
> +{
> + return dma_memory_rw_relaxed(dma, addr, (void *)buf, len,
> + DMA_DIRECTION_FROM_DEVICE);
> +}
> +
> +static inline int dma_memory_rw(DMAContext *dma, dma_addr_t addr,
> + void *buf, dma_addr_t len,
> + DMADirection dir)
> +{
> + dma_barrier(dma, dir);
> +
> + return dma_memory_rw_relaxed(dma, addr, buf, len, dir);
> +}
> +
> static inline int dma_memory_read(DMAContext *dma, dma_addr_t addr,
> void *buf, dma_addr_t len)
> {
> --
> 1.7.9.5
>
>
- [Qemu-devel] [PATCH 00/11] iommu series, Benjamin Herrenschmidt, 2012/06/21
- [Qemu-devel] [PATCH 01/11] Better support for dma_addr_t variables, Benjamin Herrenschmidt, 2012/06/21
- [Qemu-devel] [PATCH 03/11] usb-ohci: Use universal DMA helper functions, Benjamin Herrenschmidt, 2012/06/21
- [Qemu-devel] [PATCH 04/11] iommu: Make sglists and dma_bdrv helpers use new universal DMA helpers, Benjamin Herrenschmidt, 2012/06/21
- [Qemu-devel] [PATCH 02/11] iommu: Add universal DMA helper functions, Benjamin Herrenschmidt, 2012/06/21
- [Qemu-devel] [PATCH 06/11] usb: Convert usb_packet_{map, unmap} to universal DMA helpers, Benjamin Herrenschmidt, 2012/06/21
- [Qemu-devel] [PATCH 05/11] ide/ahci: Use universal DMA helper functions, Benjamin Herrenschmidt, 2012/06/21
- [Qemu-devel] [PATCH 11/11] Add a memory barrier to DMA functions, Benjamin Herrenschmidt, 2012/06/21
- Re: [Qemu-devel] [PATCH 11/11] Add a memory barrier to DMA functions,
Blue Swirl <=
- [Qemu-devel] [PATCH 07/11] iommu: Introduce IOMMU emulation infrastructure, Benjamin Herrenschmidt, 2012/06/21
- [Qemu-devel] [PATCH 10/11] pseries: Implement IOMMU and DMA for PAPR PCI devices, Benjamin Herrenschmidt, 2012/06/21
- [Qemu-devel] [PATCH 09/11] iommu: Allow PCI to use IOMMU infrastructure, Benjamin Herrenschmidt, 2012/06/21
- [Qemu-devel] [PATCH 08/11] pseries: Convert sPAPR TCEs to use generic IOMMU infrastructure, Benjamin Herrenschmidt, 2012/06/21