From: Yang Shi <yang@os.amperecomputing.com>
To: cl@gentwo.org, dennis@kernel.org, tj@kernel.org,
urezki@gmail.com, catalin.marinas@arm.com, will@kernel.org,
ryan.roberts@arm.com, david@kernel.org,
akpm@linux-foundation.org, hca@linux.ibm.com, gor@linux.ibm.com,
agordeev@linux.ibm.com
Cc: yang@os.amperecomputing.com, linux-mm@kvack.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: [PATCH 10/16] mm: percpu: prepare to use dedicated percpu area
Date: Wed, 15 Jul 2026 11:04:12 -0700 [thread overview]
Message-ID: <20260715180455.515692-11-yang@os.amperecomputing.com> (raw)
In-Reply-To: <20260715180455.515692-1-yang@os.amperecomputing.com>
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.
But still treat percpu area address as vmalloc address.
Signed-off-by: Yang Shi <yang@os.amperecomputing.com>
---
include/linux/mm.h | 11 +++++++++++
mm/Kconfig | 3 +++
mm/percpu.c | 8 ++++++++
mm/vmalloc.c | 23 ++++++++++++++++++++---
4 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 485df9c2dbdd..c8c3800fbd9f 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1858,6 +1858,17 @@ unsigned long vmalloc_to_pfn(const void *addr);
#ifdef CONFIG_MMU
extern bool is_vmalloc_addr(const void *x);
extern int is_vmalloc_or_module_addr(const void *x);
+#ifdef CONFIG_HAVE_LOCAL_PER_CPU_MAP
+static inline bool is_percpu_addr(unsigned long addr)
+{
+ return addr >= PERCPU_START && addr < LOCAL_PERCPU_END;
+}
+#else
+static inline bool is_percpu_addr(unsigned long addr)
+{
+ return false;
+}
+#endif
#else
static inline bool is_vmalloc_addr(const void *x)
{
diff --git a/mm/Kconfig b/mm/Kconfig
index 13ea4b29ee7b..e1910c332638 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -1061,6 +1061,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 45c30c6531c5..b27828602c32 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -3243,9 +3243,17 @@ 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.flags = VM_ALLOC;
+ vm.addr = (void *)ALIGN(PERCPU_START, PAGE_SIZE);
+ vm.size = num_possible_cpus() * ai->unit_size;
+ vm_area_add_early(&vm);
+ kasan_populate_early_vm_area_shadow(vm.addr, vm.size);
+#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 17c26e9796b2..9ec401918736 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -80,6 +80,9 @@ bool is_vmalloc_addr(const void *x)
{
unsigned long addr = (unsigned long)kasan_reset_tag(x);
+ if (is_percpu_addr(addr))
+ return true;
+
return addr >= VMALLOC_START && addr < VMALLOC_END;
}
EXPORT_SYMBOL(is_vmalloc_addr);
@@ -4926,9 +4929,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) {
@@ -4969,14 +4978,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
next prev parent reply other threads:[~2026-07-15 18:06 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-15 18:04 [RFC v2 PATCH 0/16] Optimize this_cpu_*() ops for non-x86 (ARM64 for this series) Yang Shi
2026-07-15 18:04 ` [PATCH 01/16] drivers: arch_numa: move percpu set up code to arch Yang Shi
2026-07-15 18:04 ` [PATCH 02/16] arm64: kconfig: make percpu related configs not depend on NUMA Yang Shi
2026-07-15 18:04 ` [PATCH 03/16] mm: pgalloc: introduce {pud|pmd}_populate_sync() Yang Shi
2026-07-15 18:04 ` [PATCH 04/16] vmalloc: pass in pgd pointer for vmap{__vunmap}_range_noflush() Yang Shi
2026-07-15 18:04 ` [PATCH 05/16] arm64: mm: enable percpu kernel page table Yang Shi
2026-07-15 18:04 ` [PATCH 06/16] arm64: mm: defined {pud|pmd}_populate_sync() Yang Shi
2026-07-15 18:04 ` [PATCH 07/16] arm64: mm: sync percpu page table for memory hotplug/unplug Yang Shi
2026-07-15 18:04 ` [PATCH 08/16] arm64: kasan: sync up kasan shadow area page table Yang Shi
2026-07-15 18:04 ` [PATCH 09/16] arm64: mm: define percpu virtual space area Yang Shi
2026-07-15 18:04 ` Yang Shi [this message]
2026-07-15 18:04 ` [PATCH 11/16] arm64: mm: map local percpu first chunk Yang Shi
2026-07-15 18:04 ` [PATCH 12/16] mm: percpu: set up first chunk and reserve chunk Yang Shi
2026-07-15 18:04 ` [PATCH 13/16] arm64: mm: introduce __per_cpu_local_off Yang Shi
2026-07-15 18:04 ` [PATCH 14/16] mm: percpu: allocate and free local percpu vm area Yang Shi
2026-07-15 18:04 ` [PATCH 15/16] arm64: kconfig: select HAVE_LOCAL_PER_CPU_MAP Yang Shi
2026-07-15 18:04 ` [PATCH 16/16] arm64: percpu: use local percpu for this_cpu_*() APIs Yang Shi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260715180455.515692-11-yang@os.amperecomputing.com \
--to=yang@os.amperecomputing.com \
--cc=agordeev@linux.ibm.com \
--cc=akpm@linux-foundation.org \
--cc=catalin.marinas@arm.com \
--cc=cl@gentwo.org \
--cc=david@kernel.org \
--cc=dennis@kernel.org \
--cc=gor@linux.ibm.com \
--cc=hca@linux.ibm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ryan.roberts@arm.com \
--cc=tj@kernel.org \
--cc=urezki@gmail.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.