diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/mm/pageattr.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 55f5b5cdb12e..c54832b75069 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -282,6 +282,45 @@ static int change_page_attr_addr(unsigned long address, pgprot_t prot) | |||
282 | return err; | 282 | return err; |
283 | } | 283 | } |
284 | 284 | ||
285 | static int __change_page_attr_set_clr(unsigned long addr, int numpages, | ||
286 | pgprot_t mask_set, pgprot_t mask_clr) | ||
287 | { | ||
288 | pgprot_t new_prot; | ||
289 | int level; | ||
290 | pte_t *pte; | ||
291 | int i, ret; | ||
292 | |||
293 | for (i = 0; i < numpages ; i++) { | ||
294 | |||
295 | pte = lookup_address(addr, &level); | ||
296 | if (!pte) | ||
297 | return -EINVAL; | ||
298 | |||
299 | new_prot = pte_pgprot(*pte); | ||
300 | |||
301 | pgprot_val(new_prot) &= ~pgprot_val(mask_clr); | ||
302 | pgprot_val(new_prot) |= pgprot_val(mask_set); | ||
303 | |||
304 | ret = change_page_attr_addr(addr, new_prot); | ||
305 | if (ret) | ||
306 | return ret; | ||
307 | addr += PAGE_SIZE; | ||
308 | } | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int change_page_attr_set_clr(unsigned long addr, int numpages, | ||
314 | pgprot_t mask_set, pgprot_t mask_clr) | ||
315 | { | ||
316 | int ret = __change_page_attr_set_clr(addr, numpages, mask_set, | ||
317 | mask_clr); | ||
318 | |||
319 | global_flush_tlb(); | ||
320 | |||
321 | return ret; | ||
322 | } | ||
323 | |||
285 | /** | 324 | /** |
286 | * change_page_attr_set - Change page table attributes in the linear mapping. | 325 | * change_page_attr_set - Change page table attributes in the linear mapping. |
287 | * @addr: Virtual address in linear mapping. | 326 | * @addr: Virtual address in linear mapping. |