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=<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 <kaleshsingh@google.com>
This commit is contained in:
Kalesh Singh
2024-02-05 11:12:46 -08:00
committed by Carlos Llamas
parent a052d19e1c
commit 1fb2de0c3d
3 changed files with 90 additions and 1 deletions

View File

@@ -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 <kaleshsingh@goole.com>
* 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 <asm/page.h>
#include <linux/align.h>
#include <linux/jump_label.h>
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 */

View File

@@ -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

41
mm/page_size_compat.c Normal file
View File

@@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Page Size Emulation
*
* Copyright (c) 2024, Google LLC.
* Author: Kalesh Singh <kaleshsingh@goole.com>
*/
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kstrtox.h>
#include <linux/page_size_compat.h>
#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);