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)53static 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)62static 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