~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/loongarch/mm/pageattr.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Copyright (C) 2024 Loongson Technology Corporation Limited
  4  */
  5 
  6 #include <linux/pagewalk.h>
  7 #include <linux/pgtable.h>
  8 #include <asm/set_memory.h>
  9 #include <asm/tlbflush.h>
 10 
 11 struct pageattr_masks {
 12         pgprot_t set_mask;
 13         pgprot_t clear_mask;
 14 };
 15 
 16 static unsigned long set_pageattr_masks(unsigned long val, struct mm_walk *walk)
 17 {
 18         unsigned long new_val = val;
 19         struct pageattr_masks *masks = walk->private;
 20 
 21         new_val &= ~(pgprot_val(masks->clear_mask));
 22         new_val |= (pgprot_val(masks->set_mask));
 23 
 24         return new_val;
 25 }
 26 
 27 static int pageattr_pgd_entry(pgd_t *pgd, unsigned long addr,
 28                               unsigned long next, struct mm_walk *walk)
 29 {
 30         pgd_t val = pgdp_get(pgd);
 31 
 32         if (pgd_leaf(val)) {
 33                 val = __pgd(set_pageattr_masks(pgd_val(val), walk));
 34                 set_pgd(pgd, val);
 35         }
 36 
 37         return 0;
 38 }
 39 
 40 static int pageattr_p4d_entry(p4d_t *p4d, unsigned long addr,
 41                               unsigned long next, struct mm_walk *walk)
 42 {
 43         p4d_t val = p4dp_get(p4d);
 44 
 45         if (p4d_leaf(val)) {
 46                 val = __p4d(set_pageattr_masks(p4d_val(val), walk));
 47                 set_p4d(p4d, val);
 48         }
 49 
 50         return 0;
 51 }
 52 
 53 static int pageattr_pud_entry(pud_t *pud, unsigned long addr,
 54                               unsigned long next, struct mm_walk *walk)
 55 {
 56         pud_t val = pudp_get(pud);
 57 
 58         if (pud_leaf(val)) {
 59                 val = __pud(set_pageattr_masks(pud_val(val), walk));
 60                 set_pud(pud, val);
 61         }
 62 
 63         return 0;
 64 }
 65 
 66 static int pageattr_pmd_entry(pmd_t *pmd, unsigned long addr,
 67                               unsigned long next, struct mm_walk *walk)
 68 {
 69         pmd_t val = pmdp_get(pmd);
 70 
 71         if (pmd_leaf(val)) {
 72                 val = __pmd(set_pageattr_masks(pmd_val(val), walk));
 73                 set_pmd(pmd, val);
 74         }
 75 
 76         return 0;
 77 }
 78 
 79 static int pageattr_pte_entry(pte_t *pte, unsigned long addr,
 80                               unsigned long next, struct mm_walk *walk)
 81 {
 82         pte_t val = ptep_get(pte);
 83 
 84         val = __pte(set_pageattr_masks(pte_val(val), walk));
 85         set_pte(pte, val);
 86 
 87         return 0;
 88 }
 89 
 90 static int pageattr_pte_hole(unsigned long addr, unsigned long next,
 91                              int depth, struct mm_walk *walk)
 92 {
 93         return 0;
 94 }
 95 
 96 static const struct mm_walk_ops pageattr_ops = {
 97         .pgd_entry = pageattr_pgd_entry,
 98         .p4d_entry = pageattr_p4d_entry,
 99         .pud_entry = pageattr_pud_entry,
100         .pmd_entry = pageattr_pmd_entry,
101         .pte_entry = pageattr_pte_entry,
102         .pte_hole = pageattr_pte_hole,
103         .walk_lock = PGWALK_RDLOCK,
104 };
105 
106 static int __set_memory(unsigned long addr, int numpages, pgprot_t set_mask, pgprot_t clear_mask)
107 {
108         int ret;
109         unsigned long start = addr;
110         unsigned long end = start + PAGE_SIZE * numpages;
111         struct pageattr_masks masks = {
112                 .set_mask = set_mask,
113                 .clear_mask = clear_mask
114         };
115 
116         if (!numpages)
117                 return 0;
118 
119         mmap_write_lock(&init_mm);
120         ret = walk_page_range_novma(&init_mm, start, end, &pageattr_ops, NULL, &masks);
121         mmap_write_unlock(&init_mm);
122 
123         flush_tlb_kernel_range(start, end);
124 
125         return ret;
126 }
127 
128 int set_memory_x(unsigned long addr, int numpages)
129 {
130         if (addr < vm_map_base)
131                 return 0;
132 
133         return __set_memory(addr, numpages, __pgprot(0), __pgprot(_PAGE_NO_EXEC));
134 }
135 
136 int set_memory_nx(unsigned long addr, int numpages)
137 {
138         if (addr < vm_map_base)
139                 return 0;
140 
141         return __set_memory(addr, numpages, __pgprot(_PAGE_NO_EXEC), __pgprot(0));
142 }
143 
144 int set_memory_ro(unsigned long addr, int numpages)
145 {
146         if (addr < vm_map_base)
147                 return 0;
148 
149         return __set_memory(addr, numpages, __pgprot(0), __pgprot(_PAGE_WRITE | _PAGE_DIRTY));
150 }
151 
152 int set_memory_rw(unsigned long addr, int numpages)
153 {
154         if (addr < vm_map_base)
155                 return 0;
156 
157         return __set_memory(addr, numpages, __pgprot(_PAGE_WRITE | _PAGE_DIRTY), __pgprot(0));
158 }
159 
160 bool kernel_page_present(struct page *page)
161 {
162         pgd_t *pgd;
163         p4d_t *p4d;
164         pud_t *pud;
165         pmd_t *pmd;
166         pte_t *pte;
167         unsigned long addr = (unsigned long)page_address(page);
168 
169         if (addr < vm_map_base)
170                 return true;
171 
172         pgd = pgd_offset_k(addr);
173         if (pgd_none(pgdp_get(pgd)))
174                 return false;
175         if (pgd_leaf(pgdp_get(pgd)))
176                 return true;
177 
178         p4d = p4d_offset(pgd, addr);
179         if (p4d_none(p4dp_get(p4d)))
180                 return false;
181         if (p4d_leaf(p4dp_get(p4d)))
182                 return true;
183 
184         pud = pud_offset(p4d, addr);
185         if (pud_none(pudp_get(pud)))
186                 return false;
187         if (pud_leaf(pudp_get(pud)))
188                 return true;
189 
190         pmd = pmd_offset(pud, addr);
191         if (pmd_none(pmdp_get(pmd)))
192                 return false;
193         if (pmd_leaf(pmdp_get(pmd)))
194                 return true;
195 
196         pte = pte_offset_kernel(pmd, addr);
197         return pte_present(ptep_get(pte));
198 }
199 
200 int set_direct_map_default_noflush(struct page *page)
201 {
202         unsigned long addr = (unsigned long)page_address(page);
203 
204         if (addr < vm_map_base)
205                 return 0;
206 
207         return __set_memory(addr, 1, PAGE_KERNEL, __pgprot(0));
208 }
209 
210 int set_direct_map_invalid_noflush(struct page *page)
211 {
212         unsigned long addr = (unsigned long)page_address(page);
213 
214         if (addr < vm_map_base)
215                 return 0;
216 
217         return __set_memory(addr, 1, __pgprot(0), __pgprot(_PAGE_PRESENT | _PAGE_VALID));
218 }
219 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php