Skip to content

Commit d50314a

Browse files
committed
arm64: Create non-empty ZONE_DMA when DRAM starts above 4GB
ZONE_DMA is created to allow 32-bit only devices to access memory in the absence of an IOMMU. On systems where the memory starts above 4GB, it is expected that some devices have a DMA offset hardwired to be able to access the bottom of the memory. Linux currently supports DT bindings for the DMA offsets but they are not (easily) available early during boot. This patch tries to guess a DMA offset and assumes that ZONE_DMA corresponds to the 32-bit mask above the start of DRAM. Fixes: 2d5a561 (arm64: Limit the CMA buffer to 32-bit if ZONE_DMA) Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Reported-by: Mark Salter <msalter@redhat.com> Tested-by: Mark Salter <msalter@redhat.com> Tested-by: Anup Patel <anup.patel@linaro.org>
1 parent fa2ec3e commit d50314a

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

arch/arm64/mm/init.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ static int __init early_initrd(char *p)
6060
early_param("initrd", early_initrd);
6161
#endif
6262

63+
/*
64+
* Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It
65+
* currently assumes that for memory starting above 4G, 32-bit devices will
66+
* use a DMA offset.
67+
*/
68+
static phys_addr_t max_zone_dma_phys(void)
69+
{
70+
phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32);
71+
return min(offset + (1ULL << 32), memblock_end_of_DRAM());
72+
}
73+
6374
static void __init zone_sizes_init(unsigned long min, unsigned long max)
6475
{
6576
struct memblock_region *reg;
@@ -70,9 +81,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
7081

7182
/* 4GB maximum for 32-bit only capable devices */
7283
if (IS_ENABLED(CONFIG_ZONE_DMA)) {
73-
unsigned long max_dma_phys =
74-
(unsigned long)(dma_to_phys(NULL, DMA_BIT_MASK(32)) + 1);
75-
max_dma = max(min, min(max, max_dma_phys >> PAGE_SHIFT));
84+
max_dma = PFN_DOWN(max_zone_dma_phys());
7685
zone_size[ZONE_DMA] = max_dma - min;
7786
}
7887
zone_size[ZONE_NORMAL] = max - max_dma;
@@ -146,7 +155,7 @@ void __init arm64_memblock_init(void)
146155

147156
/* 4GB maximum for 32-bit only capable devices */
148157
if (IS_ENABLED(CONFIG_ZONE_DMA))
149-
dma_phys_limit = dma_to_phys(NULL, DMA_BIT_MASK(32)) + 1;
158+
dma_phys_limit = max_zone_dma_phys();
150159
dma_contiguous_reserve(dma_phys_limit);
151160

152161
memblock_allow_resize();

0 commit comments

Comments
 (0)