root/arch/arm/mm/pageattr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. change_page_range
  2. in_range
  3. change_memory_common
  4. set_memory_ro
  5. set_memory_rw
  6. set_memory_nx
  7. set_memory_x

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2014, The Linux Foundation. All rights reserved.
   4  */
   5 #include <linux/mm.h>
   6 #include <linux/module.h>
   7 
   8 #include <asm/pgtable.h>
   9 #include <asm/tlbflush.h>
  10 #include <asm/set_memory.h>
  11 
  12 struct page_change_data {
  13         pgprot_t set_mask;
  14         pgprot_t clear_mask;
  15 };
  16 
  17 static int change_page_range(pte_t *ptep, unsigned long addr, void *data)
  18 {
  19         struct page_change_data *cdata = data;
  20         pte_t pte = *ptep;
  21 
  22         pte = clear_pte_bit(pte, cdata->clear_mask);
  23         pte = set_pte_bit(pte, cdata->set_mask);
  24 
  25         set_pte_ext(ptep, pte, 0);
  26         return 0;
  27 }
  28 
  29 static bool in_range(unsigned long start, unsigned long size,
  30         unsigned long range_start, unsigned long range_end)
  31 {
  32         return start >= range_start && start < range_end &&
  33                 size <= range_end - start;
  34 }
  35 
  36 static int change_memory_common(unsigned long addr, int numpages,
  37                                 pgprot_t set_mask, pgprot_t clear_mask)
  38 {
  39         unsigned long start = addr & PAGE_MASK;
  40         unsigned long end = PAGE_ALIGN(addr) + numpages * PAGE_SIZE;
  41         unsigned long size = end - start;
  42         int ret;
  43         struct page_change_data data;
  44 
  45         WARN_ON_ONCE(start != addr);
  46 
  47         if (!size)
  48                 return 0;
  49 
  50         if (!in_range(start, size, MODULES_VADDR, MODULES_END) &&
  51             !in_range(start, size, VMALLOC_START, VMALLOC_END))
  52                 return -EINVAL;
  53 
  54         data.set_mask = set_mask;
  55         data.clear_mask = clear_mask;
  56 
  57         ret = apply_to_page_range(&init_mm, start, size, change_page_range,
  58                                         &data);
  59 
  60         flush_tlb_kernel_range(start, end);
  61         return ret;
  62 }
  63 
  64 int set_memory_ro(unsigned long addr, int numpages)
  65 {
  66         return change_memory_common(addr, numpages,
  67                                         __pgprot(L_PTE_RDONLY),
  68                                         __pgprot(0));
  69 }
  70 
  71 int set_memory_rw(unsigned long addr, int numpages)
  72 {
  73         return change_memory_common(addr, numpages,
  74                                         __pgprot(0),
  75                                         __pgprot(L_PTE_RDONLY));
  76 }
  77 
  78 int set_memory_nx(unsigned long addr, int numpages)
  79 {
  80         return change_memory_common(addr, numpages,
  81                                         __pgprot(L_PTE_XN),
  82                                         __pgprot(0));
  83 }
  84 
  85 int set_memory_x(unsigned long addr, int numpages)
  86 {
  87         return change_memory_common(addr, numpages,
  88                                         __pgprot(0),
  89                                         __pgprot(L_PTE_XN));
  90 }

/* [<][>][^][v][top][bottom][index][help] */