• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_PAGE_SIZE_MIGRATION_INLINE_H
3 #define _LINUX_PAGE_SIZE_MIGRATION_INLINE_H
4 
5 /*
6  * Page Size Migration
7  *
8  * Copyright (c) 2024, Google LLC.
9  * Author: Kalesh Singh <kaleshsingh@goole.com>
10  *
11  * This file contains inline APIs for mitigations to ensure
12  * app compatibility during the transition from 4kB to 16kB
13  * page size in Android.
14  */
15 
16 #include <linux/mm_types.h>
17 #include <linux/sizes.h>
18 
19 #include <asm/page.h>
20 
21 /*
22  * vm_flags representation of VMA padding pages.
23  *
24  * This allows the kernel to identify the portion of an ELF LOAD segment VMA
25  * that is padding.
26  *
27  * 4 high bits of vm_flags [62,59] are used to represent ELF segment padding
28  * up to 60kB, which is sufficient for ELFs of both 16kB and 64kB segment
29  * alignment (p_align).
30  *
31  * The representation is illustrated below.
32  *
33  *                    62        61        60        59
34  *                _________ _________ _________ _________
35  *               |  Bit 3  |  Bit 2  |  Bit 1  |  Bit 0  |
36  *               | of  4kB | of  4kB | of  4kB | of  4kB |
37  *               |  chunks |  chunks |  chunks |  chunks |
38  *               |_________|_________|_________|_________|
39  *
40  * NOTE: Bit 63 is already used by mseal()
41  */
42 
43 #define VM_PAD_WIDTH		4
44 #define VM_PAD_SHIFT		(BITS_PER_LONG - VM_PAD_WIDTH - 1)
45 #define VM_TOTAL_PAD_PAGES	((1ULL << VM_PAD_WIDTH) - 1)
46 #define VM_PAD_MASK		(VM_TOTAL_PAD_PAGES << VM_PAD_SHIFT)
47 #define VMA_PAD_START(vma)	(vma->vm_end - (vma_pad_pages(vma) << PAGE_SHIFT))
48 
49 #if PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT)
50 /*
51  * Sets the correct padding bits / flags for a VMA split.
52  */
vma_pad_fixup_flags(struct vm_area_struct * vma,unsigned long newflags)53 static inline unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
54 						unsigned long newflags)
55 {
56 	if (newflags & VM_PAD_MASK)
57 		return (newflags & ~VM_PAD_MASK) | (vma->vm_flags & VM_PAD_MASK);
58 	else
59 		return newflags;
60 }
61 #else /* PAGE_SIZE != SZ_4K || !defined(CONFIG_64BIT) */
vma_pad_fixup_flags(struct vm_area_struct * vma,unsigned long newflags)62 static inline unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
63 						unsigned long newflags)
64 {
65 	return newflags;
66 }
67 #endif /* PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT) */
68 
69 #endif /* _LINUX_PAGE_SIZE_MIGRATION_INLINE_H */
70