Skip to content

Commit 1a8e1ce

Browse files
Nicolas Saenz Juliennectmarinas
authored andcommitted
arm64: use both ZONE_DMA and ZONE_DMA32
So far all arm64 devices have supported 32 bit DMA masks for their peripherals. This is not true anymore for the Raspberry Pi 4 as most of it's peripherals can only address the first GB of memory on a total of up to 4 GB. This goes against ZONE_DMA32's intent, as it's expected for ZONE_DMA32 to be addressable with a 32 bit mask. So it was decided to re-introduce ZONE_DMA in arm64. ZONE_DMA will contain the lower 1G of memory, which is currently the memory area addressable by any peripheral on an arm64 device. ZONE_DMA32 will contain the rest of the 32 bit addressable memory. Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent a573cdd commit 1a8e1ce

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

arch/arm64/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,10 @@ config GENERIC_CSUM
266266
config GENERIC_CALIBRATE_DELAY
267267
def_bool y
268268

269+
config ZONE_DMA
270+
bool "Support DMA zone" if EXPERT
271+
default y
272+
269273
config ZONE_DMA32
270274
bool "Support DMA32 zone" if EXPERT
271275
default y

arch/arm64/include/asm/page.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,6 @@ extern int pfn_valid(unsigned long);
3838

3939
#include <asm-generic/getorder.h>
4040

41+
#define ARCH_ZONE_DMA_BITS 30
42+
4143
#endif

arch/arm64/mm/init.c

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ EXPORT_SYMBOL(physvirt_offset);
5656
struct page *vmemmap __ro_after_init;
5757
EXPORT_SYMBOL(vmemmap);
5858

59+
/*
60+
* We create both ZONE_DMA and ZONE_DMA32. ZONE_DMA covers the first 1G of
61+
* memory as some devices, namely the Raspberry Pi 4, have peripherals with
62+
* this limited view of the memory. ZONE_DMA32 will cover the rest of the 32
63+
* bit addressable memory area.
64+
*/
65+
phys_addr_t arm64_dma_phys_limit __ro_after_init;
5966
phys_addr_t arm64_dma32_phys_limit __ro_after_init;
6067

6168
#ifdef CONFIG_KEXEC_CORE
@@ -169,15 +176,16 @@ static void __init reserve_elfcorehdr(void)
169176
{
170177
}
171178
#endif /* CONFIG_CRASH_DUMP */
179+
172180
/*
173-
* Return the maximum physical address for ZONE_DMA32 (DMA_BIT_MASK(32)). It
174-
* currently assumes that for memory starting above 4G, 32-bit devices will
175-
* use a DMA offset.
181+
* Return the maximum physical address for a zone with a given address size
182+
* limit. It currently assumes that for memory starting above 4G, 32-bit
183+
* devices will use a DMA offset.
176184
*/
177-
static phys_addr_t __init max_zone_dma32_phys(void)
185+
static phys_addr_t __init max_zone_phys(unsigned int zone_bits)
178186
{
179-
phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32);
180-
return min(offset + (1ULL << 32), memblock_end_of_DRAM());
187+
phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, zone_bits);
188+
return min(offset + (1ULL << zone_bits), memblock_end_of_DRAM());
181189
}
182190

183191
#ifdef CONFIG_NUMA
@@ -186,6 +194,9 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
186194
{
187195
unsigned long max_zone_pfns[MAX_NR_ZONES] = {0};
188196

197+
#ifdef CONFIG_ZONE_DMA
198+
max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit);
199+
#endif
189200
#ifdef CONFIG_ZONE_DMA32
190201
max_zone_pfns[ZONE_DMA32] = PFN_DOWN(arm64_dma32_phys_limit);
191202
#endif
@@ -201,13 +212,18 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
201212
struct memblock_region *reg;
202213
unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
203214
unsigned long max_dma32 = min;
215+
unsigned long max_dma = min;
204216

205217
memset(zone_size, 0, sizeof(zone_size));
206218

207-
/* 4GB maximum for 32-bit only capable devices */
219+
#ifdef CONFIG_ZONE_DMA
220+
max_dma = PFN_DOWN(arm64_dma_phys_limit);
221+
zone_size[ZONE_DMA] = max_dma - min;
222+
max_dma32 = max_dma;
223+
#endif
208224
#ifdef CONFIG_ZONE_DMA32
209225
max_dma32 = PFN_DOWN(arm64_dma32_phys_limit);
210-
zone_size[ZONE_DMA32] = max_dma32 - min;
226+
zone_size[ZONE_DMA32] = max_dma32 - max_dma;
211227
#endif
212228
zone_size[ZONE_NORMAL] = max - max_dma32;
213229

@@ -219,11 +235,17 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
219235

220236
if (start >= max)
221237
continue;
222-
238+
#ifdef CONFIG_ZONE_DMA
239+
if (start < max_dma) {
240+
unsigned long dma_end = min_not_zero(end, max_dma);
241+
zhole_size[ZONE_DMA] -= dma_end - start;
242+
}
243+
#endif
223244
#ifdef CONFIG_ZONE_DMA32
224245
if (start < max_dma32) {
225-
unsigned long dma_end = min(end, max_dma32);
226-
zhole_size[ZONE_DMA32] -= dma_end - start;
246+
unsigned long dma32_end = min(end, max_dma32);
247+
unsigned long dma32_start = max(start, max_dma);
248+
zhole_size[ZONE_DMA32] -= dma32_end - dma32_start;
227249
}
228250
#endif
229251
if (end > max_dma32) {
@@ -418,9 +440,11 @@ void __init arm64_memblock_init(void)
418440

419441
early_init_fdt_scan_reserved_mem();
420442

421-
/* 4GB maximum for 32-bit only capable devices */
443+
if (IS_ENABLED(CONFIG_ZONE_DMA))
444+
arm64_dma_phys_limit = max_zone_phys(ARCH_ZONE_DMA_BITS);
445+
422446
if (IS_ENABLED(CONFIG_ZONE_DMA32))
423-
arm64_dma32_phys_limit = max_zone_dma32_phys();
447+
arm64_dma32_phys_limit = max_zone_phys(32);
424448
else
425449
arm64_dma32_phys_limit = PHYS_MASK + 1;
426450

@@ -430,7 +454,7 @@ void __init arm64_memblock_init(void)
430454

431455
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
432456

433-
dma_contiguous_reserve(arm64_dma32_phys_limit);
457+
dma_contiguous_reserve(arm64_dma_phys_limit ? : arm64_dma32_phys_limit);
434458
}
435459

436460
void __init bootmem_init(void)
@@ -534,7 +558,7 @@ static void __init free_unused_memmap(void)
534558
void __init mem_init(void)
535559
{
536560
if (swiotlb_force == SWIOTLB_FORCE ||
537-
max_pfn > (arm64_dma32_phys_limit >> PAGE_SHIFT))
561+
max_pfn > PFN_DOWN(arm64_dma_phys_limit ? : arm64_dma32_phys_limit))
538562
swiotlb_init(1);
539563
else
540564
swiotlb_force = SWIOTLB_NO_FORCE;

0 commit comments

Comments
 (0)