Reapply "ANDROID: arm64/mm: Add command line option to make ZONE_DMA32 empty"

This reverts commit 98de91adb1.

Bug: 372371001
Change-Id: I94d473d8f430a2f0364d30105f9ee3e78184686f
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
This commit is contained in:
Suren Baghdasaryan committed 2026-04-27 23:32:26 +00:00
1 parent 24eae7ee8e
commit fdba62342c
6 files changed
+82 -10

No files matched your search

@@ -1302,6 +1302,10 @@ Kernel parameters
can be useful when debugging issues that require an SLB
miss to occur.
disable_dma32= [KNL]
Dynamically disable ZONE_DMA32 on kernels compiled with
CONFIG_ZONE_DMA32=y.
disable= [IPV6]
See Documentation/networking/ipv6.rst.
+24 -3
View File
@@ -67,6 +67,12 @@ EXPORT_SYMBOL(memstart_addr);
*/
phys_addr_t __ro_after_init arm64_dma_phys_limit;
/*
* Provide a run-time mean of disabling ZONE_DMA32 if it is enabled via
* CONFIG_ZONE_DMA32.
*/
static bool disable_dma32 __ro_after_init;
/*
* To make optimal use of block mappings when laying out the linear
* mapping, round down the base of physical memory to a size that can
@@ -127,7 +133,8 @@ void __init arch_zone_limits_init(unsigned long *max_zone_pfns)
max_zone_pfns[ZONE_DMA] = PFN_DOWN(max_zone_phys(zone_dma_limit));
#endif
#ifdef CONFIG_ZONE_DMA32
max_zone_pfns[ZONE_DMA32] = PFN_DOWN(dma32_phys_limit);
if (!disable_dma32)
max_zone_pfns[ZONE_DMA32] = PFN_DOWN(dma32_phys_limit);
#endif
max_zone_pfns[ZONE_NORMAL] = max_pfn;
}
@@ -154,13 +161,27 @@ static void __init dma_limits_init(void)
arm64_dma_phys_limit = max_zone_phys(zone_dma_limit);
#endif
#ifdef CONFIG_ZONE_DMA32
if (!arm64_dma_phys_limit)
arm64_dma_phys_limit = dma32_phys_limit;
if (!disable_dma32) {
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;
}
static int __init early_disable_dma32(char *buf)
{
if (!buf)
return -EINVAL;
if (!strcmp(buf, "on"))
disable_dma32 = true;
return 0;
}
early_param("disable_dma32", early_disable_dma32);
int pfn_is_map_memory(unsigned long pfn)
{
phys_addr_t addr = PFN_PHYS(pfn);
+19 -1
View File
@@ -114,6 +114,12 @@ static unsigned long min_pfn_mapped;
static bool __initdata can_use_brk_pgt = true;
/*
* Provide a run-time mean of disabling ZONE_DMA32 if it is enabled via
* CONFIG_ZONE_DMA32.
*/
static bool disable_dma32 __ro_after_init;
/*
* Pages returned are already directly mapped.
*
@@ -1002,7 +1008,7 @@ void __init arch_zone_limits_init(unsigned long *max_zone_pfns)
max_zone_pfns[ZONE_DMA] = min(MAX_DMA_PFN, max_low_pfn);
#endif
#ifdef CONFIG_ZONE_DMA32
max_zone_pfns[ZONE_DMA32] = min(MAX_DMA32_PFN, max_low_pfn);
max_zone_pfns[ZONE_DMA32] = disable_dma32 ? 0 : min(MAX_DMA32_PFN, max_low_pfn);
#endif
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
#ifdef CONFIG_HIGHMEM
@@ -1010,6 +1016,18 @@ void __init arch_zone_limits_init(unsigned long *max_zone_pfns)
#endif
}
static int __init early_disable_dma32(char *buf)
{
if (!buf)
return -EINVAL;
if (!strcmp(buf, "on"))
disable_dma32 = true;
return 0;
}
early_param("disable_dma32", early_disable_dma32);
__visible DEFINE_PER_CPU_ALIGNED(struct tlb_state, cpu_tlbstate) = {
.loaded_mm = &init_mm,
.next_asid = 1,
+27
View File
@@ -23,6 +23,33 @@ struct bus_dma_region {
u64 size;
};
static inline bool zone_dma32_is_empty(int node)
{
#ifdef CONFIG_ZONE_DMA32
pg_data_t *pgdat = NODE_DATA(node);
return zone_is_empty(&pgdat->node_zones[ZONE_DMA32]);
#else
return true;
#endif
}
static inline bool zone_dma32_are_empty(void)
{
#ifdef CONFIG_NUMA
int node;
for_each_node(node)
if (!zone_dma32_is_empty(node))
return false;
#else
if (!zone_dma32_is_empty(numa_node_id()))
return false;
#endif
return true;
}
static inline dma_addr_t translate_phys_to_dma(struct device *dev,
phys_addr_t paddr)
{
+4 -2
View File
@@ -62,7 +62,8 @@ static gfp_t dma_direct_optimal_gfp_mask(struct device *dev, u64 *phys_limit)
*phys_limit = dma_to_phys(dev, dma_limit);
if (*phys_limit <= zone_dma_limit)
return GFP_DMA;
if (*phys_limit <= DMA_BIT_MASK(32))
if (*phys_limit <= DMA_BIT_MASK(32) &&
!zone_dma32_are_empty())
return GFP_DMA32;
return 0;
}
@@ -144,7 +145,8 @@ static struct page *__dma_direct_alloc_pages(struct device *dev, size_t size,
if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
phys_limit < DMA_BIT_MASK(64) &&
!(gfp & (GFP_DMA32 | GFP_DMA)))
!(gfp & (GFP_DMA32 | GFP_DMA)) &&
!zone_dma32_are_empty())
gfp |= GFP_DMA32;
else if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA))
gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
+4 -4
View File
@@ -71,7 +71,7 @@ static bool cma_in_zone(gfp_t gfp)
end = cma_get_base(cma) + size - 1;
if (IS_ENABLED(CONFIG_ZONE_DMA) && (gfp & GFP_DMA))
return end <= zone_dma_limit;
if (IS_ENABLED(CONFIG_ZONE_DMA32) && (gfp & GFP_DMA32))
if (IS_ENABLED(CONFIG_ZONE_DMA32) && (gfp & GFP_DMA32) && !zone_dma32_are_empty())
return end <= max(DMA_BIT_MASK(32), zone_dma_limit);
return true;
}
@@ -153,7 +153,7 @@ static void atomic_pool_work_fn(struct work_struct *work)
if (IS_ENABLED(CONFIG_ZONE_DMA))
atomic_pool_resize(atomic_pool_dma,
GFP_KERNEL | GFP_DMA);
if (IS_ENABLED(CONFIG_ZONE_DMA32))
if (IS_ENABLED(CONFIG_ZONE_DMA32) && !zone_dma32_are_empty())
atomic_pool_resize(atomic_pool_dma32,
GFP_KERNEL | GFP_DMA32);
atomic_pool_resize(atomic_pool_kernel, GFP_KERNEL);
@@ -218,7 +218,7 @@ static int __init dma_atomic_pool_init(void)
if (!atomic_pool_dma)
ret = -ENOMEM;
}
if (has_managed_dma32) {
if (has_managed_dma32 && !zone_dma32_are_empty()) {
atomic_pool_dma32 = __dma_atomic_pool_init(atomic_pool_size,
GFP_KERNEL | GFP_DMA32);
if (!atomic_pool_dma32)
@@ -235,7 +235,7 @@ static inline struct gen_pool *dma_guess_pool(struct gen_pool *prev, gfp_t gfp)
if (prev == NULL) {
if (gfp & GFP_DMA)
return atomic_pool_dma ?: atomic_pool_dma32 ?: atomic_pool_kernel;
if (gfp & GFP_DMA32)
if ((gfp & GFP_DMA32) && !zone_dma32_are_empty())
return atomic_pool_dma32 ?: atomic_pool_dma ?: atomic_pool_kernel;
return atomic_pool_kernel ?: atomic_pool_dma32 ?: atomic_pool_dma;
}