diff mbox series

arm64: Remove arm64_dma32_phys_limit and its uses

Message ID 20210107184032.11815-1-catalin.marinas@arm.com (mailing list archive)
State New, archived
Headers show
Series arm64: Remove arm64_dma32_phys_limit and its uses | expand

Commit Message

Catalin Marinas Jan. 7, 2021, 6:40 p.m. UTC
With the introduction of a dynamic ZONE_DMA range based on DT or IORT
information, there's no need for CMA allocations from the wider
ZONE_DMA32 since on most platforms ZONE_DMA will cover the 32-bit
addressable range. Remove the arm64_dma32_phys_limit and set
arm64_dma_phys_limit to cover the smallest DMA range required on the
platform. CMA allocation and crashkernel reservation now goes in
the dynamically sized ZONE_DMA.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Cc: Chen Zhou <chenzhou10@huawei.com>
---

This patch goes on top of the ARCH_LOW_ADDRESS_LIMIT fix from Nicolas,
already in the arm64 for-next/fixes which fixes a 5.5 issue with
!CONFIG_ZONE_DMA. The changes here depend on the patches in 5.11-rc1.
While they look mostly like clean-ups, they still fix a potential issue
with !CONFIG_ZONE_DMA32 configurations where arm64_dma32_phys_limit
would be equal to PHYS_MASK but we still have a limited ZONE_DMA. In
addition, it now allows proper CMA and crashkernel reservations for
RPi4.

 arch/arm64/include/asm/processor.h |  3 +--
 arch/arm64/mm/init.c               | 33 ++++++++++++++++--------------
 2 files changed, 19 insertions(+), 17 deletions(-)

Comments

Catalin Marinas Jan. 11, 2021, 4:57 p.m. UTC | #1
On Thu, Jan 07, 2021 at 06:40:32PM +0000, Catalin Marinas wrote:
> With the introduction of a dynamic ZONE_DMA range based on DT or IORT
> information, there's no need for CMA allocations from the wider
> ZONE_DMA32 since on most platforms ZONE_DMA will cover the 32-bit
> addressable range. Remove the arm64_dma32_phys_limit and set
> arm64_dma_phys_limit to cover the smallest DMA range required on the
> platform. CMA allocation and crashkernel reservation now goes in
> the dynamically sized ZONE_DMA.
> 
> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
> Cc: Chen Zhou <chenzhou10@huawei.com>
> ---
> 
> This patch goes on top of the ARCH_LOW_ADDRESS_LIMIT fix from Nicolas,
> already in the arm64 for-next/fixes which fixes a 5.5 issue with
> !CONFIG_ZONE_DMA. The changes here depend on the patches in 5.11-rc1.
> While they look mostly like clean-ups, they still fix a potential issue
> with !CONFIG_ZONE_DMA32 configurations where arm64_dma32_phys_limit
> would be equal to PHYS_MASK but we still have a limited ZONE_DMA. In
> addition, it now allows proper CMA and crashkernel reservations for
> RPi4.
[...]
> @@ -394,16 +399,9 @@ void __init arm64_memblock_init(void)
>  
>  	early_init_fdt_scan_reserved_mem();
>  
> -	if (IS_ENABLED(CONFIG_ZONE_DMA32))
> -		arm64_dma32_phys_limit = max_zone_phys(32);
> -	else
> -		arm64_dma32_phys_limit = PHYS_MASK + 1;
> -
>  	reserve_elfcorehdr();
>  
>  	high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
> -
> -	dma_contiguous_reserve(arm64_dma32_phys_limit);
>  }
>  
>  void __init bootmem_init(void)
> @@ -438,6 +436,11 @@ void __init bootmem_init(void)
>  	sparse_init();
>  	zone_sizes_init(min, max);
>  
> +	/*
> +	 * Reserve the CMA area after arm64_dma_phys_limit was initialised.
> +	 */
> +	dma_contiguous_reserve(arm64_dma_phys_limit);

Prior to this patch, disabling CONFIG_ZONE_DMA32 leads to CMA allocation
from the whole RAM as arm64_dma32_phys_limit becomes PHYS_MASK+1. With
this patch (which I plan to merge in 5.11-rc4), we limit the CMA
allocation to the 32-bit addressable RAM (if any) even if we don't
describe anything in DT or IORT since ZONE_DMA is capped at 32-bit. We
could relax this so that ZONE_DMA can be expanded beyond 32-bit with
ZONE_DMA32 disabled and no DT/IORT information. Is there a real use-case
for such configuration? We might as well make ZONE_DMA depend on
ZONE_DMA32 (though given the EXPERT dependency, people should know what
they are doing...).

An alternative would be to change max_zone_phys() to avoid the U32_MAX
cap if ZONE_DMA32 is disabled but I don't think it's worth as I don't
see much point in a kernel config with ZONE_DMA enabled and ZONE_DMA32
disabled.
Nicolas Saenz Julienne Jan. 11, 2021, 5:35 p.m. UTC | #2
On Mon, 2021-01-11 at 16:57 +0000, Catalin Marinas wrote:
> On Thu, Jan 07, 2021 at 06:40:32PM +0000, Catalin Marinas wrote:
> > With the introduction of a dynamic ZONE_DMA range based on DT or IORT
> > information, there's no need for CMA allocations from the wider
> > ZONE_DMA32 since on most platforms ZONE_DMA will cover the 32-bit
> > addressable range. Remove the arm64_dma32_phys_limit and set
> > arm64_dma_phys_limit to cover the smallest DMA range required on the
> > platform. CMA allocation and crashkernel reservation now goes in
> > the dynamically sized ZONE_DMA.
> > 
> > Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> > Cc: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
> > Cc: Chen Zhou <chenzhou10@huawei.com>
> > ---
> > 
> > This patch goes on top of the ARCH_LOW_ADDRESS_LIMIT fix from Nicolas,
> > already in the arm64 for-next/fixes which fixes a 5.5 issue with
> > !CONFIG_ZONE_DMA. The changes here depend on the patches in 5.11-rc1.
> > While they look mostly like clean-ups, they still fix a potential issue
> > with !CONFIG_ZONE_DMA32 configurations where arm64_dma32_phys_limit
> > would be equal to PHYS_MASK but we still have a limited ZONE_DMA. In
> > addition, it now allows proper CMA and crashkernel reservations for
> > RPi4.
> [...]
> > @@ -394,16 +399,9 @@ void __init arm64_memblock_init(void)
> >  
> > 
> >  	early_init_fdt_scan_reserved_mem();
> >  
> > 
> > -	if (IS_ENABLED(CONFIG_ZONE_DMA32))
> > -		arm64_dma32_phys_limit = max_zone_phys(32);
> > -	else
> > -		arm64_dma32_phys_limit = PHYS_MASK + 1;
> > -
> >  	reserve_elfcorehdr();
> >  
> > 
> >  	high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
> > -
> > -	dma_contiguous_reserve(arm64_dma32_phys_limit);
> >  }
> >  
> > 
> >  void __init bootmem_init(void)
> > @@ -438,6 +436,11 @@ void __init bootmem_init(void)
> >  	sparse_init();
> >  	zone_sizes_init(min, max);
> >  
> > 
> > +	/*
> > +	 * Reserve the CMA area after arm64_dma_phys_limit was initialised.
> > +	 */
> > +	dma_contiguous_reserve(arm64_dma_phys_limit);
> 
> Prior to this patch, disabling CONFIG_ZONE_DMA32 leads to CMA allocation
> from the whole RAM as arm64_dma32_phys_limit becomes PHYS_MASK+1. With
> this patch (which I plan to merge in 5.11-rc4), we limit the CMA
> allocation to the 32-bit addressable RAM (if any) even if we don't
> describe anything in DT or IORT since ZONE_DMA is capped at 32-bit. We
> could relax this so that ZONE_DMA can be expanded beyond 32-bit with
> ZONE_DMA32 disabled and no DT/IORT information. Is there a real use-case
> for such configuration?

AFAIK there is a good amount of PCIe cards that depend on 32-bit addressing. So
expanding ZONE_DMA beyond 32-bit would potentially break those. That said I
don't have any concrete example of people using this.

> We might as well make ZONE_DMA depend on ZONE_DMA32 (though given the EXPERT
> dependency, people should know what they are doing...).

I guess in the long run it'll make things easier to mantain, so it has its
value.

> An alternative would be to change max_zone_phys() to avoid the U32_MAX
> cap if ZONE_DMA32 is disabled but I don't think it's worth as I don't
> see much point in a kernel config with ZONE_DMA enabled and ZONE_DMA32
> disabled.

Agree, it seems a pointless configuration. On top of that, AFAIK, there isn't
any drawback to having a zero sized ZONE_DMA32.

Regards,
Nicolas
Nicolas Saenz Julienne Jan. 11, 2021, 7:04 p.m. UTC | #3
On Thu, 2021-01-07 at 18:40 +0000, Catalin Marinas wrote:
> With the introduction of a dynamic ZONE_DMA range based on DT or IORT
> information, there's no need for CMA allocations from the wider
> ZONE_DMA32 since on most platforms ZONE_DMA will cover the 32-bit
> addressable range. Remove the arm64_dma32_phys_limit and set
> arm64_dma_phys_limit to cover the smallest DMA range required on the
> platform. CMA allocation and crashkernel reservation now goes in
> the dynamically sized ZONE_DMA.
> 
> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
> Cc: Chen Zhou <chenzhou10@huawei.com>
> ---



Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Tested-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> # On RPi4B

Regards,
Nicolas
diff mbox series

Patch

diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 69ad25fbeae4..ca2cd75d3286 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -94,8 +94,7 @@ 
 #endif /* CONFIG_ARM64_FORCE_52BIT */
 
 extern phys_addr_t arm64_dma_phys_limit;
-extern phys_addr_t arm64_dma32_phys_limit;
-#define ARCH_LOW_ADDRESS_LIMIT	((arm64_dma_phys_limit ? : arm64_dma32_phys_limit) - 1)
+#define ARCH_LOW_ADDRESS_LIMIT	(arm64_dma_phys_limit - 1)
 
 struct debug_info {
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 7deddf56f7c3..709d98fea90c 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -53,13 +53,13 @@  s64 memstart_addr __ro_after_init = -1;
 EXPORT_SYMBOL(memstart_addr);
 
 /*
- * We create both ZONE_DMA and ZONE_DMA32. ZONE_DMA covers the first 1G of
- * memory as some devices, namely the Raspberry Pi 4, have peripherals with
- * this limited view of the memory. ZONE_DMA32 will cover the rest of the 32
- * bit addressable memory area.
+ * If the corresponding config options are enabled, we create both ZONE_DMA
+ * and ZONE_DMA32. By default ZONE_DMA covers the 32-bit addressable memory
+ * unless restricted on specific platforms (e.g. 30-bit on Raspberry Pi 4).
+ * In such case, ZONE_DMA32 covers the rest of the 32-bit addressable memory,
+ * otherwise it is empty.
  */
 phys_addr_t arm64_dma_phys_limit __ro_after_init;
-phys_addr_t arm64_dma32_phys_limit __ro_after_init;
 
 #ifdef CONFIG_KEXEC_CORE
 /*
@@ -84,7 +84,7 @@  static void __init reserve_crashkernel(void)
 
 	if (crash_base == 0) {
 		/* Current arm64 boot protocol requires 2MB alignment */
-		crash_base = memblock_find_in_range(0, arm64_dma32_phys_limit,
+		crash_base = memblock_find_in_range(0, arm64_dma_phys_limit,
 				crash_size, SZ_2M);
 		if (crash_base == 0) {
 			pr_warn("cannot allocate crashkernel (size:0x%llx)\n",
@@ -196,6 +196,7 @@  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 acpi_zone_dma_bits;
 	unsigned int __maybe_unused dt_zone_dma_bits;
+	phys_addr_t __maybe_unused dma32_phys_limit = max_zone_phys(32);
 
 #ifdef CONFIG_ZONE_DMA
 	acpi_zone_dma_bits = fls64(acpi_iort_dma_get_max_cpu_address());
@@ -205,8 +206,12 @@  static void __init zone_sizes_init(unsigned long min, unsigned long max)
 	max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit);
 #endif
 #ifdef CONFIG_ZONE_DMA32
-	max_zone_pfns[ZONE_DMA32] = PFN_DOWN(arm64_dma32_phys_limit);
+	max_zone_pfns[ZONE_DMA32] = PFN_DOWN(dma32_phys_limit);
+	if (!arm64_dma_phys_limit)
+		arm64_dma_phys_limit = dma32_phys_limit;
 #endif
+	if (!arm64_dma_phys_limit)
+		arm64_dma_phys_limit = PHYS_MASK + 1;
 	max_zone_pfns[ZONE_NORMAL] = max;
 
 	free_area_init(max_zone_pfns);
@@ -394,16 +399,9 @@  void __init arm64_memblock_init(void)
 
 	early_init_fdt_scan_reserved_mem();
 
-	if (IS_ENABLED(CONFIG_ZONE_DMA32))
-		arm64_dma32_phys_limit = max_zone_phys(32);
-	else
-		arm64_dma32_phys_limit = PHYS_MASK + 1;
-
 	reserve_elfcorehdr();
 
 	high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
-
-	dma_contiguous_reserve(arm64_dma32_phys_limit);
 }
 
 void __init bootmem_init(void)
@@ -438,6 +436,11 @@  void __init bootmem_init(void)
 	sparse_init();
 	zone_sizes_init(min, max);
 
+	/*
+	 * Reserve the CMA area after arm64_dma_phys_limit was initialised.
+	 */
+	dma_contiguous_reserve(arm64_dma_phys_limit);
+
 	/*
 	 * request_standard_resources() depends on crashkernel's memory being
 	 * reserved, so do it here.
@@ -455,7 +458,7 @@  void __init bootmem_init(void)
 void __init mem_init(void)
 {
 	if (swiotlb_force == SWIOTLB_FORCE ||
-	    max_pfn > PFN_DOWN(arm64_dma_phys_limit ? : arm64_dma32_phys_limit))
+	    max_pfn > PFN_DOWN(arm64_dma_phys_limit))
 		swiotlb_init(1);
 	else
 		swiotlb_force = SWIOTLB_NO_FORCE;