Skip to content

Commit

Permalink
arm64: Create non-empty ZONE_DMA when DRAM starts above 4GB
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Catalin Marinas committed Jul 23, 2014
1 parent fa2ec3e commit d50314a
Showing 1 changed file with 13 additions and 4 deletions.
17 changes: 13 additions & 4 deletions arch/arm64/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ static int __init early_initrd(char *p)
early_param("initrd", early_initrd);
#endif

/*
* Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It
* currently assumes that for memory starting above 4G, 32-bit devices will
* use a DMA offset.
*/
static phys_addr_t max_zone_dma_phys(void)
{
phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32);
return min(offset + (1ULL << 32), memblock_end_of_DRAM());
}

static void __init zone_sizes_init(unsigned long min, unsigned long max)
{
struct memblock_region *reg;
Expand All @@ -70,9 +81,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)

/* 4GB maximum for 32-bit only capable devices */
if (IS_ENABLED(CONFIG_ZONE_DMA)) {
unsigned long max_dma_phys =
(unsigned long)(dma_to_phys(NULL, DMA_BIT_MASK(32)) + 1);
max_dma = max(min, min(max, max_dma_phys >> PAGE_SHIFT));
max_dma = PFN_DOWN(max_zone_dma_phys());
zone_size[ZONE_DMA] = max_dma - min;
}
zone_size[ZONE_NORMAL] = max - max_dma;
Expand Down Expand Up @@ -146,7 +155,7 @@ void __init arm64_memblock_init(void)

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

memblock_allow_resize();
Expand Down

0 comments on commit d50314a

Please sign in to comment.