RISC-V privilege specification doesn't define an IOMMU or any method modify
PMA attributes or PTE entries to allow non-coherent mappings yet. In
the beginning, this approach was adopted assuming that most of the RISC-V
platforms would support full cache-coherent IO. Here is excerpt from the
priv spec section 3.6.5
"In RISC-V platforms, the use of hardware-incoherent regions is discouraged
due to software complexity, performance, and energy impacts."
While some of the RISC-V platforms adhere to the above suggestion, not all
platforms can afford to build to fully cache-coherent I/O devices. To
address DMA for non-coherent I/O devices, we need to mark a region of memory
as non-cacheable. Some of the platforms rely on a fixed region of uncached
memory that is remapped to the system memory while some other modify
the PTE entries to achieve that.
The patch3 solves the issue for the fist use case by using a global
pool of memory that is reserved for DMA. The device access the reserved area
of the region while corresponding CPU address will be from uncached region
As the uncached region is remapped to the beginning of the system ram, both
CPU and device get the same view.
To facilitate streaming DMA APIs, patch 1 introduces a set of generic
cache operations. Any platform can use the generic ops to provide platform
specific cache management operations. Once the standard RISC-V CMO extension
is available, it will also use these generic ops.
To address the second use case, Page Based Memory Attribute (PBMT) extension
is proposed. Once the extension is in good shape, we can leverage that
using CONFIG_DIRECT_REMAP. Currently, it is selected via a compile time config
option. We will probably need another arch specific hooks to know if the
platform supports direct remap at runtime. For RISC-V, it will check the
presence of PBMT extension while other arch function will simply return true
if DIRECT_REMAP is enabled. This is required as arious different config
(DIRECT_REMAP, GLOBAL_POOL) will be enabled in the defconfig so that a
unified kernel image can boot on all RISC-V platforms.
This patch series depends on Christoph's global pool support series[1].
Tested on Qemu, HiFive unleashed and beagleV. This series is also available
at [2].
This series also solves the non-coherent DMA support on beagleV but requires
additional beagleV specific patches[3] which will be upstreamed soon.
[1] https://lists.linuxfoundation.org/pipermail/iommu/2021-July/057266.html
[2] https://github.com/atishp04/linux/tree/riscv_nc_global_pool
[3] https://github.com/atishp04/linux/tree/wip_beaglev_dma_nc_global
Atish Patra (5):
RISC-V: Implement arch_sync_dma* functions
of: Move of_dma_get_range to of_address.h
dma-mapping: Enable global non-coherent pool support for RISC-V
dma-direct: Allocate dma pages directly if global pool allocation
fails
RISC-V: Support a new config option for non-coherent DMA
arch/riscv/Kconfig | 8 +++
arch/riscv/include/asm/dma-noncoherent.h | 19 +++++++
arch/riscv/mm/Makefile | 1 +
arch/riscv/mm/dma-noncoherent.c | 66 ++++++++++++++++++++++++
drivers/of/of_private.h | 10 ----
include/linux/of_address.h | 12 +++++
kernel/dma/coherent.c | 49 +++++++++++++++---
kernel/dma/direct.c | 7 ++-
8 files changed, 152 insertions(+), 20 deletions(-)
create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
create mode 100644 arch/riscv/mm/dma-noncoherent.c
--
2.31.1
To facilitate streaming DMA APIs, this patch introduces a set of generic
cache operations related dma sync. Any platform can use the generic ops
to provide platform specific cache management operations. Once the
standard RISC-V CMO extension is available, it can be built on top of it.
Signed-off-by: Atish Patra <[email protected]>
---
arch/riscv/include/asm/dma-noncoherent.h | 19 +++++++
arch/riscv/mm/Makefile | 1 +
arch/riscv/mm/dma-noncoherent.c | 66 ++++++++++++++++++++++++
3 files changed, 86 insertions(+)
create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
create mode 100644 arch/riscv/mm/dma-noncoherent.c
diff --git a/arch/riscv/include/asm/dma-noncoherent.h b/arch/riscv/include/asm/dma-noncoherent.h
new file mode 100644
index 000000000000..5bdb03c9c427
--- /dev/null
+++ b/arch/riscv/include/asm/dma-noncoherent.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ */
+
+#ifndef __ASM_RISCV_DMA_NON_COHERENT_H
+#define __ASM_RISCV_DMA_NON_COHERENT_H
+
+#ifdef CONFIG_RISCV_DMA_NONCOHERENT
+struct riscv_dma_cache_sync {
+ void (*cache_invalidate)(phys_addr_t paddr, size_t size);
+ void (*cache_clean)(phys_addr_t paddr, size_t size);
+ void (*cache_flush)(phys_addr_t paddr, size_t size);
+};
+
+void riscv_dma_cache_sync_set(struct riscv_dma_cache_sync *ops);
+#endif
+
+#endif
diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
index 7ebaef10ea1b..959bef49098b 100644
--- a/arch/riscv/mm/Makefile
+++ b/arch/riscv/mm/Makefile
@@ -27,3 +27,4 @@ KASAN_SANITIZE_init.o := n
endif
obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
+obj-$(CONFIG_RISCV_DMA_NONCOHERENT) += dma-noncoherent.o
diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
new file mode 100644
index 000000000000..2f6e9627c4aa
--- /dev/null
+++ b/arch/riscv/mm/dma-noncoherent.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * RISC-V specific functions to support DMA for non-coherent devices
+ *
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ */
+
+#include <linux/dma-direct.h>
+#include <linux/dma-map-ops.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/libfdt.h>
+#include <linux/mm.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <asm/dma-noncoherent.h>
+
+static struct riscv_dma_cache_sync *dma_cache_sync;
+unsigned long riscv_dma_uc_offset;
+
+static void __dma_sync(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
+{
+ if ((dir == DMA_FROM_DEVICE) && (dma_cache_sync->cache_invalidate))
+ dma_cache_sync->cache_invalidate(paddr, size);
+ else if ((dir == DMA_TO_DEVICE) && (dma_cache_sync->cache_clean))
+ dma_cache_sync->cache_clean(paddr, size);
+ else if ((dir == DMA_BIDIRECTIONAL) && dma_cache_sync->cache_flush)
+ dma_cache_sync->cache_flush(paddr, size);
+}
+
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
+{
+ if (!dma_cache_sync)
+ return;
+
+ __dma_sync(paddr, size, dir);
+}
+
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
+{
+ if (!dma_cache_sync)
+ return;
+
+ __dma_sync(paddr, size, dir);
+}
+
+void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
+ const struct iommu_ops *iommu, bool coherent)
+{
+ /* If a specific device is dma-coherent, set it here */
+ dev->dma_coherent = coherent;
+}
+
+void arch_dma_prep_coherent(struct page *page, size_t size)
+{
+ void *flush_addr = page_address(page);
+
+ memset(flush_addr, 0, size);
+ if (dma_cache_sync && dma_cache_sync->cache_flush)
+ dma_cache_sync->cache_flush(__pa(flush_addr), size);
+}
+
+void riscv_dma_cache_sync_set(struct riscv_dma_cache_sync *ops)
+{
+ dma_cache_sync = ops;
+}
--
2.31.1
DMA_GLOBAL_POOL config may be enabled for platforms where global pool is
not supported because a generic defconfig is expected to boot on different
platforms. Specifically, some RISC-V platforms may use global pool for
non-coherent devices while some other platforms are completely coherent.
However, it is expected that single kernel image must boot on all the
platforms.
Continue the dma direct allocation if a allocation from global pool failed.
This indicates that the platform is relying on some other method (direct
remap) or just have coherent devices.
Signed-off-by: Atish Patra <[email protected]>
---
kernel/dma/direct.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index d1d0258ed6d0..984ea776f099 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -161,8 +161,11 @@ void *dma_direct_alloc(struct device *dev, size_t size,
return arch_dma_alloc(dev, size, dma_handle, gfp, attrs);
if (IS_ENABLED(CONFIG_DMA_GLOBAL_POOL) &&
- !dev_is_dma_coherent(dev))
- return dma_alloc_from_global_coherent(dev, size, dma_handle);
+ !dev_is_dma_coherent(dev)) {
+ ret = dma_alloc_from_global_coherent(dev, size, dma_handle);
+ if (ret)
+ return ret;
+ }
/*
* Remapping or decrypting memory may block. If either is required and
--
2.31.1
Currently, linux,dma-default is used to reserve a global non-coherent pool
to allocate memory for dma operations. This can be useful for RISC-V as
well as the ISA specification doesn't specify a method to modify PMA
attributes or page table entries to define non-cacheable area yet.
A non-cacheable memory window is an alternate options for vendors to
support non-coherent devices. "dma-ranges" must be used in conjunction with
"linux,dma-default" property to define one or more mappings between device
and cpu accesible memory regions.
This allows RISC-V to use global pool for non-coherent platforms that
relies on a uncached memory region that is outside of the system ram.
Signed-off-by: Atish Patra <[email protected]>
---
kernel/dma/coherent.c | 49 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 41 insertions(+), 8 deletions(-)
diff --git a/kernel/dma/coherent.c b/kernel/dma/coherent.c
index 97677df5408b..d0b33b1a76f0 100644
--- a/kernel/dma/coherent.c
+++ b/kernel/dma/coherent.c
@@ -9,6 +9,8 @@
#include <linux/module.h>
#include <linux/dma-direct.h>
#include <linux/dma-map-ops.h>
+#include <linux/of_address.h>
+#include <linux/libfdt.h>
struct dma_coherent_mem {
void *virt_base;
@@ -302,19 +304,27 @@ int dma_mmap_from_global_coherent(struct vm_area_struct *vma, void *vaddr,
vaddr, size, ret);
}
-int dma_init_global_coherent(phys_addr_t phys_addr, size_t size)
+static int __dma_init_global_coherent(phys_addr_t phys_addr, dma_addr_t device_addr, size_t size)
{
struct dma_coherent_mem *mem;
- mem = dma_init_coherent_memory(phys_addr, phys_addr, size, true);
+ if (phys_addr == device_addr)
+ mem = dma_init_coherent_memory(phys_addr, device_addr, size, true);
+ else
+ mem = dma_init_coherent_memory(phys_addr, device_addr, size, false);
+
if (IS_ERR(mem))
return PTR_ERR(mem);
dma_coherent_default_memory = mem;
pr_info("DMA: default coherent area is set\n");
return 0;
}
-#endif /* CONFIG_DMA_GLOBAL_POOL */
+int dma_init_global_coherent(phys_addr_t phys_addr, size_t size)
+{
+ return __dma_init_global_coherent(phys_addr, phys_addr, size);
+}
+#endif /* CONFIG_DMA_GLOBAL_POOL */
/*
* Support for reserved memory regions defined in device tree
*/
@@ -329,8 +339,8 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
if (!rmem->priv) {
struct dma_coherent_mem *mem;
- mem = dma_init_coherent_memory(rmem->base, rmem->base,
- rmem->size, true);
+ mem = dma_init_coherent_memory(rmem->base, rmem->base, rmem->size, true);
+
if (IS_ERR(mem))
return PTR_ERR(mem);
rmem->priv = mem;
@@ -358,7 +368,7 @@ static int __init rmem_dma_setup(struct reserved_mem *rmem)
if (of_get_flat_dt_prop(node, "reusable", NULL))
return -EINVAL;
-#ifdef CONFIG_ARM
+#if defined(CONFIG_ARM) || defined(CONFIG_RISCV)
if (!of_get_flat_dt_prop(node, "no-map", NULL)) {
pr_err("Reserved memory: regions without no-map are not yet supported\n");
return -EINVAL;
@@ -382,10 +392,33 @@ static int __init rmem_dma_setup(struct reserved_mem *rmem)
#ifdef CONFIG_DMA_GLOBAL_POOL
static int __init dma_init_reserved_memory(void)
{
+ struct device_node *np;
+ const struct bus_dma_region *map = NULL;
+ int ret;
+ int64_t uc_offset = 0;
+
if (!dma_reserved_default_memory)
return -ENOMEM;
- return dma_init_global_coherent(dma_reserved_default_memory->base,
- dma_reserved_default_memory->size);
+
+ /* dma-ranges is only valid for global pool i.e. dma-default is set */
+ np = of_find_node_with_property(NULL, "linux,dma-default");
+ if (!np)
+ goto global_init;
+ of_node_put(np);
+
+ ret = of_dma_get_range(np, &map);
+ if (ret < 0)
+ goto global_init;
+
+ /* Sanity check for the non-coherent global pool from uncached region */
+ if (map->dma_start == dma_reserved_default_memory->base &&
+ map->size == dma_reserved_default_memory->size)
+ uc_offset = map->offset;
+
+global_init:
+ return __dma_init_global_coherent(dma_reserved_default_memory->base + uc_offset,
+ dma_reserved_default_memory->base,
+ dma_reserved_default_memory->size);
}
core_initcall(dma_init_reserved_memory);
#endif /* CONFIG_DMA_GLOBAL_POOL */
--
2.31.1
In future, there will be more RISC-V platforms with non-coherent DMA.
Instead of selecting all the required config options in every soc, create
a new config that selects all the required configs related non-coherent
DMA.
Signed-off-by: Atish Patra <[email protected]>
---
arch/riscv/Kconfig | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 8fcceb8eda07..931b283c8ec9 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -209,6 +209,14 @@ config PGTABLE_LEVELS
config LOCKDEP_SUPPORT
def_bool y
+config RISCV_DMA_NONCOHERENT
+ bool
+ select ARCH_HAS_DMA_PREP_COHERENT
+ select ARCH_HAS_SYNC_DMA_FOR_DEVICE
+ select ARCH_HAS_SYNC_DMA_FOR_CPU
+ select ARCH_HAS_SETUP_DMA_OPS
+ select DMA_GLOBAL_POOL
+
source "arch/riscv/Kconfig.socs"
source "arch/riscv/Kconfig.erratas"
--
2.31.1
Currently, of_dma_get_range is kept in of_private.h as it is used by only
OF support code.
Move it to of_address.h so that it can be used by the code outside OF
support code.
Signed-off-by: Atish Patra <[email protected]>
---
drivers/of/of_private.h | 10 ----------
include/linux/of_address.h | 12 ++++++++++++
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 631489f7f8c0..f65f801e3aae 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -160,16 +160,6 @@ extern int of_bus_n_addr_cells(struct device_node *np);
extern int of_bus_n_size_cells(struct device_node *np);
struct bus_dma_region;
-#if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_HAS_DMA)
-int of_dma_get_range(struct device_node *np,
- const struct bus_dma_region **map);
-#else
-static inline int of_dma_get_range(struct device_node *np,
- const struct bus_dma_region **map)
-{
- return -ENODEV;
-}
-#endif
void fdt_init_reserved_mem(void);
void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 45598dbec269..0e20f85850fc 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -154,4 +154,16 @@ static inline const __be32 *of_get_pci_address(struct device_node *dev, int bar_
return __of_get_address(dev, -1, bar_no, size, flags);
}
+struct bus_dma_region;
+#if defined(CONFIG_OF_ADDRESS) && defined(CONFIG_HAS_DMA)
+int of_dma_get_range(struct device_node *np,
+ const struct bus_dma_region **map);
+#else
+static inline int of_dma_get_range(struct device_node *np,
+ const struct bus_dma_region **map)
+{
+ return -ENODEV;
+}
+#endif
+
#endif /* __OF_ADDRESS_H */
--
2.31.1
On Fri, Jul 23, 2021 at 3:40 PM Atish Patra <[email protected]> wrote:
>
> Currently, linux,dma-default is used to reserve a global non-coherent pool
> to allocate memory for dma operations. This can be useful for RISC-V as
> well as the ISA specification doesn't specify a method to modify PMA
> attributes or page table entries to define non-cacheable area yet.
> A non-cacheable memory window is an alternate options for vendors to
> support non-coherent devices. "dma-ranges" must be used in conjunction with
> "linux,dma-default" property to define one or more mappings between device
> and cpu accesible memory regions.
'dma-ranges' applies to buses. And, well, maybe devices when the bus
is not well defined. It is not a reserved-memory property.
Rob
> +#ifdef CONFIG_RISCV_DMA_NONCOHERENT
> +struct riscv_dma_cache_sync {
> + void (*cache_invalidate)(phys_addr_t paddr, size_t size);
> + void (*cache_clean)(phys_addr_t paddr, size_t size);
> + void (*cache_flush)(phys_addr_t paddr, size_t size);
> +};
> +
> +void riscv_dma_cache_sync_set(struct riscv_dma_cache_sync *ops);
> +#endif
As told a bunch of times before: doing indirect calls here is a
performance nightmare. Use something that actually does perform
horribly like alternatives. Or even delay implementing that until
we need it and do a plain direct call for now.
static void __dma_sync(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> +{
> + if ((dir == DMA_FROM_DEVICE) && (dma_cache_sync->cache_invalidate))
> + dma_cache_sync->cache_invalidate(paddr, size);
> + else if ((dir == DMA_TO_DEVICE) && (dma_cache_sync->cache_clean))
> + dma_cache_sync->cache_clean(paddr, size);
> + else if ((dir == DMA_BIDIRECTIONAL) && dma_cache_sync->cache_flush)
> + dma_cache_sync->cache_flush(paddr, size);
> +}
The seletion of flush types is completely broken. Take a look at the
comment in arch/arc/mm/dma.c above arch_sync_dma_for_device for a good
explanation.
> +void arch_dma_prep_coherent(struct page *page, size_t size)
> +{
> + void *flush_addr = page_address(page);
> +
> + memset(flush_addr, 0, size);
arch_dma_prep_coherent is not supposed to modify the content of
the data.
On Fri, Jul 23, 2021 at 02:40:30PM -0700, Atish Patra wrote:
> DMA_GLOBAL_POOL config may be enabled for platforms where global pool is
> not supported because a generic defconfig is expected to boot on different
> platforms. Specifically, some RISC-V platforms may use global pool for
> non-coherent devices while some other platforms are completely coherent.
> However, it is expected that single kernel image must boot on all the
> platforms.
>
> Continue the dma direct allocation if a allocation from global pool failed.
> This indicates that the platform is relying on some other method (direct
> remap) or just have coherent devices.
>
> Signed-off-by: Atish Patra <[email protected]>
> ---
> kernel/dma/direct.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
> index d1d0258ed6d0..984ea776f099 100644
> --- a/kernel/dma/direct.c
> +++ b/kernel/dma/direct.c
> @@ -161,8 +161,11 @@ void *dma_direct_alloc(struct device *dev, size_t size,
> return arch_dma_alloc(dev, size, dma_handle, gfp, attrs);
>
> if (IS_ENABLED(CONFIG_DMA_GLOBAL_POOL) &&
> - !dev_is_dma_coherent(dev))
> - return dma_alloc_from_global_coherent(dev, size, dma_handle);
> + !dev_is_dma_coherent(dev)) {
> + ret = dma_alloc_from_global_coherent(dev, size, dma_handle);
> + if (ret)
> + return ret;
This will now silently return normal non-cache coherent memory when
the global pool allocation fails, and thus is completely broken.
On Fri, Jul 23, 2021 at 02:40:29PM -0700, Atish Patra wrote:
> Currently, linux,dma-default is used to reserve a global non-coherent pool
> to allocate memory for dma operations. This can be useful for RISC-V as
> well as the ISA specification doesn't specify a method to modify PMA
> attributes or page table entries to define non-cacheable area yet.
> A non-cacheable memory window is an alternate options for vendors to
> support non-coherent devices.
Please explain why you do not want to use the simply non-cachable
window support using arch_dma_set_uncached as used by mips, niops2 and
xtensa.
> +static int __dma_init_global_coherent(phys_addr_t phys_addr, dma_addr_t device_addr, size_t size)
> {
> struct dma_coherent_mem *mem;
>
> - mem = dma_init_coherent_memory(phys_addr, phys_addr, size, true);
> + if (phys_addr == device_addr)
> + mem = dma_init_coherent_memory(phys_addr, device_addr, size, true);
> + else
> + mem = dma_init_coherent_memory(phys_addr, device_addr, size, false);
Nak. The phys_addr != device_addr support is goign away. This needs
to be filled in using dma-ranges property hanging of the struct device.
On Sun, Jul 25, 2021 at 11:57 PM Christoph Hellwig <[email protected]> wrote:
>
> > +#ifdef CONFIG_RISCV_DMA_NONCOHERENT
> > +struct riscv_dma_cache_sync {
> > + void (*cache_invalidate)(phys_addr_t paddr, size_t size);
> > + void (*cache_clean)(phys_addr_t paddr, size_t size);
> > + void (*cache_flush)(phys_addr_t paddr, size_t size);
> > +};
> > +
> > +void riscv_dma_cache_sync_set(struct riscv_dma_cache_sync *ops);
> > +#endif
>
> As told a bunch of times before: doing indirect calls here is a
> performance nightmare. Use something that actually does perform
> horribly like alternatives. Or even delay implementing that until
> we need it and do a plain direct call for now.
>
I was initially planning to replace this with alternatives in the
future versions. But there is no point in doing it
until we have CMO spec finalized. We also don't have any other
platform using these apart from sifive l2
cache controllers for now.
I will change these to direct for now.
> static void __dma_sync(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> > +{
> > + if ((dir == DMA_FROM_DEVICE) && (dma_cache_sync->cache_invalidate))
> > + dma_cache_sync->cache_invalidate(paddr, size);
> > + else if ((dir == DMA_TO_DEVICE) && (dma_cache_sync->cache_clean))
> > + dma_cache_sync->cache_clean(paddr, size);
> > + else if ((dir == DMA_BIDIRECTIONAL) && dma_cache_sync->cache_flush)
> > + dma_cache_sync->cache_flush(paddr, size);
> > +}
>
> The seletion of flush types is completely broken. Take a look at the
> comment in arch/arc/mm/dma.c above arch_sync_dma_for_device for a good
> explanation.
>
Thanks. I will fix it.
> > +void arch_dma_prep_coherent(struct page *page, size_t size)
> > +{
> > + void *flush_addr = page_address(page);
> > +
> > + memset(flush_addr, 0, size);
>
> arch_dma_prep_coherent is not supposed to modify the content of
> the data.
Sorry. This was a leftover from some experimental code. It shouldn't
have been included.
> _______________________________________________
> iommu mailing list
> [email protected]
> https://lists.linuxfoundation.org/mailman/listinfo/iommu
--
Regards,
Atish
On Mon, Jul 26, 2021 at 12:00 AM Christoph Hellwig <[email protected]> wrote:
>
> On Fri, Jul 23, 2021 at 02:40:29PM -0700, Atish Patra wrote:
> > Currently, linux,dma-default is used to reserve a global non-coherent pool
> > to allocate memory for dma operations. This can be useful for RISC-V as
> > well as the ISA specification doesn't specify a method to modify PMA
> > attributes or page table entries to define non-cacheable area yet.
> > A non-cacheable memory window is an alternate options for vendors to
> > support non-coherent devices.
>
> Please explain why you do not want to use the simply non-cachable
> window support using arch_dma_set_uncached as used by mips, niops2 and
> xtensa.
>
arch_dma_set_uncached works as well in this case. However, mips,
niops2 & xtensa uses a
fixed (via config) value for the offset. Similar approach can't be
used here because the platform specific
offset value has to be determined at runtime so that a single kernel
image can boot on all platforms.
That's why we need the following additional changes for RISC-V to make it work.
1. a new DT property so that arch specific code is aware of the
non-cacheable window offset.
- either under /chosen node or a completely separate node with
multiple non-cacheable window support
We also need to define how it is going to referenced from
individual device if a per-device non-cacheable
window support is required in future. As of now, the beagleV memory
region lies in 0x10_0000_00000 - x17_FFFF_FFFF
which is mapped to start of DRAM 0x80000000. All of the
non-coherent devices can do 32bit DMA only.
2. Use the dma-ranges and modify the arch_dma_set_uncached function to
pass the struct device as an argument.
Either way, we will need arch specific hook ups and additional changes
while the global non-coherent pool
provides a more elegant solution without any additional arch specific code.
If arch_dma_set_uncached is still preferred way to solve this problem,
I can revise the patch with either approach 1 or approach 2
> > +static int __dma_init_global_coherent(phys_addr_t phys_addr, dma_addr_t device_addr, size_t size)
>
>
>
>
> > {
> > struct dma_coherent_mem *mem;
> >
> > - mem = dma_init_coherent_memory(phys_addr, phys_addr, size, true);
> > + if (phys_addr == device_addr)
> > + mem = dma_init_coherent_memory(phys_addr, device_addr, size, true);
> > + else
> > + mem = dma_init_coherent_memory(phys_addr, device_addr, size, false);
>
> Nak. The phys_addr != device_addr support is goign away. This needs
ok.
> to be filled in using dma-ranges property hanging of the struct device.
struct device is only accessible in rmem_dma_device_init. I couldn't
find a proper way to access it during
dma_reserved_default_memory setup under global pool.
Does that mean we should use a per-device memory pool instead of a
global non-coherent pool ?
> _______________________________________________
> iommu mailing list
> [email protected]
> https://lists.linuxfoundation.org/mailman/listinfo/iommu
--
Regards,
Atish
On Mon, Jul 26, 2021 at 03:47:54PM -0700, Atish Patra wrote:
> arch_dma_set_uncached works as well in this case. However, mips,
> niops2 & xtensa uses a
> fixed (via config) value for the offset. Similar approach can't be
> used here because the platform specific
> offset value has to be determined at runtime so that a single kernel
> image can boot on all platforms.
Nothing in the interface requires a fixed offset. And using the offset
has one enormous advantage in that there is no need to declare a
statically sized pool - allocations are fully dynamic. And any kind of
fixed pool tends to cause huge problems.
> 1. a new DT property so that arch specific code is aware of the
> non-cacheable window offset.
Yes.
> individual device if a per-device non-cacheable
> window support is required in future. As of now, the beagleV memory
If you require a per-device noncachable area you can use the per-device
coherent pools. But why would you want that?
> region lies in 0x10_0000_00000 - x17_FFFF_FFFF
> which is mapped to start of DRAM 0x80000000. All of the
> non-coherent devices can do 32bit DMA only.
Adjust ZONE_DMA32 so that it takes the uncached offset into account.
> > > - mem = dma_init_coherent_memory(phys_addr, phys_addr, size, true);
> > > + if (phys_addr == device_addr)
> > > + mem = dma_init_coherent_memory(phys_addr, device_addr, size, true);
> > > + else
> > > + mem = dma_init_coherent_memory(phys_addr, device_addr, size, false);
> >
> > Nak. The phys_addr != device_addr support is goign away. This needs
>
> ok.
>
> > to be filled in using dma-ranges property hanging of the struct device.
>
> struct device is only accessible in rmem_dma_device_init. I couldn't
> find a proper way to access it during
> dma_reserved_default_memory setup under global pool.
>
> Does that mean we should use a per-device memory pool instead of a
> global non-coherent pool ?
Indeed, that would be a problem in this case. But if we can just
use the uncached offset directly I think everything will be much
simpler.
On Fri, 23 Jul 2021 14:40:26 PDT (-0700), Atish Patra wrote:
> RISC-V privilege specification doesn't define an IOMMU or any method modify
> PMA attributes or PTE entries to allow non-coherent mappings yet. In
> the beginning, this approach was adopted assuming that most of the RISC-V
> platforms would support full cache-coherent IO. Here is excerpt from the
> priv spec section 3.6.5
>
> "In RISC-V platforms, the use of hardware-incoherent regions is discouraged
> due to software complexity, performance, and energy impacts."
>
> While some of the RISC-V platforms adhere to the above suggestion, not all
> platforms can afford to build to fully cache-coherent I/O devices. To
> address DMA for non-coherent I/O devices, we need to mark a region of memory
> as non-cacheable. Some of the platforms rely on a fixed region of uncached
> memory that is remapped to the system memory while some other modify
> the PTE entries to achieve that.
>
> The patch3 solves the issue for the fist use case by using a global
> pool of memory that is reserved for DMA. The device access the reserved area
> of the region while corresponding CPU address will be from uncached region
> As the uncached region is remapped to the beginning of the system ram, both
> CPU and device get the same view.
>
> To facilitate streaming DMA APIs, patch 1 introduces a set of generic
> cache operations. Any platform can use the generic ops to provide platform
> specific cache management operations. Once the standard RISC-V CMO extension
> is available, it will also use these generic ops.
>
> To address the second use case, Page Based Memory Attribute (PBMT) extension
> is proposed. Once the extension is in good shape, we can leverage that
> using CONFIG_DIRECT_REMAP. Currently, it is selected via a compile time config
> option. We will probably need another arch specific hooks to know if the
> platform supports direct remap at runtime. For RISC-V, it will check the
> presence of PBMT extension while other arch function will simply return true
IIUC this is another extension that's not yet frozen or implemented in
hardware? Is this one compatible with what's in the c906, or is it
doing things its own way?
> if DIRECT_REMAP is enabled. This is required as arious different config
> (DIRECT_REMAP, GLOBAL_POOL) will be enabled in the defconfig so that a
> unified kernel image can boot on all RISC-V platforms.
>
> This patch series depends on Christoph's global pool support series[1].
> Tested on Qemu, HiFive unleashed and beagleV. This series is also available
> at [2].
> This series also solves the non-coherent DMA support on beagleV but requires
> additional beagleV specific patches[3] which will be upstreamed soon.
>
>
> [1] https://lists.linuxfoundation.org/pipermail/iommu/2021-July/057266.html
> [2] https://github.com/atishp04/linux/tree/riscv_nc_global_pool
> [3] https://github.com/atishp04/linux/tree/wip_beaglev_dma_nc_global
>
> Atish Patra (5):
> RISC-V: Implement arch_sync_dma* functions
> of: Move of_dma_get_range to of_address.h
> dma-mapping: Enable global non-coherent pool support for RISC-V
> dma-direct: Allocate dma pages directly if global pool allocation
> fails
> RISC-V: Support a new config option for non-coherent DMA
>
> arch/riscv/Kconfig | 8 +++
> arch/riscv/include/asm/dma-noncoherent.h | 19 +++++++
> arch/riscv/mm/Makefile | 1 +
> arch/riscv/mm/dma-noncoherent.c | 66 ++++++++++++++++++++++++
> drivers/of/of_private.h | 10 ----
> include/linux/of_address.h | 12 +++++
> kernel/dma/coherent.c | 49 +++++++++++++++---
> kernel/dma/direct.c | 7 ++-
> 8 files changed, 152 insertions(+), 20 deletions(-)
> create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
> create mode 100644 arch/riscv/mm/dma-noncoherent.c
Can you guys please make up your minds about how this is going to be
supported at the ISA level? I get a different answer every day here:
sometimes it's that these systems are not compliant, sometimes that
Linux is the compliance suite, sometimes that we're doing an ISA
extension, and sometimes that we're doing the SBI stuff.
I don't really care all that much about what the decision is, but it's
impossible to move forward without some semblance of a plan.
On Wed, Jul 28, 2021 at 9:30 PM Palmer Dabbelt <[email protected]> wrote:
>
> On Fri, 23 Jul 2021 14:40:26 PDT (-0700), Atish Patra wrote:
> > RISC-V privilege specification doesn't define an IOMMU or any method modify
> > PMA attributes or PTE entries to allow non-coherent mappings yet. In
> > the beginning, this approach was adopted assuming that most of the RISC-V
> > platforms would support full cache-coherent IO. Here is excerpt from the
> > priv spec section 3.6.5
> >
> > "In RISC-V platforms, the use of hardware-incoherent regions is discouraged
> > due to software complexity, performance, and energy impacts."
> >
> > While some of the RISC-V platforms adhere to the above suggestion, not all
> > platforms can afford to build to fully cache-coherent I/O devices. To
> > address DMA for non-coherent I/O devices, we need to mark a region of memory
> > as non-cacheable. Some of the platforms rely on a fixed region of uncached
> > memory that is remapped to the system memory while some other modify
> > the PTE entries to achieve that.
> >
> > The patch3 solves the issue for the fist use case by using a global
> > pool of memory that is reserved for DMA. The device access the reserved area
> > of the region while corresponding CPU address will be from uncached region
> > As the uncached region is remapped to the beginning of the system ram, both
> > CPU and device get the same view.
> >
> > To facilitate streaming DMA APIs, patch 1 introduces a set of generic
> > cache operations. Any platform can use the generic ops to provide platform
> > specific cache management operations. Once the standard RISC-V CMO extension
> > is available, it will also use these generic ops.
> >
> > To address the second use case, Page Based Memory Attribute (PBMT) extension
> > is proposed. Once the extension is in good shape, we can leverage that
> > using CONFIG_DIRECT_REMAP. Currently, it is selected via a compile time config
> > option. We will probably need another arch specific hooks to know if the
> > platform supports direct remap at runtime. For RISC-V, it will check the
> > presence of PBMT extension while other arch function will simply return true
>
> IIUC this is another extension that's not yet frozen or implemented in
> hardware? Is this one compatible with what's in the c906, or is it
> doing things its own way?
Hi Palmer,
This series doesn't implement the PBMT extension which is still in discussion.
It simply reuse the existing non-coherent dma mapping support in
upstream kernel and enable
it for RISC-V. The current version uses a non-coherent global pool. I
will update it to use arch_set_uncached
as per Christoph's suggestion. It solves the non-coherent DMA problem
for beagleV and not c906.
I briefly mentioned the PBMT extension just to provide an idea how the
RISC-V Linux kernel
can support both unached window and PBMT extension. PBMT extension is
planned to be frozen
by the end of this year and none of the hardware has implemented it.
The implementation in c906 is a non-standard one and will not be
supported by the default PBMT
extension implementation.
>
> > if DIRECT_REMAP is enabled. This is required as arious different config
> > (DIRECT_REMAP, GLOBAL_POOL) will be enabled in the defconfig so that a
> > unified kernel image can boot on all RISC-V platforms.
> >
> > This patch series depends on Christoph's global pool support series[1].
> > Tested on Qemu, HiFive unleashed and beagleV. This series is also available
> > at [2].
> > This series also solves the non-coherent DMA support on beagleV but requires
> > additional beagleV specific patches[3] which will be upstreamed soon.
> >
> >
> > [1] https://lists.linuxfoundation.org/pipermail/iommu/2021-July/057266.html
> > [2] https://github.com/atishp04/linux/tree/riscv_nc_global_pool
> > [3] https://github.com/atishp04/linux/tree/wip_beaglev_dma_nc_global
> >
> > Atish Patra (5):
> > RISC-V: Implement arch_sync_dma* functions
> > of: Move of_dma_get_range to of_address.h
> > dma-mapping: Enable global non-coherent pool support for RISC-V
> > dma-direct: Allocate dma pages directly if global pool allocation
> > fails
> > RISC-V: Support a new config option for non-coherent DMA
> >
> > arch/riscv/Kconfig | 8 +++
> > arch/riscv/include/asm/dma-noncoherent.h | 19 +++++++
> > arch/riscv/mm/Makefile | 1 +
> > arch/riscv/mm/dma-noncoherent.c | 66 ++++++++++++++++++++++++
> > drivers/of/of_private.h | 10 ----
> > include/linux/of_address.h | 12 +++++
> > kernel/dma/coherent.c | 49 +++++++++++++++---
> > kernel/dma/direct.c | 7 ++-
> > 8 files changed, 152 insertions(+), 20 deletions(-)
> > create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
> > create mode 100644 arch/riscv/mm/dma-noncoherent.c
>
> Can you guys please make up your minds about how this is going to be
> supported at the ISA level? I get a different answer every day here:
> sometimes it's that these systems are not compliant, sometimes that
> Linux is the compliance suite, sometimes that we're doing an ISA
> extension, and sometimes that we're doing the SBI stuff.
>
I am not sure whom you have talked to. I would be happy to set up a
meeting so that everybody is on
the same page if you are getting different answers every time.
> I don't really care all that much about what the decision is, but it's
> impossible to move forward without some semblance of a plan.
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv
--
Regards,
Atish
On Tue, Jul 27, 2021 at 1:52 AM Christoph Hellwig <[email protected]> wrote:
>
> On Mon, Jul 26, 2021 at 03:47:54PM -0700, Atish Patra wrote:
> > arch_dma_set_uncached works as well in this case. However, mips,
> > niops2 & xtensa uses a
> > fixed (via config) value for the offset. Similar approach can't be
> > used here because the platform specific
> > offset value has to be determined at runtime so that a single kernel
> > image can boot on all platforms.
>
> Nothing in the interface requires a fixed offset. And using the offset
> has one enormous advantage in that there is no need to declare a
> statically sized pool - allocations are fully dynamic. And any kind of
> fixed pool tends to cause huge problems.
>
> > 1. a new DT property so that arch specific code is aware of the
> > non-cacheable window offset.
>
> Yes.
>
> > individual device if a per-device non-cacheable
> > window support is required in future. As of now, the beagleV memory
>
> If you require a per-device noncachable area you can use the per-device
> coherent pools. But why would you want that?
>
> > region lies in 0x10_0000_00000 - x17_FFFF_FFFF
> > which is mapped to start of DRAM 0x80000000. All of the
> > non-coherent devices can do 32bit DMA only.
>
> Adjust ZONE_DMA32 so that it takes the uncached offset into account.
>
> > > > - mem = dma_init_coherent_memory(phys_addr, phys_addr, size, true);
> > > > + if (phys_addr == device_addr)
> > > > + mem = dma_init_coherent_memory(phys_addr, device_addr, size, true);
> > > > + else
> > > > + mem = dma_init_coherent_memory(phys_addr, device_addr, size, false);
> > >
> > > Nak. The phys_addr != device_addr support is goign away. This needs
> >
> > ok.
> >
> > > to be filled in using dma-ranges property hanging of the struct device.
> >
> > struct device is only accessible in rmem_dma_device_init. I couldn't
> > find a proper way to access it during
> > dma_reserved_default_memory setup under global pool.
> >
> > Does that mean we should use a per-device memory pool instead of a
> > global non-coherent pool ?
>
> Indeed, that would be a problem in this case. But if we can just
> use the uncached offset directly I think everything will be much
> simpler.
Yes. I was planning to change this to use an uncached offset.
However, the planned mass production for beaglev starlight sbc is
cancelled now [1].
As there is no other board that requires an uncached offset, I don't
think there is no usecase
for adding uncached offset support for RISC-V right now. I will
revisit(hopefully we don't have to)
this in case any platform implements uncached window support in future.
[1] https://www.cnx-software.com/2021/07/31/beaglev-starlight-sbc-wont-be-mass-manufactured-redesigned-beaglev-risc-v-sbc-expected-in-q1-2022/
--
Regards,
Atish
1
On Thu, Jul 29, 2021 at 2:19 PM Atish Patra <[email protected]> wrote:
>
> On Wed, Jul 28, 2021 at 9:30 PM Palmer Dabbelt <[email protected]> wrote:
> >
> > On Fri, 23 Jul 2021 14:40:26 PDT (-0700), Atish Patra wrote:
> > > RISC-V privilege specification doesn't define an IOMMU or any method modify
> > > PMA attributes or PTE entries to allow non-coherent mappings yet. In
> > > the beginning, this approach was adopted assuming that most of the RISC-V
> > > platforms would support full cache-coherent IO. Here is excerpt from the
> > > priv spec section 3.6.5
> > >
> > > "In RISC-V platforms, the use of hardware-incoherent regions is discouraged
> > > due to software complexity, performance, and energy impacts."
> > >
> > > While some of the RISC-V platforms adhere to the above suggestion, not all
> > > platforms can afford to build to fully cache-coherent I/O devices. To
> > > address DMA for non-coherent I/O devices, we need to mark a region of memory
> > > as non-cacheable. Some of the platforms rely on a fixed region of uncached
> > > memory that is remapped to the system memory while some other modify
> > > the PTE entries to achieve that.
> > >
> > > The patch3 solves the issue for the fist use case by using a global
> > > pool of memory that is reserved for DMA. The device access the reserved area
> > > of the region while corresponding CPU address will be from uncached region
> > > As the uncached region is remapped to the beginning of the system ram, both
> > > CPU and device get the same view.
> > >
> > > To facilitate streaming DMA APIs, patch 1 introduces a set of generic
> > > cache operations. Any platform can use the generic ops to provide platform
> > > specific cache management operations. Once the standard RISC-V CMO extension
> > > is available, it will also use these generic ops.
> > >
> > > To address the second use case, Page Based Memory Attribute (PBMT) extension
> > > is proposed. Once the extension is in good shape, we can leverage that
> > > using CONFIG_DIRECT_REMAP. Currently, it is selected via a compile time config
> > > option. We will probably need another arch specific hooks to know if the
> > > platform supports direct remap at runtime. For RISC-V, it will check the
> > > presence of PBMT extension while other arch function will simply return true
> >
> > IIUC this is another extension that's not yet frozen or implemented in
> > hardware? Is this one compatible with what's in the c906, or is it
> > doing things its own way?
>
> Hi Palmer,
> This series doesn't implement the PBMT extension which is still in discussion.
> It simply reuse the existing non-coherent dma mapping support in
> upstream kernel and enable
> it for RISC-V. The current version uses a non-coherent global pool. I
> will update it to use arch_set_uncached
> as per Christoph's suggestion. It solves the non-coherent DMA problem
> for beagleV and not c906.
>
> I briefly mentioned the PBMT extension just to provide an idea how the
> RISC-V Linux kernel
> can support both unached window and PBMT extension. PBMT extension is
> planned to be frozen
> by the end of this year and none of the hardware has implemented it.
>
> The implementation in c906 is a non-standard one and will not be
> supported by the default PBMT
> extension implementation.
The default PBMT & c908 PBMT are similar, only BIT definitions are
different. I propose to support default PBMT first and give the back
door to modify the PBMT definition during boot.
The "protection_map[] = (__P000, __P001 ..__S000, __S001)" in
mm/mmap.c has been modified by arch/mips, arm, sparc, x86, so I think
it's proper solution direction.
The reset problem is how to passing custom PBMT at the very early boot
stage. Now I'm trying to use the DTS parsing instead of boot param hdr
which Anup objected to.
ref: https://lore.kernel.org/linux-riscv/[email protected]/
Any comments are welcome.
>
>
> >
> > > if DIRECT_REMAP is enabled. This is required as arious different config
> > > (DIRECT_REMAP, GLOBAL_POOL) will be enabled in the defconfig so that a
> > > unified kernel image can boot on all RISC-V platforms.
> > >
> > > This patch series depends on Christoph's global pool support series[1].
> > > Tested on Qemu, HiFive unleashed and beagleV. This series is also available
> > > at [2].
> > > This series also solves the non-coherent DMA support on beagleV but requires
> > > additional beagleV specific patches[3] which will be upstreamed soon.
> > >
> > >
> > > [1] https://lists.linuxfoundation.org/pipermail/iommu/2021-July/057266.html
> > > [2] https://github.com/atishp04/linux/tree/riscv_nc_global_pool
> > > [3] https://github.com/atishp04/linux/tree/wip_beaglev_dma_nc_global
> > >
> > > Atish Patra (5):
> > > RISC-V: Implement arch_sync_dma* functions
> > > of: Move of_dma_get_range to of_address.h
> > > dma-mapping: Enable global non-coherent pool support for RISC-V
> > > dma-direct: Allocate dma pages directly if global pool allocation
> > > fails
> > > RISC-V: Support a new config option for non-coherent DMA
> > >
> > > arch/riscv/Kconfig | 8 +++
> > > arch/riscv/include/asm/dma-noncoherent.h | 19 +++++++
> > > arch/riscv/mm/Makefile | 1 +
> > > arch/riscv/mm/dma-noncoherent.c | 66 ++++++++++++++++++++++++
> > > drivers/of/of_private.h | 10 ----
> > > include/linux/of_address.h | 12 +++++
> > > kernel/dma/coherent.c | 49 +++++++++++++++---
> > > kernel/dma/direct.c | 7 ++-
> > > 8 files changed, 152 insertions(+), 20 deletions(-)
> > > create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
> > > create mode 100644 arch/riscv/mm/dma-noncoherent.c
> >
> > Can you guys please make up your minds about how this is going to be
> > supported at the ISA level? I get a different answer every day here:
> > sometimes it's that these systems are not compliant, sometimes that
> > Linux is the compliance suite, sometimes that we're doing an ISA
> > extension, and sometimes that we're doing the SBI stuff.
> >
>
> I am not sure whom you have talked to. I would be happy to set up a
> meeting so that everybody is on
> the same page if you are getting different answers every time.
>
> > I don't really care all that much about what the decision is, but it's
> > impossible to move forward without some semblance of a plan.
> >
> > _______________________________________________
> > linux-riscv mailing list
> > [email protected]
> > http://lists.infradead.org/mailman/listinfo/linux-riscv
>
>
>
> --
> Regards,
> Atish
> _______________________________________________
> iommu mailing list
> [email protected]
> https://lists.linuxfoundation.org/mailman/listinfo/iommu
--
Best Regards
Guo Ren
ML: https://lore.kernel.org/linux-csky/
On Sat, Jul 24, 2021 at 5:40 AM Atish Patra <[email protected]> wrote:
>
> To facilitate streaming DMA APIs, this patch introduces a set of generic
> cache operations related dma sync. Any platform can use the generic ops
> to provide platform specific cache management operations. Once the
> standard RISC-V CMO extension is available, it can be built on top of it.
>
> Signed-off-by: Atish Patra <[email protected]>
> ---
> arch/riscv/include/asm/dma-noncoherent.h | 19 +++++++
> arch/riscv/mm/Makefile | 1 +
> arch/riscv/mm/dma-noncoherent.c | 66 ++++++++++++++++++++++++
> 3 files changed, 86 insertions(+)
> create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
> create mode 100644 arch/riscv/mm/dma-noncoherent.c
>
> diff --git a/arch/riscv/include/asm/dma-noncoherent.h b/arch/riscv/include/asm/dma-noncoherent.h
> new file mode 100644
> index 000000000000..5bdb03c9c427
> --- /dev/null
> +++ b/arch/riscv/include/asm/dma-noncoherent.h
> @@ -0,0 +1,19 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> + */
> +
> +#ifndef __ASM_RISCV_DMA_NON_COHERENT_H
> +#define __ASM_RISCV_DMA_NON_COHERENT_H
> +
> +#ifdef CONFIG_RISCV_DMA_NONCOHERENT
> +struct riscv_dma_cache_sync {
> + void (*cache_invalidate)(phys_addr_t paddr, size_t size);
> + void (*cache_clean)(phys_addr_t paddr, size_t size);
> + void (*cache_flush)(phys_addr_t paddr, size_t size);
> +};
I like the style like this than my previous patch which using
sbi_call. The c906 has custom instructions that could be called in
S-mode directly.
Hope the patch could be soon merged, after correct the
DMA_FROM/TO_DEVICE/BIDIRECTIONAL and alternatives ops_set.
> +
> +void riscv_dma_cache_sync_set(struct riscv_dma_cache_sync *ops);
> +#endif
> +
> +#endif
> diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
> index 7ebaef10ea1b..959bef49098b 100644
> --- a/arch/riscv/mm/Makefile
> +++ b/arch/riscv/mm/Makefile
> @@ -27,3 +27,4 @@ KASAN_SANITIZE_init.o := n
> endif
>
> obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
> +obj-$(CONFIG_RISCV_DMA_NONCOHERENT) += dma-noncoherent.o
> diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
> new file mode 100644
> index 000000000000..2f6e9627c4aa
> --- /dev/null
> +++ b/arch/riscv/mm/dma-noncoherent.c
> @@ -0,0 +1,66 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * RISC-V specific functions to support DMA for non-coherent devices
> + *
> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> + */
> +
> +#include <linux/dma-direct.h>
> +#include <linux/dma-map-ops.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/libfdt.h>
> +#include <linux/mm.h>
> +#include <linux/of.h>
> +#include <linux/of_fdt.h>
> +#include <asm/dma-noncoherent.h>
> +
> +static struct riscv_dma_cache_sync *dma_cache_sync;
> +unsigned long riscv_dma_uc_offset;
> +
> +static void __dma_sync(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> +{
> + if ((dir == DMA_FROM_DEVICE) && (dma_cache_sync->cache_invalidate))
> + dma_cache_sync->cache_invalidate(paddr, size);
> + else if ((dir == DMA_TO_DEVICE) && (dma_cache_sync->cache_clean))
> + dma_cache_sync->cache_clean(paddr, size);
> + else if ((dir == DMA_BIDIRECTIONAL) && dma_cache_sync->cache_flush)
> + dma_cache_sync->cache_flush(paddr, size);
> +}
> +
> +void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> +{
> + if (!dma_cache_sync)
> + return;
> +
> + __dma_sync(paddr, size, dir);
> +}
> +
> +void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> +{
> + if (!dma_cache_sync)
> + return;
> +
> + __dma_sync(paddr, size, dir);
> +}
> +
> +void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
> + const struct iommu_ops *iommu, bool coherent)
> +{
> + /* If a specific device is dma-coherent, set it here */
> + dev->dma_coherent = coherent;
> +}
> +
> +void arch_dma_prep_coherent(struct page *page, size_t size)
> +{
> + void *flush_addr = page_address(page);
> +
> + memset(flush_addr, 0, size);
> + if (dma_cache_sync && dma_cache_sync->cache_flush)
> + dma_cache_sync->cache_flush(__pa(flush_addr), size);
> +}
> +
> +void riscv_dma_cache_sync_set(struct riscv_dma_cache_sync *ops)
> +{
> + dma_cache_sync = ops;
> +}
> --
> 2.31.1
>
> _______________________________________________
> iommu mailing list
> [email protected]
> https://lists.linuxfoundation.org/mailman/listinfo/iommu
--
Best Regards
Guo Ren
ML: https://lore.kernel.org/linux-csky/
On Mon, Aug 16, 2021 at 6:48 PM Guo Ren <[email protected]> wrote:
>
> On Sat, Jul 24, 2021 at 5:40 AM Atish Patra <[email protected]> wrote:
> >
> > To facilitate streaming DMA APIs, this patch introduces a set of generic
> > cache operations related dma sync. Any platform can use the generic ops
> > to provide platform specific cache management operations. Once the
> > standard RISC-V CMO extension is available, it can be built on top of it.
> >
> > Signed-off-by: Atish Patra <[email protected]>
> > ---
> > arch/riscv/include/asm/dma-noncoherent.h | 19 +++++++
> > arch/riscv/mm/Makefile | 1 +
> > arch/riscv/mm/dma-noncoherent.c | 66 ++++++++++++++++++++++++
> > 3 files changed, 86 insertions(+)
> > create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
> > create mode 100644 arch/riscv/mm/dma-noncoherent.c
> >
> > diff --git a/arch/riscv/include/asm/dma-noncoherent.h b/arch/riscv/include/asm/dma-noncoherent.h
> > new file mode 100644
> > index 000000000000..5bdb03c9c427
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/dma-noncoherent.h
> > @@ -0,0 +1,19 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > + */
> > +
> > +#ifndef __ASM_RISCV_DMA_NON_COHERENT_H
> > +#define __ASM_RISCV_DMA_NON_COHERENT_H
> > +
> > +#ifdef CONFIG_RISCV_DMA_NONCOHERENT
> > +struct riscv_dma_cache_sync {
> > + void (*cache_invalidate)(phys_addr_t paddr, size_t size);
> > + void (*cache_clean)(phys_addr_t paddr, size_t size);
> > + void (*cache_flush)(phys_addr_t paddr, size_t size);
> > +};
> I like the style like this than my previous patch which using
> sbi_call. The c906 has custom instructions that could be called in
> S-mode directly.
>
How are you going to include the custom instructions in the upstream kernel ?
> Hope the patch could be soon merged, after correct the
> DMA_FROM/TO_DEVICE/BIDIRECTIONAL and alternatives ops_set.
>
> > +
> > +void riscv_dma_cache_sync_set(struct riscv_dma_cache_sync *ops);
> > +#endif
> > +
> > +#endif
> > diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
> > index 7ebaef10ea1b..959bef49098b 100644
> > --- a/arch/riscv/mm/Makefile
> > +++ b/arch/riscv/mm/Makefile
> > @@ -27,3 +27,4 @@ KASAN_SANITIZE_init.o := n
> > endif
> >
> > obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
> > +obj-$(CONFIG_RISCV_DMA_NONCOHERENT) += dma-noncoherent.o
> > diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
> > new file mode 100644
> > index 000000000000..2f6e9627c4aa
> > --- /dev/null
> > +++ b/arch/riscv/mm/dma-noncoherent.c
> > @@ -0,0 +1,66 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * RISC-V specific functions to support DMA for non-coherent devices
> > + *
> > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > + */
> > +
> > +#include <linux/dma-direct.h>
> > +#include <linux/dma-map-ops.h>
> > +#include <linux/init.h>
> > +#include <linux/io.h>
> > +#include <linux/libfdt.h>
> > +#include <linux/mm.h>
> > +#include <linux/of.h>
> > +#include <linux/of_fdt.h>
> > +#include <asm/dma-noncoherent.h>
> > +
> > +static struct riscv_dma_cache_sync *dma_cache_sync;
> > +unsigned long riscv_dma_uc_offset;
> > +
> > +static void __dma_sync(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> > +{
> > + if ((dir == DMA_FROM_DEVICE) && (dma_cache_sync->cache_invalidate))
> > + dma_cache_sync->cache_invalidate(paddr, size);
> > + else if ((dir == DMA_TO_DEVICE) && (dma_cache_sync->cache_clean))
> > + dma_cache_sync->cache_clean(paddr, size);
> > + else if ((dir == DMA_BIDIRECTIONAL) && dma_cache_sync->cache_flush)
> > + dma_cache_sync->cache_flush(paddr, size);
> > +}
> > +
> > +void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> > +{
> > + if (!dma_cache_sync)
> > + return;
> > +
> > + __dma_sync(paddr, size, dir);
> > +}
> > +
> > +void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> > +{
> > + if (!dma_cache_sync)
> > + return;
> > +
> > + __dma_sync(paddr, size, dir);
> > +}
> > +
> > +void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
> > + const struct iommu_ops *iommu, bool coherent)
> > +{
> > + /* If a specific device is dma-coherent, set it here */
> > + dev->dma_coherent = coherent;
> > +}
> > +
> > +void arch_dma_prep_coherent(struct page *page, size_t size)
> > +{
> > + void *flush_addr = page_address(page);
> > +
> > + memset(flush_addr, 0, size);
> > + if (dma_cache_sync && dma_cache_sync->cache_flush)
> > + dma_cache_sync->cache_flush(__pa(flush_addr), size);
> > +}
> > +
> > +void riscv_dma_cache_sync_set(struct riscv_dma_cache_sync *ops)
> > +{
> > + dma_cache_sync = ops;
> > +}
> > --
> > 2.31.1
> >
> > _______________________________________________
> > iommu mailing list
> > [email protected]
> > https://lists.linuxfoundation.org/mailman/listinfo/iommu
>
>
>
> --
> Best Regards
> Guo Ren
>
> ML: https://lore.kernel.org/linux-csky/
> _______________________________________________
> iommu mailing list
> [email protected]
> https://lists.linuxfoundation.org/mailman/listinfo/iommu
--
Regards,
Atish
On Mon, Aug 16, 2021 at 6:37 PM Guo Ren <[email protected]> wrote:
>
> 1
>
> On Thu, Jul 29, 2021 at 2:19 PM Atish Patra <[email protected]> wrote:
> >
> > On Wed, Jul 28, 2021 at 9:30 PM Palmer Dabbelt <[email protected]> wrote:
> > >
> > > On Fri, 23 Jul 2021 14:40:26 PDT (-0700), Atish Patra wrote:
> > > > RISC-V privilege specification doesn't define an IOMMU or any method modify
> > > > PMA attributes or PTE entries to allow non-coherent mappings yet. In
> > > > the beginning, this approach was adopted assuming that most of the RISC-V
> > > > platforms would support full cache-coherent IO. Here is excerpt from the
> > > > priv spec section 3.6.5
> > > >
> > > > "In RISC-V platforms, the use of hardware-incoherent regions is discouraged
> > > > due to software complexity, performance, and energy impacts."
> > > >
> > > > While some of the RISC-V platforms adhere to the above suggestion, not all
> > > > platforms can afford to build to fully cache-coherent I/O devices. To
> > > > address DMA for non-coherent I/O devices, we need to mark a region of memory
> > > > as non-cacheable. Some of the platforms rely on a fixed region of uncached
> > > > memory that is remapped to the system memory while some other modify
> > > > the PTE entries to achieve that.
> > > >
> > > > The patch3 solves the issue for the fist use case by using a global
> > > > pool of memory that is reserved for DMA. The device access the reserved area
> > > > of the region while corresponding CPU address will be from uncached region
> > > > As the uncached region is remapped to the beginning of the system ram, both
> > > > CPU and device get the same view.
> > > >
> > > > To facilitate streaming DMA APIs, patch 1 introduces a set of generic
> > > > cache operations. Any platform can use the generic ops to provide platform
> > > > specific cache management operations. Once the standard RISC-V CMO extension
> > > > is available, it will also use these generic ops.
> > > >
> > > > To address the second use case, Page Based Memory Attribute (PBMT) extension
> > > > is proposed. Once the extension is in good shape, we can leverage that
> > > > using CONFIG_DIRECT_REMAP. Currently, it is selected via a compile time config
> > > > option. We will probably need another arch specific hooks to know if the
> > > > platform supports direct remap at runtime. For RISC-V, it will check the
> > > > presence of PBMT extension while other arch function will simply return true
> > >
> > > IIUC this is another extension that's not yet frozen or implemented in
> > > hardware? Is this one compatible with what's in the c906, or is it
> > > doing things its own way?
> >
> > Hi Palmer,
> > This series doesn't implement the PBMT extension which is still in discussion.
> > It simply reuse the existing non-coherent dma mapping support in
> > upstream kernel and enable
> > it for RISC-V. The current version uses a non-coherent global pool. I
> > will update it to use arch_set_uncached
> > as per Christoph's suggestion. It solves the non-coherent DMA problem
> > for beagleV and not c906.
> >
> > I briefly mentioned the PBMT extension just to provide an idea how the
> > RISC-V Linux kernel
> > can support both unached window and PBMT extension. PBMT extension is
> > planned to be frozen
> > by the end of this year and none of the hardware has implemented it.
> >
> > The implementation in c906 is a non-standard one and will not be
> > supported by the default PBMT
> > extension implementation.
> The default PBMT & c908 PBMT are similar, only BIT definitions are
> different. I propose to support default PBMT first and give the back
> door to modify the PBMT definition during boot.
> The "protection_map[] = (__P000, __P001 ..__S000, __S001)" in
> mm/mmap.c has been modified by arch/mips, arm, sparc, x86, so I think
> it's proper solution direction.
>
> The reset problem is how to passing custom PBMT at the very early boot
> stage. Now I'm trying to use the DTS parsing instead of boot param hdr
> which Anup objected to.
>
IIRC, c906 has a compatible mode that has the compliant PTE bit modifications.
Can you use that mode in the Allwinner D1 board to boot Linux ? I am
not sure if you have any fallback method for non-coherent DMA
if custom DMA_COHERENT bits are not enabled through enhanced mode ?
> ref: https://lore.kernel.org/linux-riscv/[email protected]/
>
> Any comments are welcome.
>
> >
> >
> > >
> > > > if DIRECT_REMAP is enabled. This is required as arious different config
> > > > (DIRECT_REMAP, GLOBAL_POOL) will be enabled in the defconfig so that a
> > > > unified kernel image can boot on all RISC-V platforms.
> > > >
> > > > This patch series depends on Christoph's global pool support series[1].
> > > > Tested on Qemu, HiFive unleashed and beagleV. This series is also available
> > > > at [2].
> > > > This series also solves the non-coherent DMA support on beagleV but requires
> > > > additional beagleV specific patches[3] which will be upstreamed soon.
> > > >
> > > >
> > > > [1] https://lists.linuxfoundation.org/pipermail/iommu/2021-July/057266.html
> > > > [2] https://github.com/atishp04/linux/tree/riscv_nc_global_pool
> > > > [3] https://github.com/atishp04/linux/tree/wip_beaglev_dma_nc_global
> > > >
> > > > Atish Patra (5):
> > > > RISC-V: Implement arch_sync_dma* functions
> > > > of: Move of_dma_get_range to of_address.h
> > > > dma-mapping: Enable global non-coherent pool support for RISC-V
> > > > dma-direct: Allocate dma pages directly if global pool allocation
> > > > fails
> > > > RISC-V: Support a new config option for non-coherent DMA
> > > >
> > > > arch/riscv/Kconfig | 8 +++
> > > > arch/riscv/include/asm/dma-noncoherent.h | 19 +++++++
> > > > arch/riscv/mm/Makefile | 1 +
> > > > arch/riscv/mm/dma-noncoherent.c | 66 ++++++++++++++++++++++++
> > > > drivers/of/of_private.h | 10 ----
> > > > include/linux/of_address.h | 12 +++++
> > > > kernel/dma/coherent.c | 49 +++++++++++++++---
> > > > kernel/dma/direct.c | 7 ++-
> > > > 8 files changed, 152 insertions(+), 20 deletions(-)
> > > > create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
> > > > create mode 100644 arch/riscv/mm/dma-noncoherent.c
> > >
> > > Can you guys please make up your minds about how this is going to be
> > > supported at the ISA level? I get a different answer every day here:
> > > sometimes it's that these systems are not compliant, sometimes that
> > > Linux is the compliance suite, sometimes that we're doing an ISA
> > > extension, and sometimes that we're doing the SBI stuff.
> > >
> >
> > I am not sure whom you have talked to. I would be happy to set up a
> > meeting so that everybody is on
> > the same page if you are getting different answers every time.
> >
> > > I don't really care all that much about what the decision is, but it's
> > > impossible to move forward without some semblance of a plan.
> > >
> > > _______________________________________________
> > > linux-riscv mailing list
> > > [email protected]
> > > http://lists.infradead.org/mailman/listinfo/linux-riscv
> >
> >
> >
> > --
> > Regards,
> > Atish
> > _______________________________________________
> > iommu mailing list
> > [email protected]
> > https://lists.linuxfoundation.org/mailman/listinfo/iommu
>
>
>
> --
> Best Regards
> Guo Ren
>
> ML: https://lore.kernel.org/linux-csky/
--
Regards,
Atish
On Tue, Aug 17, 2021 at 11:24 AM Atish Patra <[email protected]> wrote:
>
> On Mon, Aug 16, 2021 at 6:48 PM Guo Ren <[email protected]> wrote:
> >
> > On Sat, Jul 24, 2021 at 5:40 AM Atish Patra <[email protected]> wrote:
> > >
> > > To facilitate streaming DMA APIs, this patch introduces a set of generic
> > > cache operations related dma sync. Any platform can use the generic ops
> > > to provide platform specific cache management operations. Once the
> > > standard RISC-V CMO extension is available, it can be built on top of it.
> > >
> > > Signed-off-by: Atish Patra <[email protected]>
> > > ---
> > > arch/riscv/include/asm/dma-noncoherent.h | 19 +++++++
> > > arch/riscv/mm/Makefile | 1 +
> > > arch/riscv/mm/dma-noncoherent.c | 66 ++++++++++++++++++++++++
> > > 3 files changed, 86 insertions(+)
> > > create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
> > > create mode 100644 arch/riscv/mm/dma-noncoherent.c
> > >
> > > diff --git a/arch/riscv/include/asm/dma-noncoherent.h b/arch/riscv/include/asm/dma-noncoherent.h
> > > new file mode 100644
> > > index 000000000000..5bdb03c9c427
> > > --- /dev/null
> > > +++ b/arch/riscv/include/asm/dma-noncoherent.h
> > > @@ -0,0 +1,19 @@
> > > +/* SPDX-License-Identifier: GPL-2.0-only */
> > > +/*
> > > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > > + */
> > > +
> > > +#ifndef __ASM_RISCV_DMA_NON_COHERENT_H
> > > +#define __ASM_RISCV_DMA_NON_COHERENT_H
> > > +
> > > +#ifdef CONFIG_RISCV_DMA_NONCOHERENT
> > > +struct riscv_dma_cache_sync {
> > > + void (*cache_invalidate)(phys_addr_t paddr, size_t size);
> > > + void (*cache_clean)(phys_addr_t paddr, size_t size);
> > > + void (*cache_flush)(phys_addr_t paddr, size_t size);
> > > +};
> > I like the style like this than my previous patch which using
> > sbi_call. The c906 has custom instructions that could be called in
> > S-mode directly.
> >
>
> How are you going to include the custom instructions in the upstream kernel ?
In errata, call set_ops? I'm headache with that issue.
>
> > Hope the patch could be soon merged, after correct the
> > DMA_FROM/TO_DEVICE/BIDIRECTIONAL and alternatives ops_set.
> >
> > > +
> > > +void riscv_dma_cache_sync_set(struct riscv_dma_cache_sync *ops);
> > > +#endif
> > > +
> > > +#endif
> > > diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
> > > index 7ebaef10ea1b..959bef49098b 100644
> > > --- a/arch/riscv/mm/Makefile
> > > +++ b/arch/riscv/mm/Makefile
> > > @@ -27,3 +27,4 @@ KASAN_SANITIZE_init.o := n
> > > endif
> > >
> > > obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
> > > +obj-$(CONFIG_RISCV_DMA_NONCOHERENT) += dma-noncoherent.o
> > > diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
> > > new file mode 100644
> > > index 000000000000..2f6e9627c4aa
> > > --- /dev/null
> > > +++ b/arch/riscv/mm/dma-noncoherent.c
> > > @@ -0,0 +1,66 @@
> > > +// SPDX-License-Identifier: GPL-2.0-only
> > > +/*
> > > + * RISC-V specific functions to support DMA for non-coherent devices
> > > + *
> > > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > > + */
> > > +
> > > +#include <linux/dma-direct.h>
> > > +#include <linux/dma-map-ops.h>
> > > +#include <linux/init.h>
> > > +#include <linux/io.h>
> > > +#include <linux/libfdt.h>
> > > +#include <linux/mm.h>
> > > +#include <linux/of.h>
> > > +#include <linux/of_fdt.h>
> > > +#include <asm/dma-noncoherent.h>
> > > +
> > > +static struct riscv_dma_cache_sync *dma_cache_sync;
> > > +unsigned long riscv_dma_uc_offset;
> > > +
> > > +static void __dma_sync(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> > > +{
> > > + if ((dir == DMA_FROM_DEVICE) && (dma_cache_sync->cache_invalidate))
> > > + dma_cache_sync->cache_invalidate(paddr, size);
> > > + else if ((dir == DMA_TO_DEVICE) && (dma_cache_sync->cache_clean))
> > > + dma_cache_sync->cache_clean(paddr, size);
> > > + else if ((dir == DMA_BIDIRECTIONAL) && dma_cache_sync->cache_flush)
> > > + dma_cache_sync->cache_flush(paddr, size);
> > > +}
> > > +
> > > +void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> > > +{
> > > + if (!dma_cache_sync)
> > > + return;
> > > +
> > > + __dma_sync(paddr, size, dir);
> > > +}
> > > +
> > > +void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> > > +{
> > > + if (!dma_cache_sync)
> > > + return;
> > > +
> > > + __dma_sync(paddr, size, dir);
> > > +}
> > > +
> > > +void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
> > > + const struct iommu_ops *iommu, bool coherent)
> > > +{
> > > + /* If a specific device is dma-coherent, set it here */
> > > + dev->dma_coherent = coherent;
> > > +}
> > > +
> > > +void arch_dma_prep_coherent(struct page *page, size_t size)
> > > +{
> > > + void *flush_addr = page_address(page);
> > > +
> > > + memset(flush_addr, 0, size);
> > > + if (dma_cache_sync && dma_cache_sync->cache_flush)
> > > + dma_cache_sync->cache_flush(__pa(flush_addr), size);
> > > +}
> > > +
> > > +void riscv_dma_cache_sync_set(struct riscv_dma_cache_sync *ops)
> > > +{
> > > + dma_cache_sync = ops;
> > > +}
> > > --
> > > 2.31.1
> > >
> > > _______________________________________________
> > > iommu mailing list
> > > [email protected]
> > > https://lists.linuxfoundation.org/mailman/listinfo/iommu
> >
> >
> >
> > --
> > Best Regards
> > Guo Ren
> >
> > ML: https://lore.kernel.org/linux-csky/
> > _______________________________________________
> > iommu mailing list
> > [email protected]
> > https://lists.linuxfoundation.org/mailman/listinfo/iommu
>
>
>
> --
> Regards,
> Atish
--
Best Regards
Guo Ren
ML: https://lore.kernel.org/linux-csky/
On Tue, Aug 17, 2021 at 11:28 AM Atish Patra <[email protected]> wrote:
>
> On Mon, Aug 16, 2021 at 6:37 PM Guo Ren <[email protected]> wrote:
> >
> > 1
> >
> > On Thu, Jul 29, 2021 at 2:19 PM Atish Patra <[email protected]> wrote:
> > >
> > > On Wed, Jul 28, 2021 at 9:30 PM Palmer Dabbelt <[email protected]> wrote:
> > > >
> > > > On Fri, 23 Jul 2021 14:40:26 PDT (-0700), Atish Patra wrote:
> > > > > RISC-V privilege specification doesn't define an IOMMU or any method modify
> > > > > PMA attributes or PTE entries to allow non-coherent mappings yet. In
> > > > > the beginning, this approach was adopted assuming that most of the RISC-V
> > > > > platforms would support full cache-coherent IO. Here is excerpt from the
> > > > > priv spec section 3.6.5
> > > > >
> > > > > "In RISC-V platforms, the use of hardware-incoherent regions is discouraged
> > > > > due to software complexity, performance, and energy impacts."
> > > > >
> > > > > While some of the RISC-V platforms adhere to the above suggestion, not all
> > > > > platforms can afford to build to fully cache-coherent I/O devices. To
> > > > > address DMA for non-coherent I/O devices, we need to mark a region of memory
> > > > > as non-cacheable. Some of the platforms rely on a fixed region of uncached
> > > > > memory that is remapped to the system memory while some other modify
> > > > > the PTE entries to achieve that.
> > > > >
> > > > > The patch3 solves the issue for the fist use case by using a global
> > > > > pool of memory that is reserved for DMA. The device access the reserved area
> > > > > of the region while corresponding CPU address will be from uncached region
> > > > > As the uncached region is remapped to the beginning of the system ram, both
> > > > > CPU and device get the same view.
> > > > >
> > > > > To facilitate streaming DMA APIs, patch 1 introduces a set of generic
> > > > > cache operations. Any platform can use the generic ops to provide platform
> > > > > specific cache management operations. Once the standard RISC-V CMO extension
> > > > > is available, it will also use these generic ops.
> > > > >
> > > > > To address the second use case, Page Based Memory Attribute (PBMT) extension
> > > > > is proposed. Once the extension is in good shape, we can leverage that
> > > > > using CONFIG_DIRECT_REMAP. Currently, it is selected via a compile time config
> > > > > option. We will probably need another arch specific hooks to know if the
> > > > > platform supports direct remap at runtime. For RISC-V, it will check the
> > > > > presence of PBMT extension while other arch function will simply return true
> > > >
> > > > IIUC this is another extension that's not yet frozen or implemented in
> > > > hardware? Is this one compatible with what's in the c906, or is it
> > > > doing things its own way?
> > >
> > > Hi Palmer,
> > > This series doesn't implement the PBMT extension which is still in discussion.
> > > It simply reuse the existing non-coherent dma mapping support in
> > > upstream kernel and enable
> > > it for RISC-V. The current version uses a non-coherent global pool. I
> > > will update it to use arch_set_uncached
> > > as per Christoph's suggestion. It solves the non-coherent DMA problem
> > > for beagleV and not c906.
> > >
> > > I briefly mentioned the PBMT extension just to provide an idea how the
> > > RISC-V Linux kernel
> > > can support both unached window and PBMT extension. PBMT extension is
> > > planned to be frozen
> > > by the end of this year and none of the hardware has implemented it.
> > >
> > > The implementation in c906 is a non-standard one and will not be
> > > supported by the default PBMT
> > > extension implementation.
> > The default PBMT & c908 PBMT are similar, only BIT definitions are
> > different. I propose to support default PBMT first and give the back
> > door to modify the PBMT definition during boot.
> > The "protection_map[] = (__P000, __P001 ..__S000, __S001)" in
> > mm/mmap.c has been modified by arch/mips, arm, sparc, x86, so I think
> > it's proper solution direction.
> >
> > The reset problem is how to passing custom PBMT at the very early boot
> > stage. Now I'm trying to use the DTS parsing instead of boot param hdr
> > which Anup objected to.
> >
>
> IIRC, c906 has a compatible mode that has the compliant PTE bit modifications.
> Can you use that mode iOn the Allwinner D1 board to boot Linux ? I am
> not sure if you have any fallback method for non-coherent DMA
> if custom DMA_COHERENT bits are not enabled through enhanced mode ?
We need custom PBMT(enhanced mode) to enable the dma driver on D1
(GMAC, USB, EMMC) or these drivers couldn't work.
D1 hasn't any uncached region in SOC design.
>
> > ref: https://lore.kernel.org/linux-riscv/[email protected]/
> >
> > Any comments are welcome.
> >
> > >
> > >
> > > >
> > > > > if DIRECT_REMAP is enabled. This is required as arious different config
> > > > > (DIRECT_REMAP, GLOBAL_POOL) will be enabled in the defconfig so that a
> > > > > unified kernel image can boot on all RISC-V platforms.
> > > > >
> > > > > This patch series depends on Christoph's global pool support series[1].
> > > > > Tested on Qemu, HiFive unleashed and beagleV. This series is also available
> > > > > at [2].
> > > > > This series also solves the non-coherent DMA support on beagleV but requires
> > > > > additional beagleV specific patches[3] which will be upstreamed soon.
> > > > >
> > > > >
> > > > > [1] https://lists.linuxfoundation.org/pipermail/iommu/2021-July/057266.html
> > > > > [2] https://github.com/atishp04/linux/tree/riscv_nc_global_pool
> > > > > [3] https://github.com/atishp04/linux/tree/wip_beaglev_dma_nc_global
> > > > >
> > > > > Atish Patra (5):
> > > > > RISC-V: Implement arch_sync_dma* functions
> > > > > of: Move of_dma_get_range to of_address.h
> > > > > dma-mapping: Enable global non-coherent pool support for RISC-V
> > > > > dma-direct: Allocate dma pages directly if global pool allocation
> > > > > fails
> > > > > RISC-V: Support a new config option for non-coherent DMA
> > > > >
> > > > > arch/riscv/Kconfig | 8 +++
> > > > > arch/riscv/include/asm/dma-noncoherent.h | 19 +++++++
> > > > > arch/riscv/mm/Makefile | 1 +
> > > > > arch/riscv/mm/dma-noncoherent.c | 66 ++++++++++++++++++++++++
> > > > > drivers/of/of_private.h | 10 ----
> > > > > include/linux/of_address.h | 12 +++++
> > > > > kernel/dma/coherent.c | 49 +++++++++++++++---
> > > > > kernel/dma/direct.c | 7 ++-
> > > > > 8 files changed, 152 insertions(+), 20 deletions(-)
> > > > > create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
> > > > > create mode 100644 arch/riscv/mm/dma-noncoherent.c
> > > >
> > > > Can you guys please make up your minds about how this is going to be
> > > > supported at the ISA level? I get a different answer every day here:
> > > > sometimes it's that these systems are not compliant, sometimes that
> > > > Linux is the compliance suite, sometimes that we're doing an ISA
> > > > extension, and sometimes that we're doing the SBI stuff.
> > > >
> > >
> > > I am not sure whom you have talked to. I would be happy to set up a
> > > meeting so that everybody is on
> > > the same page if you are getting different answers every time.
> > >
> > > > I don't really care all that much about what the decision is, but it's
> > > > impossible to move forward without some semblance of a plan.
> > > >
> > > > _______________________________________________
> > > > linux-riscv mailing list
> > > > [email protected]
> > > > http://lists.infradead.org/mailman/listinfo/linux-riscv
> > >
> > >
> > >
> > > --
> > > Regards,
> > > Atish
> > > _______________________________________________
> > > iommu mailing list
> > > [email protected]
> > > https://lists.linuxfoundation.org/mailman/listinfo/iommu
> >
> >
> >
> > --
> > Best Regards
> > Guo Ren
> >
> > ML: https://lore.kernel.org/linux-csky/
>
>
>
> --
> Regards,
> Atish
--
Best Regards
Guo Ren
ML: https://lore.kernel.org/linux-csky/
On Tue, Jul 27, 2021 at 5:53 AM Atish Patra <[email protected]> wrote:
>
> On Sun, Jul 25, 2021 at 11:57 PM Christoph Hellwig <[email protected]> wrote:
> >
> > > +#ifdef CONFIG_RISCV_DMA_NONCOHERENT
> > > +struct riscv_dma_cache_sync {
> > > + void (*cache_invalidate)(phys_addr_t paddr, size_t size);
> > > + void (*cache_clean)(phys_addr_t paddr, size_t size);
> > > + void (*cache_flush)(phys_addr_t paddr, size_t size);
> > > +};
> > > +
> > > +void riscv_dma_cache_sync_set(struct riscv_dma_cache_sync *ops);
> > > +#endif
> >
> > As told a bunch of times before: doing indirect calls here is a
> > performance nightmare. Use something that actually does perform
> > horribly like alternatives. Or even delay implementing that until
> > we need it and do a plain direct call for now.
> >
>
> I was initially planning to replace this with alternatives in the
> future versions. But there is no point in doing it
> until we have CMO spec finalized. We also don't have any other
> platform using these apart from sifive l2
> cache controllers for now.
>
> I will change these to direct for now.
I think alternatives' would be helpful, I've rebased on your patchset, thx.
https://lore.kernel.org/linux-riscv/[email protected]/
>
> > static void __dma_sync(phys_addr_t paddr, size_t size, enum dma_data_direction dir)
> > > +{
> > > + if ((dir == DMA_FROM_DEVICE) && (dma_cache_sync->cache_invalidate))
> > > + dma_cache_sync->cache_invalidate(paddr, size);
> > > + else if ((dir == DMA_TO_DEVICE) && (dma_cache_sync->cache_clean))
> > > + dma_cache_sync->cache_clean(paddr, size);
> > > + else if ((dir == DMA_BIDIRECTIONAL) && dma_cache_sync->cache_flush)
> > > + dma_cache_sync->cache_flush(paddr, size);
> > > +}
> >
> > The seletion of flush types is completely broken. Take a look at the
> > comment in arch/arc/mm/dma.c above arch_sync_dma_for_device for a good
> > explanation.
> >
>
> Thanks. I will fix it.
>
> > > +void arch_dma_prep_coherent(struct page *page, size_t size)
> > > +{
> > > + void *flush_addr = page_address(page);
> > > +
> > > + memset(flush_addr, 0, size);
> >
> > arch_dma_prep_coherent is not supposed to modify the content of
> > the data.
>
> Sorry. This was a leftover from some experimental code. It shouldn't
> have been included.
>
> > _______________________________________________
> > iommu mailing list
> > [email protected]
> > https://lists.linuxfoundation.org/mailman/listinfo/iommu
>
>
>
> --
> Regards,
> Atish
> _______________________________________________
> iommu mailing list
> [email protected]
> https://lists.linuxfoundation.org/mailman/listinfo/iommu
--
Best Regards
Guo Ren
ML: https://lore.kernel.org/linux-csky/