[PATCH 04/11] mm: percpu: prepare to use dedicated percpu area
Yang Shi
yang at os.amperecomputing.com
Wed Apr 29 10:04:32 PDT 2026
The percpu variables are allocated from vmalloc area by default. The
architectures which support local percpu map will allocate percpu
variables from dedicated percpu area, for example, ARM64.
Introduce a new kernel config, CONFIG_HAVE_LOCAL_PER_CPU_MAP. The
architectures which support local percpu map will need to select it. If
it is enabled, allocate percpu variables from the dedicated percpu area.
Signed-off-by: Yang Shi <yang at os.amperecomputing.com>
---
mm/Kconfig | 3 +++
mm/percpu.c | 6 ++++++
mm/vmalloc.c | 20 +++++++++++++++++---
3 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/mm/Kconfig b/mm/Kconfig
index e8bf1e9e6ad9..ccdf58b63fb8 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -1022,6 +1022,9 @@ config NEED_PER_CPU_PAGE_FIRST_CHUNK
config USE_PERCPU_NUMA_NODE_ID
bool
+config HAVE_LOCAL_PER_CPU_MAP
+ bool
+
config HAVE_SETUP_PER_CPU_AREA
bool
diff --git a/mm/percpu.c b/mm/percpu.c
index b0676b8054ed..daa2c88e6971 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -3243,9 +3243,15 @@ int __init pcpu_page_first_chunk(size_t reserved_size, pcpu_fc_cpu_to_node_fn_t
}
/* allocate vm area, map the pages and copy static data */
+#ifdef CONFIG_HAVE_LOCAL_PER_CPU_MAP
+ vm.addr = (void *)ALIGN(PERCPU_START, PAGE_SIZE);
+ vm.size = num_possible_cpus() * ai->unit_size;
+ vm_area_add_early(&vm);
+#else
vm.flags = VM_ALLOC;
vm.size = num_possible_cpus() * ai->unit_size;
vm_area_register_early(&vm, PAGE_SIZE);
+#endif
for (unit = 0; unit < num_possible_cpus(); unit++) {
unsigned long unit_addr =
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index aa08651ec0df..068a6709062d 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -4841,9 +4841,15 @@ pvm_find_va_enclose_addr(unsigned long addr)
static unsigned long
pvm_determine_end_from_reverse(struct vmap_area **va, unsigned long align)
{
- unsigned long vmalloc_end = VMALLOC_END & ~(align - 1);
+ unsigned long vmalloc_end;
unsigned long addr;
+#ifdef CONFIG_HAVE_LOCAL_PER_CPU_MAP
+ vmalloc_end = PERCPU_END & ~(align - 1);
+#else
+ vmalloc_end = VMALLOC_END & ~(align - 1);
+#endif
+
if (likely(*va)) {
list_for_each_entry_from_reverse((*va),
&free_vmap_area_list, list) {
@@ -4884,14 +4890,22 @@ struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
const size_t *sizes, int nr_vms,
size_t align)
{
- const unsigned long vmalloc_start = ALIGN(VMALLOC_START, align);
- const unsigned long vmalloc_end = VMALLOC_END & ~(align - 1);
+ unsigned long vmalloc_start;
+ unsigned long vmalloc_end;
struct vmap_area **vas, *va;
struct vm_struct **vms;
int area, area2, last_area, term_area;
unsigned long base, start, size, end, last_end, orig_start, orig_end;
bool purged = false;
+#ifdef CONFIG_HAVE_LOCAL_PER_CPU_MAP
+ vmalloc_start = ALIGN(PERCPU_START, align);
+ vmalloc_end = PERCPU_END & ~(align - 1);
+#else
+ vmalloc_start = ALIGN(VMALLOC_START, align);
+ vmalloc_end = VMALLOC_END & ~(align - 1);
+#endif
+
/* verify parameters and allocate data structures */
BUG_ON(offset_in_page(align) || !is_power_of_2(align));
for (last_area = 0, area = 0; area < nr_vms; area++) {
--
2.47.0
More information about the linux-arm-kernel
mailing list