All of lore.kernel.org
 help / color / mirror / Atom feed
From: Catalin Marinas <catalin.marinas@arm.com>
To: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Cc: robh+dt@kernel.org, hch@lst.de, ardb@kernel.org,
	linux-kernel@vger.kernel.org, robin.murphy@arm.com,
	linux-arm-kernel@lists.infradead.org,
	linux-rpi-kernel@lists.infradead.org, jeremy.linton@arm.com,
	iommu@lists.linux-foundation.org, devicetree@vger.kernel.org,
	will@kernel.org, lorenzo.pieralisi@arm.com, guohanjun@huawei.com
Subject: Re: [PATCH v4 5/7] arm64: mm: Set ZONE_DMA size based on devicetree's dma-ranges
Date: Thu, 22 Oct 2020 19:06:33 +0100	[thread overview]
Message-ID: <20201022180632.GI1229@gaia> (raw)
In-Reply-To: <20201021123437.21538-6-nsaenzjulienne@suse.de>

On Wed, Oct 21, 2020 at 02:34:35PM +0200, Nicolas Saenz Julienne wrote:
> @@ -188,9 +186,11 @@ static phys_addr_t __init max_zone_phys(unsigned int zone_bits)
>  static void __init zone_sizes_init(unsigned long min, unsigned long max)
>  {
>  	unsigned long max_zone_pfns[MAX_NR_ZONES]  = {0};
> +	unsigned int __maybe_unused dt_zone_dma_bits;
>  
>  #ifdef CONFIG_ZONE_DMA
> -	zone_dma_bits = ARM64_ZONE_DMA_BITS;
> +	dt_zone_dma_bits = ilog2(of_dma_get_max_cpu_address(NULL));
> +	zone_dma_bits = min(32U, dt_zone_dma_bits);

A thought: can we remove the min here and expand ZONE_DMA to whatever
dt_zone_dma_bits says? More on this below.

>  	arm64_dma_phys_limit = max_zone_phys(zone_dma_bits);
>  	max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit);
>  #endif

I was talking earlier to Ard and Robin on the ZONE_DMA32 history and the
need for max_zone_phys(). This was rather theoretical, the Seattle
platform has all RAM starting above 4GB and that led to an empty
ZONE_DMA32 originally. The max_zone_phys() hack was meant to lift
ZONE_DMA32 into the bottom of the RAM, on the assumption that such
32-bit devices would have a DMA offset hardwired. We are not aware of
any such case on arm64 systems and even on Seattle, IIUC 32-bit devices
only work if they are behind an SMMU (so no hardwired offset).

In hindsight, it would have made more sense on platforms with RAM above
4GB to expand ZONE_DMA32 to cover the whole memory (so empty
ZONE_NORMAL). Something like:

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index a53c1e0fb017..7d5e3dd85617 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -187,8 +187,12 @@ static void __init reserve_elfcorehdr(void)
  */
 static phys_addr_t __init max_zone_phys(unsigned int zone_bits)
 {
-	phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, zone_bits);
-	return min(offset + (1ULL << zone_bits), memblock_end_of_DRAM());
+	phys_addr_t zone_mask = 1ULL << zone_bits;
+
+	if (!(memblock_start_of_DRAM() & zone_mask))
+		zone_mask = PHYS_ADDR_MAX;
+
+	return min(zone_mask, memblock_end_of_DRAM());
 }
 
 static void __init zone_sizes_init(unsigned long min, unsigned long max)

I don't think this makes any difference for ZONE_DMA unless a
broken DT or IORT reports the max CPU address below the start of DRAM.

There's a minor issue if of_dma_get_max_cpu_address() matches
memblock_end_of_DRAM() but they are not a power of 2. We'd be left with
a bit of RAM at the end in ZONE_NORMAL due to ilog2 truncation.

-- 
Catalin

WARNING: multiple messages have this Message-ID (diff)
From: Catalin Marinas <catalin.marinas@arm.com>
To: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Cc: devicetree@vger.kernel.org, will@kernel.org,
	linux-kernel@vger.kernel.org, jeremy.linton@arm.com,
	ardb@kernel.org, iommu@lists.linux-foundation.org,
	robh+dt@kernel.org, linux-rpi-kernel@lists.infradead.org,
	guohanjun@huawei.com, robin.murphy@arm.com, hch@lst.de,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v4 5/7] arm64: mm: Set ZONE_DMA size based on devicetree's dma-ranges
Date: Thu, 22 Oct 2020 19:06:33 +0100	[thread overview]
Message-ID: <20201022180632.GI1229@gaia> (raw)
In-Reply-To: <20201021123437.21538-6-nsaenzjulienne@suse.de>

On Wed, Oct 21, 2020 at 02:34:35PM +0200, Nicolas Saenz Julienne wrote:
> @@ -188,9 +186,11 @@ static phys_addr_t __init max_zone_phys(unsigned int zone_bits)
>  static void __init zone_sizes_init(unsigned long min, unsigned long max)
>  {
>  	unsigned long max_zone_pfns[MAX_NR_ZONES]  = {0};
> +	unsigned int __maybe_unused dt_zone_dma_bits;
>  
>  #ifdef CONFIG_ZONE_DMA
> -	zone_dma_bits = ARM64_ZONE_DMA_BITS;
> +	dt_zone_dma_bits = ilog2(of_dma_get_max_cpu_address(NULL));
> +	zone_dma_bits = min(32U, dt_zone_dma_bits);

A thought: can we remove the min here and expand ZONE_DMA to whatever
dt_zone_dma_bits says? More on this below.

>  	arm64_dma_phys_limit = max_zone_phys(zone_dma_bits);
>  	max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit);
>  #endif

I was talking earlier to Ard and Robin on the ZONE_DMA32 history and the
need for max_zone_phys(). This was rather theoretical, the Seattle
platform has all RAM starting above 4GB and that led to an empty
ZONE_DMA32 originally. The max_zone_phys() hack was meant to lift
ZONE_DMA32 into the bottom of the RAM, on the assumption that such
32-bit devices would have a DMA offset hardwired. We are not aware of
any such case on arm64 systems and even on Seattle, IIUC 32-bit devices
only work if they are behind an SMMU (so no hardwired offset).

In hindsight, it would have made more sense on platforms with RAM above
4GB to expand ZONE_DMA32 to cover the whole memory (so empty
ZONE_NORMAL). Something like:

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index a53c1e0fb017..7d5e3dd85617 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -187,8 +187,12 @@ static void __init reserve_elfcorehdr(void)
  */
 static phys_addr_t __init max_zone_phys(unsigned int zone_bits)
 {
-	phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, zone_bits);
-	return min(offset + (1ULL << zone_bits), memblock_end_of_DRAM());
+	phys_addr_t zone_mask = 1ULL << zone_bits;
+
+	if (!(memblock_start_of_DRAM() & zone_mask))
+		zone_mask = PHYS_ADDR_MAX;
+
+	return min(zone_mask, memblock_end_of_DRAM());
 }
 
 static void __init zone_sizes_init(unsigned long min, unsigned long max)

I don't think this makes any difference for ZONE_DMA unless a
broken DT or IORT reports the max CPU address below the start of DRAM.

There's a minor issue if of_dma_get_max_cpu_address() matches
memblock_end_of_DRAM() but they are not a power of 2. We'd be left with
a bit of RAM at the end in ZONE_NORMAL due to ilog2 truncation.

-- 
Catalin
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

WARNING: multiple messages have this Message-ID (diff)
From: Catalin Marinas <catalin.marinas@arm.com>
To: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Cc: devicetree@vger.kernel.org, lorenzo.pieralisi@arm.com,
	will@kernel.org, linux-kernel@vger.kernel.org,
	jeremy.linton@arm.com, ardb@kernel.org,
	iommu@lists.linux-foundation.org, robh+dt@kernel.org,
	linux-rpi-kernel@lists.infradead.org, guohanjun@huawei.com,
	robin.murphy@arm.com, hch@lst.de,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v4 5/7] arm64: mm: Set ZONE_DMA size based on devicetree's dma-ranges
Date: Thu, 22 Oct 2020 19:06:33 +0100	[thread overview]
Message-ID: <20201022180632.GI1229@gaia> (raw)
In-Reply-To: <20201021123437.21538-6-nsaenzjulienne@suse.de>

On Wed, Oct 21, 2020 at 02:34:35PM +0200, Nicolas Saenz Julienne wrote:
> @@ -188,9 +186,11 @@ static phys_addr_t __init max_zone_phys(unsigned int zone_bits)
>  static void __init zone_sizes_init(unsigned long min, unsigned long max)
>  {
>  	unsigned long max_zone_pfns[MAX_NR_ZONES]  = {0};
> +	unsigned int __maybe_unused dt_zone_dma_bits;
>  
>  #ifdef CONFIG_ZONE_DMA
> -	zone_dma_bits = ARM64_ZONE_DMA_BITS;
> +	dt_zone_dma_bits = ilog2(of_dma_get_max_cpu_address(NULL));
> +	zone_dma_bits = min(32U, dt_zone_dma_bits);

A thought: can we remove the min here and expand ZONE_DMA to whatever
dt_zone_dma_bits says? More on this below.

>  	arm64_dma_phys_limit = max_zone_phys(zone_dma_bits);
>  	max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit);
>  #endif

I was talking earlier to Ard and Robin on the ZONE_DMA32 history and the
need for max_zone_phys(). This was rather theoretical, the Seattle
platform has all RAM starting above 4GB and that led to an empty
ZONE_DMA32 originally. The max_zone_phys() hack was meant to lift
ZONE_DMA32 into the bottom of the RAM, on the assumption that such
32-bit devices would have a DMA offset hardwired. We are not aware of
any such case on arm64 systems and even on Seattle, IIUC 32-bit devices
only work if they are behind an SMMU (so no hardwired offset).

In hindsight, it would have made more sense on platforms with RAM above
4GB to expand ZONE_DMA32 to cover the whole memory (so empty
ZONE_NORMAL). Something like:

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index a53c1e0fb017..7d5e3dd85617 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -187,8 +187,12 @@ static void __init reserve_elfcorehdr(void)
  */
 static phys_addr_t __init max_zone_phys(unsigned int zone_bits)
 {
-	phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, zone_bits);
-	return min(offset + (1ULL << zone_bits), memblock_end_of_DRAM());
+	phys_addr_t zone_mask = 1ULL << zone_bits;
+
+	if (!(memblock_start_of_DRAM() & zone_mask))
+		zone_mask = PHYS_ADDR_MAX;
+
+	return min(zone_mask, memblock_end_of_DRAM());
 }
 
 static void __init zone_sizes_init(unsigned long min, unsigned long max)

I don't think this makes any difference for ZONE_DMA unless a
broken DT or IORT reports the max CPU address below the start of DRAM.

There's a minor issue if of_dma_get_max_cpu_address() matches
memblock_end_of_DRAM() but they are not a power of 2. We'd be left with
a bit of RAM at the end in ZONE_NORMAL due to ilog2 truncation.

-- 
Catalin

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2020-10-22 18:06 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-21 12:34 [PATCH v4 0/7] arm64: Default to 32-bit wide ZONE_DMA Nicolas Saenz Julienne
2020-10-21 12:34 ` Nicolas Saenz Julienne
2020-10-21 12:34 ` Nicolas Saenz Julienne
2020-10-21 12:34 ` Nicolas Saenz Julienne
2020-10-21 12:34 ` [PATCH v4 1/7] arm64: mm: Move reserve_crashkernel() into mem_init() Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-21 12:34 ` [PATCH v4 2/7] arm64: mm: Move zone_dma_bits initialization into zone_sizes_init() Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-21 12:34 ` [PATCH v4 3/7] of/address: Introduce of_dma_get_max_cpu_address() Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-22 12:23   ` Ard Biesheuvel
2020-10-22 12:23     ` Ard Biesheuvel
2020-10-22 12:23     ` Ard Biesheuvel
2020-10-22 14:03     ` Nicolas Saenz Julienne
2020-10-22 14:03       ` Nicolas Saenz Julienne
2020-10-22 14:03       ` Nicolas Saenz Julienne
2020-10-21 12:34 ` [PATCH v4 4/7] of: unittest: Add test for of_dma_get_max_cpu_address() Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-26 14:38   ` Rob Herring
2020-10-26 14:38     ` Rob Herring
2020-10-26 14:38     ` Rob Herring
2020-10-21 12:34 ` [PATCH v4 5/7] arm64: mm: Set ZONE_DMA size based on devicetree's dma-ranges Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-22 18:06   ` Catalin Marinas [this message]
2020-10-22 18:06     ` Catalin Marinas
2020-10-22 18:06     ` Catalin Marinas
2020-10-23 15:27     ` Nicolas Saenz Julienne
2020-10-23 15:27       ` Nicolas Saenz Julienne
2020-10-23 15:27       ` Nicolas Saenz Julienne
2020-10-23 17:38       ` Catalin Marinas
2020-10-23 17:38         ` Catalin Marinas
2020-10-23 17:38         ` Catalin Marinas
2020-10-21 12:34 ` [PATCH v4 6/7] arm64: mm: Set ZONE_DMA size based on early IORT scan Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-27 11:50   ` Lorenzo Pieralisi
2020-10-27 11:50     ` Lorenzo Pieralisi
2020-10-27 11:50     ` Lorenzo Pieralisi
2020-10-28 11:08   ` Hanjun Guo
2020-10-28 11:08     ` Hanjun Guo
2020-10-28 11:08     ` Hanjun Guo
2020-10-21 12:34 ` [PATCH v4 7/7] mm: Remove examples from enum zone_type comment Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-21 12:34   ` Nicolas Saenz Julienne
2020-10-23  6:49   ` Christoph Hellwig
2020-10-23  6:49     ` Christoph Hellwig
2020-10-23  6:49     ` Christoph Hellwig
2020-10-23  6:49     ` Christoph Hellwig
2020-10-23 19:05 ` [PATCH v4 0/7] arm64: Default to 32-bit wide ZONE_DMA Jeremy Linton
2020-10-23 19:05   ` Jeremy Linton
2020-10-23 19:05   ` Jeremy Linton
2020-10-23 19:05   ` Jeremy Linton
2020-10-27 11:50   ` Nicolas Saenz Julienne
2020-10-27 11:50     ` Nicolas Saenz Julienne
2020-10-27 11:50     ` Nicolas Saenz Julienne
2020-10-27 11:50     ` Nicolas Saenz Julienne
2020-10-27 11:50     ` Nicolas Saenz Julienne

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201022180632.GI1229@gaia \
    --to=catalin.marinas@arm.com \
    --cc=ardb@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=guohanjun@huawei.com \
    --cc=hch@lst.de \
    --cc=iommu@lists.linux-foundation.org \
    --cc=jeremy.linton@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rpi-kernel@lists.infradead.org \
    --cc=lorenzo.pieralisi@arm.com \
    --cc=nsaenzjulienne@suse.de \
    --cc=robh+dt@kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.