pgtable.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <asm/pgalloc.h>
  3. #include <linux/gfp.h>
  4. #include <linux/kernel.h>
  5. #include <linux/pgtable.h>
  6. int ptep_set_access_flags(struct vm_area_struct *vma,
  7. unsigned long address, pte_t *ptep,
  8. pte_t entry, int dirty)
  9. {
  10. asm goto(ALTERNATIVE("nop", "j %l[svvptc]", 0, RISCV_ISA_EXT_SVVPTC, 1)
  11. : : : : svvptc);
  12. if (!pte_same(ptep_get(ptep), entry))
  13. __set_pte_at(vma->vm_mm, ptep, entry);
  14. /*
  15. * update_mmu_cache will unconditionally execute, handling both
  16. * the case that the PTE changed and the spurious fault case.
  17. */
  18. return true;
  19. svvptc:
  20. if (!pte_same(ptep_get(ptep), entry)) {
  21. __set_pte_at(vma->vm_mm, ptep, entry);
  22. /* Here only not svadu is impacted */
  23. flush_tlb_page(vma, address);
  24. return true;
  25. }
  26. return false;
  27. }
  28. int ptep_test_and_clear_young(struct vm_area_struct *vma,
  29. unsigned long address,
  30. pte_t *ptep)
  31. {
  32. if (!pte_young(ptep_get(ptep)))
  33. return 0;
  34. return test_and_clear_bit(_PAGE_ACCESSED_OFFSET, &pte_val(*ptep));
  35. }
  36. EXPORT_SYMBOL_GPL(ptep_test_and_clear_young);
  37. #ifdef CONFIG_64BIT
  38. pud_t *pud_offset(p4d_t *p4d, unsigned long address)
  39. {
  40. if (pgtable_l4_enabled)
  41. return p4d_pgtable(p4dp_get(p4d)) + pud_index(address);
  42. return (pud_t *)p4d;
  43. }
  44. p4d_t *p4d_offset(pgd_t *pgd, unsigned long address)
  45. {
  46. if (pgtable_l5_enabled)
  47. return pgd_pgtable(pgdp_get(pgd)) + p4d_index(address);
  48. return (p4d_t *)pgd;
  49. }
  50. #endif
  51. #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
  52. int p4d_set_huge(p4d_t *p4d, phys_addr_t addr, pgprot_t prot)
  53. {
  54. return 0;
  55. }
  56. void p4d_clear_huge(p4d_t *p4d)
  57. {
  58. }
  59. int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot)
  60. {
  61. pud_t new_pud = pfn_pud(__phys_to_pfn(phys), prot);
  62. set_pud(pud, new_pud);
  63. return 1;
  64. }
  65. int pud_clear_huge(pud_t *pud)
  66. {
  67. if (!pud_leaf(pudp_get(pud)))
  68. return 0;
  69. pud_clear(pud);
  70. return 1;
  71. }
  72. int pud_free_pmd_page(pud_t *pud, unsigned long addr)
  73. {
  74. pmd_t *pmd = pud_pgtable(pudp_get(pud));
  75. int i;
  76. pud_clear(pud);
  77. flush_tlb_kernel_range(addr, addr + PUD_SIZE);
  78. for (i = 0; i < PTRS_PER_PMD; i++) {
  79. if (!pmd_none(pmd[i])) {
  80. pte_t *pte = (pte_t *)pmd_page_vaddr(pmd[i]);
  81. pte_free_kernel(NULL, pte);
  82. }
  83. }
  84. pmd_free(NULL, pmd);
  85. return 1;
  86. }
  87. int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot)
  88. {
  89. pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), prot);
  90. set_pmd(pmd, new_pmd);
  91. return 1;
  92. }
  93. int pmd_clear_huge(pmd_t *pmd)
  94. {
  95. if (!pmd_leaf(pmdp_get(pmd)))
  96. return 0;
  97. pmd_clear(pmd);
  98. return 1;
  99. }
  100. int pmd_free_pte_page(pmd_t *pmd, unsigned long addr)
  101. {
  102. pte_t *pte = (pte_t *)pmd_page_vaddr(pmdp_get(pmd));
  103. pmd_clear(pmd);
  104. flush_tlb_kernel_range(addr, addr + PMD_SIZE);
  105. pte_free_kernel(NULL, pte);
  106. return 1;
  107. }
  108. #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
  109. #ifdef CONFIG_TRANSPARENT_HUGEPAGE
  110. pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
  111. unsigned long address, pmd_t *pmdp)
  112. {
  113. pmd_t pmd = pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp);
  114. VM_BUG_ON(address & ~HPAGE_PMD_MASK);
  115. VM_BUG_ON(pmd_trans_huge(pmdp_get(pmdp)));
  116. /*
  117. * When leaf PTE entries (regular pages) are collapsed into a leaf
  118. * PMD entry (huge page), a valid non-leaf PTE is converted into a
  119. * valid leaf PTE at the level 1 page table. Since the sfence.vma
  120. * forms that specify an address only apply to leaf PTEs, we need a
  121. * global flush here. collapse_huge_page() assumes these flushes are
  122. * eager, so just do the fence here.
  123. */
  124. flush_tlb_mm(vma->vm_mm);
  125. return pmd;
  126. }
  127. #endif /* CONFIG_TRANSPARENT_HUGEPAGE */