Page size is the granularity at which an OS manages memory. Most CPUs today support a 4 KB page size and so the Android OS and apps have historically been built and optimized to run with a 4 KB page size. ARM CPUs support the larger 16 KB page size, and starting in Android 15, AOSP has support for building Android with a 16 KB page size as well. This option uses additional memory but improves system performance. As of Android 15, this option isn't enabled by default, but it is available as a developer mode or a developer option for OEMs and app developers to prepare for switching to 16 KB mode everywhere in the future.
Android 15 and higher have support for building
Android with a 16 KB ELF alignment, which works with 4 KB and
16 KB kernels starting with
android14-6.1
.
When used with a 16 KB kernel, this configuration uses additional memory
but improves system performance.
Set Android userspace to 16 KB
16 KB pages are only supported on arm64
targets with 16 KB kernels.
However, there is also an option to
simulate 16 KB userspace on x86_64
for Cuttlefish.
For arm64
targets, if you use
Kleaf
to build your kernel, --page_size=16k
builds the kernel in 16 KB mode.
If you are directly using Linux kernel configuration, you can select 16 KB
pages by setting CONFIG_ARM64_16K_PAGES
instead of CONFIG_ARM64_4K_PAGES
.
To enable 16 KB page size support in Android userspace, set the following build options on your product:
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
removes thePAGE_SIZE
define, and it makes components determine page size at runtime.PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
which ensures platform ELF files are built with 16 KB alignment. This larger-than-needed size is for future compatibility. With 16 KB ELF alignment, the kernel can support 4 KB/16 KB page sizes.
Verify build flags
After selecting the lunch
target, verify that the build flags are set up
correctly in the environment:
$ source build/envsetup.sh
$ lunch target
$ get_build_var TARGET_MAX_PAGE_SIZE_SUPPORTED
16384
$ get_build_var TARGET_NO_BIONIC_PAGE_SIZE_MACRO
true
If the previous two commands return 16384
and true
respectively, your build
flags are set up correctly to work with a 16 KB kernel. However, even if
a build passes, there might still be runtime issues due to differences in a
16 KB environment.
16 KB page size system programming
The vast majority of code on any Android-powered device doesn't directly deal with page size. However, for code that deals with pages, the kernel's memory allocation behavior changes, and you need to keep this in mind to write code that is not only compatible but also maximally performant and minimally resource intensive.
If you call mmap
on a 1 KB, 2 KB, or up to a 4 KB region on a
4 KB system, the system reserves 4 KB to implement this. In other
words, when requesting memory from the kernel, the kernel must always round up
the requested memory to the nearest page size. For example, if you allocate a
5 KB region on a 4 KB region, the kernel allocates 8 KB.
On a 16 KB kernel, these extra "tail ends" of pages are larger. For example, all of these allocations, from 1 KB to 5 KB would allocate 16 KB when used with a 16 KB kernel. If you request 17 KB, it allocates 32 KB.
For example, on a 4 KB system, it's okay to allocate two 4 KB read-write anonymous regions. However, on a 16 KB kernel, this would result in allocating two pages or 32 KB. On a 16 KB kernel, if possible, these regions can be combined into a single read or writeable page so that only 16 KB is used, wasting 8 KB compared to the 4 KB kernel case. To reduce even more memory usage, more pages can be combined. In fact, on a 16 KB system that is maximally optimized, 16 KB pages require less memory than 4 KB systems because the page table is one fourth the size for the same memory.
Whenever using mmap
, ensure that you round the size you are requesting up to
the nearest page size. This ensures that the entire amount of memory the kernel
allocates is directly visible to userspace in runtime values, instead of being
implicitly requested and implicitly or accidentally accessible.
Build shared libraries with 16 KB ELF alignment
To build shared libraries that are part of the android project, the earlier settings in Enable 16 KB page size are sufficient:
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
To build shared libraries that aren't part of android project, you need to pass this linker flag:
-Wl,-z,max-page-size=16384
Verify binaries and prebuilts for 16 KB ELF alignment
The best way to verify alignment and runtime behavior is to test and run on a 16 KB compiled kernel. However, in order to catch some issues earlier:
Starting in Android 16 (AOSP experimental), you can set
PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := true
at build time. Useignore_max_page_size: true
inAndroid.bp
andLOCAL_IGNORE_MAX_PAGE_SIZE := true
inAndroid.mk
to temporarily ignore them. These settings verify all prebuilts and allow you to detect when one is updated but is not 16 KB aligned.You can run
atest elf_alignment_test
which verifies the alignment of on-device ELF files on devices launching with Android 15 and later.