Commit 13d01786 authored by Kefeng Wang's avatar Kefeng Wang
Browse files

mm: huge_memory: add folio_get_unmapped_area()

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I9Q9DF


CVE: NA

-------------------------------------------------

The mmap() already supports align an mmap address by the PMD size, add a
folio_get_unmapped_area() to be align other page size, eg, 64K on arm64,
which could increase the probability of the specific order of large
folio, that is, try the best to allocate 64K, also it may reduce more TLB
miss, experimental.

Signed-off-by: default avatarKefeng Wang <wangkefeng.wang@huawei.com>
parent c64beef7
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
@@ -887,6 +887,52 @@ static unsigned long __thp_get_unmapped_area(struct file *filp,
	return ret;
}

static bool file_mapping_align_enabled(struct file *filp)
{
	struct address_space *mapping;

	if (!filp)
		return false;

	mapping = filp->f_mapping;
	if (!mapping || !mapping_large_folio_support(mapping))
		return false;

	return true;
}

static bool anon_mapping_align_enabled(int order)
{
	unsigned long mask;

	mask = READ_ONCE(huge_anon_orders_always) |
	       READ_ONCE(huge_anon_orders_madvise);

	if (hugepage_global_enabled())
		mask |= READ_ONCE(huge_anon_orders_inherit);

	mask = BIT(order) & mask;
	if (!mask)
		return false;

	return true;
}

static unsigned long folio_get_unmapped_area(struct file *filp, unsigned long addr,
		unsigned long len, unsigned long pgoff, unsigned long flags)
{
	int order = arch_wants_exec_folio_order();

	if (order < 0)
		return 0;

	if (file_mapping_align_enabled(filp) ||
		(!filp && anon_mapping_align_enabled(order)))
		return __thp_get_unmapped_area(filp, addr, len, pgoff, flags,
					       PAGE_SIZE << order);
	return 0;
}

unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
		unsigned long len, unsigned long pgoff, unsigned long flags)
{
@@ -897,6 +943,10 @@ unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
	if (ret)
		return ret;

	ret = folio_get_unmapped_area(filp, addr, len, off, flags);
	if (ret)
		return ret;

	return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
}
EXPORT_SYMBOL_GPL(thp_get_unmapped_area);