From 1fb2de0c3d3ab1bb6243bfc8ad04474ceee20d41 Mon Sep 17 00:00:00 2001 From: Kalesh Singh Date: Mon, 5 Feb 2024 11:12:46 -0800 Subject: [PATCH] ANDROID: 16K: Add page-compat helper macros Add page-compat macros are namespace-prefixed by __ and otherwise named the same as their not-page-compat counter parts. Page-compat mode is disabled by default; it can be enabled by setting kernel boot parmeter, androidboot.page_shift= androidboot.page_shift is only supported on kernels with a base page-size of 4KB. The valid range of androidboot.page_shift is [13, 16]. In other words page sizes of 8KB, 16KB, 32KB and 64KB can be emulated. Bug: 383389337 Bug: 315325080 Bug: 302403436 Change-Id: I2f7fca417313652139ef21ac25c2b31080988c5b Signed-off-by: Kalesh Singh --- include/linux/page_size_compat.h | 47 ++++++++++++++++++++++++++++++++ mm/Makefile | 3 +- mm/page_size_compat.c | 41 ++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 include/linux/page_size_compat.h create mode 100644 mm/page_size_compat.c diff --git a/include/linux/page_size_compat.h b/include/linux/page_size_compat.h new file mode 100644 index 000000000000..c30fa771f625 --- /dev/null +++ b/include/linux/page_size_compat.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_PAGE_SIZE_COMPAT_H +#define __LINUX_PAGE_SIZE_COMPAT_H + +/* + * include/linux/page_size_compat.h + * + * Page Size Emulation + * + * Copyright (c) 2024, Google LLC. + * Author: Kalesh Singh + + * Helper macros for page size emulation. + * + * The macros for use with the emulated page size are all + * namespaced by the prefix '__'. + * + * The valid range of androidboot.page_shift is [13, 16]. + * In other words page sizes of 8KB, 16KB, 32KB and 64KB can + * be emulated. + */ + +#include + +#include +#include + +DECLARE_STATIC_KEY_FALSE(page_shift_compat_enabled); +extern int page_shift_compat __ro_after_init; + +static __always_inline unsigned __page_shift(void) +{ + if (static_branch_unlikely(&page_shift_compat_enabled)) + return page_shift_compat; + else + return PAGE_SHIFT; +} + +#define __PAGE_SHIFT __page_shift() +#define __PAGE_SIZE (_AC(1,UL) << __PAGE_SHIFT) +#define __PAGE_MASK (~(__PAGE_SIZE-1)) +#define __PAGE_ALIGN(addr) ALIGN(addr, __PAGE_SIZE) +#define __PAGE_ALIGN_DOWN(addr) ALIGN_DOWN(addr, __PAGE_SIZE) +#define __PAGE_ALIGNED(addr) IS_ALIGNED((unsigned long)(addr), __PAGE_SIZE) +#define __offset_in_page(p) ((unsigned long)(p) & ~__PAGE_MASK) + +#endif /* __LINUX_PAGE_SIZE_COMPAT_H */ diff --git a/mm/Makefile b/mm/Makefile index 3ceafdeacac3..f828f8cef79c 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -55,7 +55,8 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ mm_init.o percpu.o slab_common.o \ compaction.o show_mem.o \ interval_tree.o list_lru.o workingset.o \ - debug.o gup.o mmap_lock.o $(mmu-y) + debug.o gup.o mmap_lock.o $(mmu-y) \ + page_size_compat.o # Give 'page_alloc' its own module-parameter namespace page-alloc-y := page_alloc.o diff --git a/mm/page_size_compat.c b/mm/page_size_compat.c new file mode 100644 index 000000000000..5cb3e9d3d07b --- /dev/null +++ b/mm/page_size_compat.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Page Size Emulation + * + * Copyright (c) 2024, Google LLC. + * Author: Kalesh Singh + */ + +#include +#include +#include +#include + +#define MIN_PAGE_SHIFT_COMPAT (PAGE_SHIFT + 1) +#define MAX_PAGE_SHIFT_COMPAT 16 /* Max of 64KB */ + +DEFINE_STATIC_KEY_FALSE(page_shift_compat_enabled); + +int page_shift_compat __ro_after_init = MIN_PAGE_SHIFT_COMPAT; + +static int __init early_page_shift_compat(char *buf) +{ + int ret; + + ret = kstrtoint(buf, 10, &page_shift_compat); + if (ret) + return ret; + + /* Only supported on 4KB kernel */ + if (PAGE_SHIFT != 12) + return -ENOTSUPP; + + if (page_shift_compat < MIN_PAGE_SHIFT_COMPAT || + page_shift_compat > MAX_PAGE_SHIFT_COMPAT) + return -EINVAL; + + static_branch_enable(&page_shift_compat_enabled); + + return 0; +} +early_param("androidboot.page_shift", early_page_shift_compat);