diff mbox series

[RFC,2/2] apple: dart: use driver specific instance of LMB

Message ID 20241029071846.514559-3-sughosh.ganu@linaro.org
State New
Headers show
Series apple: dart: Add driver specific instance of LMB | expand

Commit Message

Sughosh Ganu Oct. 29, 2024, 7:18 a.m. UTC
The LMB module is typically used for managing the platform's RAM
memory. RAM memory gets added to the module's memory map, and
subsequently allocated through various LMB API's.

The IOMMU driver for the apple platforms also uses the LMB API's for
allocating device virtual addresses(VA). These addresses are different
from the RAM addresses, and cannot be added to the RAM memory map. Add
a separate instance of LMB memory map for the device VA's, which gets
managed by the IOMMU driver. Use lmb_push() and lmb_pop() functions to
set-up the relevant lmb instance.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
 drivers/iommu/apple_dart.c | 67 +++++++++++++++++++++++++++++++++++++-
 include/lmb.h              |  2 ++
 lib/lmb.c                  |  1 -
 3 files changed, 68 insertions(+), 2 deletions(-)

Comments

Janne Grunau Oct. 29, 2024, 8:32 a.m. UTC | #1
Hej,

On Tue, Oct 29, 2024 at 12:48:46PM +0530, Sughosh Ganu wrote:
> The LMB module is typically used for managing the platform's RAM
> memory. RAM memory gets added to the module's memory map, and
> subsequently allocated through various LMB API's.
> 
> The IOMMU driver for the apple platforms also uses the LMB API's for
> allocating device virtual addresses(VA). These addresses are different
> from the RAM addresses, and cannot be added to the RAM memory map. Add
> a separate instance of LMB memory map for the device VA's, which gets
> managed by the IOMMU driver. Use lmb_push() and lmb_pop() functions to
> set-up the relevant lmb instance.

thanks, this fixes the initial brokenness when setting up dma mappings
but I still see SError due to translation fault. I don't have time right
now to look into it so it could be unrelated to the iommu.

> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
>  drivers/iommu/apple_dart.c | 67 +++++++++++++++++++++++++++++++++++++-
>  include/lmb.h              |  2 ++
>  lib/lmb.c                  |  1 -
>  3 files changed, 68 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iommu/apple_dart.c b/drivers/iommu/apple_dart.c
> index 611ac7cd6de..55f60287b0e 100644
> --- a/drivers/iommu/apple_dart.c
> +++ b/drivers/iommu/apple_dart.c
> @@ -3,6 +3,7 @@
>   * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
>   */
>  
> +#include <alist.h>
>  #include <cpu_func.h>
>  #include <dm.h>
>  #include <iommu.h>
> @@ -70,6 +71,8 @@
>  
>  struct apple_dart_priv {
>  	void *base;
> +	struct lmb apple_dart_lmb;
> +	struct lmb ram_lmb;
>  	u64 *l1, *l2;
>  	int bypass, shift;
>  
> @@ -87,6 +90,56 @@ struct apple_dart_priv {
>  	void (*flush_tlb)(struct apple_dart_priv *priv);
>  };
>  
> +static int apple_dart_lmb_init(struct apple_dart_priv *priv)
> +{
> +	bool ret;
> +	struct lmb *almb = &priv->apple_dart_lmb;
> +
> +	ret = alist_init(&almb->free_mem, sizeof(struct lmb_region),
> +			 (uint)LMB_ALIST_INITIAL_SIZE);
> +	if (!ret) {
> +		log_debug("Unable to initialise the list for LMB free memory\n");
> +		return -ENOMEM;
> +	}
> +
> +	ret = alist_init(&almb->used_mem, sizeof(struct lmb_region),
> +			 (uint)LMB_ALIST_INITIAL_SIZE);
> +	if (!ret) {
> +		log_debug("Unable to initialise the list for LMB used memory\n");
> +		return -ENOMEM;
> +	}
> +
> +	return 0;
> +}
> +
> +static void apple_dart_lmb_uninit(struct apple_dart_priv *priv)
> +{
> +	struct lmb *almb = &priv->apple_dart_lmb;
> +
> +	alist_uninit(&almb->free_mem);
> +	alist_uninit(&almb->used_mem);
> +}
> +
> +static void apple_dart_lmb_setup(struct apple_dart_priv *priv)
> +{
> +	struct lmb *almb = &priv->apple_dart_lmb;
> +	struct lmb *rlmb = &priv->ram_lmb;
> +
> +	lmb_push(rlmb);
> +
> +	lmb_pop(almb);

This doesn't look look like a good solution to me. We're conflating two
different concepts into the global lmb. This looks error prone to me. I
was looking into adding iomb_* entry points into the lmb points which
take a pointer.

Janne
Sughosh Ganu Oct. 29, 2024, 8:52 a.m. UTC | #2
On Tue, 29 Oct 2024 at 14:02, Janne Grunau <j@jannau.net> wrote:
>
> Hej,
>
> On Tue, Oct 29, 2024 at 12:48:46PM +0530, Sughosh Ganu wrote:
> > The LMB module is typically used for managing the platform's RAM
> > memory. RAM memory gets added to the module's memory map, and
> > subsequently allocated through various LMB API's.
> >
> > The IOMMU driver for the apple platforms also uses the LMB API's for
> > allocating device virtual addresses(VA). These addresses are different
> > from the RAM addresses, and cannot be added to the RAM memory map. Add
> > a separate instance of LMB memory map for the device VA's, which gets
> > managed by the IOMMU driver. Use lmb_push() and lmb_pop() functions to
> > set-up the relevant lmb instance.
>
> thanks, this fixes the initial brokenness when setting up dma mappings
> but I still see SError due to translation fault. I don't have time right
> now to look into it so it could be unrelated to the iommu.

Good to know. Thanks for testing the changes.

>
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> >  drivers/iommu/apple_dart.c | 67 +++++++++++++++++++++++++++++++++++++-
> >  include/lmb.h              |  2 ++
> >  lib/lmb.c                  |  1 -
> >  3 files changed, 68 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/iommu/apple_dart.c b/drivers/iommu/apple_dart.c
> > index 611ac7cd6de..55f60287b0e 100644
> > --- a/drivers/iommu/apple_dart.c
> > +++ b/drivers/iommu/apple_dart.c
> > @@ -3,6 +3,7 @@
> >   * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
> >   */
> >
> > +#include <alist.h>
> >  #include <cpu_func.h>
> >  #include <dm.h>
> >  #include <iommu.h>
> > @@ -70,6 +71,8 @@
> >
> >  struct apple_dart_priv {
> >       void *base;
> > +     struct lmb apple_dart_lmb;
> > +     struct lmb ram_lmb;
> >       u64 *l1, *l2;
> >       int bypass, shift;
> >
> > @@ -87,6 +90,56 @@ struct apple_dart_priv {
> >       void (*flush_tlb)(struct apple_dart_priv *priv);
> >  };
> >
> > +static int apple_dart_lmb_init(struct apple_dart_priv *priv)
> > +{
> > +     bool ret;
> > +     struct lmb *almb = &priv->apple_dart_lmb;
> > +
> > +     ret = alist_init(&almb->free_mem, sizeof(struct lmb_region),
> > +                      (uint)LMB_ALIST_INITIAL_SIZE);
> > +     if (!ret) {
> > +             log_debug("Unable to initialise the list for LMB free memory\n");
> > +             return -ENOMEM;
> > +     }
> > +
> > +     ret = alist_init(&almb->used_mem, sizeof(struct lmb_region),
> > +                      (uint)LMB_ALIST_INITIAL_SIZE);
> > +     if (!ret) {
> > +             log_debug("Unable to initialise the list for LMB used memory\n");
> > +             return -ENOMEM;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static void apple_dart_lmb_uninit(struct apple_dart_priv *priv)
> > +{
> > +     struct lmb *almb = &priv->apple_dart_lmb;
> > +
> > +     alist_uninit(&almb->free_mem);
> > +     alist_uninit(&almb->used_mem);
> > +}
> > +
> > +static void apple_dart_lmb_setup(struct apple_dart_priv *priv)
> > +{
> > +     struct lmb *almb = &priv->apple_dart_lmb;
> > +     struct lmb *rlmb = &priv->ram_lmb;
> > +
> > +     lmb_push(rlmb);
> > +
> > +     lmb_pop(almb);
>
> This doesn't look look like a good solution to me. We're conflating two
> different concepts into the global lmb. This looks error prone to me. I
> was looking into adding iomb_* entry points into the lmb points which
> take a pointer.

Yes, even I was trying to avoid having another instance of LMB as much
as possible, but given that this is breaking the platform, I thought
this would be the quickest to fix the break. Personally, I would
prefer LMB to have a consistent window of RAM addresses for all
platforms, i.e. ram_base to ram_top. Also, apart from this peculiar
scenario, I am not sure if there would be other uses of having to
allocate anything other than RAM addresses by LMB.

-sughosh


>
> Janne
Janne Grunau Oct. 30, 2024, 8:54 a.m. UTC | #3
On Tue, Oct 29, 2024 at 02:22:53PM +0530, Sughosh Ganu wrote:
> On Tue, 29 Oct 2024 at 14:02, Janne Grunau <j@jannau.net> wrote:
> >
> > On Tue, Oct 29, 2024 at 12:48:46PM +0530, Sughosh Ganu wrote:
> > > The LMB module is typically used for managing the platform's RAM
> > > memory. RAM memory gets added to the module's memory map, and
> > > subsequently allocated through various LMB API's.
> > >
> > > The IOMMU driver for the apple platforms also uses the LMB API's for
> > > allocating device virtual addresses(VA). These addresses are different
> > > from the RAM addresses, and cannot be added to the RAM memory map. Add
> > > a separate instance of LMB memory map for the device VA's, which gets
> > > managed by the IOMMU driver. Use lmb_push() and lmb_pop() functions to
> > > set-up the relevant lmb instance.
> >
> > thanks, this fixes the initial brokenness when setting up dma mappings
> > but I still see SError due to translation fault. I don't have time right
> > now to look into it so it could be unrelated to the iommu.
> 
> Good to know. Thanks for testing the changes.

It's SError-ing on `dc zva` of an invalid address which somehow got into
the main lmb. I don't see how but it went away with my minimal io_lmb
implemenmtation exposing lmb_setup, lmb_add, lmb_alloc, lmb_free.

I'm not too happy about this approach since it's a little fragile with
respect to the global struct lmb. to be somewhat safe we would need to
reorder lmb.c to avoid `static struct lmb lmb;` is visible in "shared"
code to avoid using it by surprise in the middle of functions like in
_lmb_alloc_base().

I'll post patches later today.

Janne
diff mbox series

Patch

diff --git a/drivers/iommu/apple_dart.c b/drivers/iommu/apple_dart.c
index 611ac7cd6de..55f60287b0e 100644
--- a/drivers/iommu/apple_dart.c
+++ b/drivers/iommu/apple_dart.c
@@ -3,6 +3,7 @@ 
  * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
  */
 
+#include <alist.h>
 #include <cpu_func.h>
 #include <dm.h>
 #include <iommu.h>
@@ -70,6 +71,8 @@ 
 
 struct apple_dart_priv {
 	void *base;
+	struct lmb apple_dart_lmb;
+	struct lmb ram_lmb;
 	u64 *l1, *l2;
 	int bypass, shift;
 
@@ -87,6 +90,56 @@  struct apple_dart_priv {
 	void (*flush_tlb)(struct apple_dart_priv *priv);
 };
 
+static int apple_dart_lmb_init(struct apple_dart_priv *priv)
+{
+	bool ret;
+	struct lmb *almb = &priv->apple_dart_lmb;
+
+	ret = alist_init(&almb->free_mem, sizeof(struct lmb_region),
+			 (uint)LMB_ALIST_INITIAL_SIZE);
+	if (!ret) {
+		log_debug("Unable to initialise the list for LMB free memory\n");
+		return -ENOMEM;
+	}
+
+	ret = alist_init(&almb->used_mem, sizeof(struct lmb_region),
+			 (uint)LMB_ALIST_INITIAL_SIZE);
+	if (!ret) {
+		log_debug("Unable to initialise the list for LMB used memory\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void apple_dart_lmb_uninit(struct apple_dart_priv *priv)
+{
+	struct lmb *almb = &priv->apple_dart_lmb;
+
+	alist_uninit(&almb->free_mem);
+	alist_uninit(&almb->used_mem);
+}
+
+static void apple_dart_lmb_setup(struct apple_dart_priv *priv)
+{
+	struct lmb *almb = &priv->apple_dart_lmb;
+	struct lmb *rlmb = &priv->ram_lmb;
+
+	lmb_push(rlmb);
+
+	lmb_pop(almb);
+}
+
+static void apple_dart_lmb_pop(struct apple_dart_priv *priv)
+{
+	struct lmb *almb = &priv->apple_dart_lmb;
+	struct lmb *rlmb = &priv->ram_lmb;
+
+	lmb_push(almb);
+
+	lmb_pop(rlmb);
+}
+
 static void apple_dart_t8020_flush_tlb(struct apple_dart_priv *priv)
 {
 	dsb();
@@ -123,7 +176,9 @@  static dma_addr_t apple_dart_map(struct udevice *dev, void *addr, size_t size)
 	off = (phys_addr_t)addr - paddr;
 	psize = ALIGN(size + off, DART_PAGE_SIZE);
 
+	apple_dart_lmb_setup(priv);
 	dva = lmb_alloc(psize, DART_PAGE_SIZE);
+	apple_dart_lmb_pop(priv);
 
 	idx = dva / DART_PAGE_SIZE;
 	for (i = 0; i < psize / DART_PAGE_SIZE; i++) {
@@ -159,7 +214,9 @@  static void apple_dart_unmap(struct udevice *dev, dma_addr_t addr, size_t size)
 			   (unsigned long)&priv->l2[idx + i]);
 	priv->flush_tlb(priv);
 
+	apple_dart_lmb_setup(priv);
 	lmb_free(dva, psize);
+	apple_dart_lmb_pop(priv);
 }
 
 static struct iommu_ops apple_dart_ops = {
@@ -173,7 +230,7 @@  static int apple_dart_probe(struct udevice *dev)
 	dma_addr_t addr;
 	phys_addr_t l2;
 	int ntte, nl1, nl2;
-	int sid, i;
+	int sid, i, ret;
 	u32 params2, params4;
 
 	priv->base = dev_read_addr_ptr(dev);
@@ -212,7 +269,13 @@  static int apple_dart_probe(struct udevice *dev)
 	priv->dvabase = DART_PAGE_SIZE;
 	priv->dvaend = SZ_4G - DART_PAGE_SIZE;
 
+	ret = apple_dart_lmb_init(priv);
+	if (ret)
+		return ret;
+
+	apple_dart_lmb_setup(priv);
 	lmb_add(priv->dvabase, priv->dvaend - priv->dvabase);
+	apple_dart_lmb_pop(priv);
 
 	/* Disable translations. */
 	for (sid = 0; sid < priv->nsid; sid++)
@@ -294,6 +357,8 @@  static int apple_dart_remove(struct udevice *dev)
 	}
 	priv->flush_tlb(priv);
 
+	apple_dart_lmb_uninit(priv);
+
 	return 0;
 }
 
diff --git a/include/lmb.h b/include/lmb.h
index 72d7093023a..a39b48a9a97 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -14,6 +14,8 @@ 
  * Copyright (C) 2001 Peter Bergner, IBM Corp.
  */
 
+#define LMB_ALIST_INITIAL_SIZE	4
+
 /**
  * enum lmb_flags - definition of memory region attributes
  * @LMB_NONE: no special request
diff --git a/lib/lmb.c b/lib/lmb.c
index 2960c05abfc..959236f6e5a 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -28,7 +28,6 @@  DECLARE_GLOBAL_DATA_PTR;
 #define MAP_OP_ADD		(u8)0x3
 
 #define LMB_ALLOC_ANYWHERE	0
-#define LMB_ALIST_INITIAL_SIZE	4
 
 static struct lmb lmb;