pageattr.c 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*
  2. * Copyright IBM Corp. 2011
  3. * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
  4. */
  5. #include <linux/module.h>
  6. #include <linux/mm.h>
  7. #include <linux/hugetlb.h>
  8. #include <asm/cacheflush.h>
  9. #include <asm/pgtable.h>
  10. static pte_t *walk_page_table(unsigned long addr)
  11. {
  12. pgd_t *pgdp;
  13. pud_t *pudp;
  14. pmd_t *pmdp;
  15. pte_t *ptep;
  16. pgdp = pgd_offset_k(addr);
  17. if (pgd_none(*pgdp))
  18. return NULL;
  19. pudp = pud_offset(pgdp, addr);
  20. if (pud_none(*pudp))
  21. return NULL;
  22. pmdp = pmd_offset(pudp, addr);
  23. if (pmd_none(*pmdp) || pmd_large(*pmdp))
  24. return NULL;
  25. ptep = pte_offset_kernel(pmdp, addr);
  26. if (pte_none(*ptep))
  27. return NULL;
  28. return ptep;
  29. }
  30. static void change_page_attr(unsigned long addr, int numpages,
  31. pte_t (*set) (pte_t))
  32. {
  33. pte_t *ptep, pte;
  34. int i;
  35. for (i = 0; i < numpages; i++) {
  36. ptep = walk_page_table(addr);
  37. if (WARN_ON_ONCE(!ptep))
  38. break;
  39. pte = *ptep;
  40. pte = set(pte);
  41. __ptep_ipte(addr, ptep);
  42. *ptep = pte;
  43. addr += PAGE_SIZE;
  44. }
  45. }
  46. int set_memory_ro(unsigned long addr, int numpages)
  47. {
  48. change_page_attr(addr, numpages, pte_wrprotect);
  49. return 0;
  50. }
  51. int set_memory_rw(unsigned long addr, int numpages)
  52. {
  53. change_page_attr(addr, numpages, pte_mkwrite);
  54. return 0;
  55. }
  56. /* not possible */
  57. int set_memory_nx(unsigned long addr, int numpages)
  58. {
  59. return 0;
  60. }
  61. int set_memory_x(unsigned long addr, int numpages)
  62. {
  63. return 0;
  64. }