Skip to content

Commit

Permalink
mm/hugetlb: Handle pte markers in page faults
Browse files Browse the repository at this point in the history
Allow hugetlb code to handle pte markers just like none ptes.  It's mostly
there, we just need to make sure we don't assume hugetlb_no_page() only handles
none pte, so when detecting pte change we should use pte_same() rather than
pte_none().  We need to pass in the old_pte to do the comparison.

Check the original pte to see whether it's a pte marker, if it is, we should
recover uffd-wp bit on the new pte to be installed, so that the next write will
be trapped by uffd.

Signed-off-by: Peter Xu <peterx@redhat.com>
  • Loading branch information
xzpeter authored and intel-lab-lkp committed Apr 5, 2022
1 parent b9e6c67 commit e7e7aae
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions mm/hugetlb.c
Expand Up @@ -5412,7 +5412,8 @@ static inline vm_fault_t hugetlb_handle_userfault(struct vm_area_struct *vma,
static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
struct vm_area_struct *vma,
struct address_space *mapping, pgoff_t idx,
unsigned long address, pte_t *ptep, unsigned int flags)
unsigned long address, pte_t *ptep,
pte_t old_pte, unsigned int flags)
{
struct hstate *h = hstate_vma(vma);
vm_fault_t ret = VM_FAULT_SIGBUS;
Expand Down Expand Up @@ -5539,7 +5540,8 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,

ptl = huge_pte_lock(h, mm, ptep);
ret = 0;
if (!huge_pte_none(huge_ptep_get(ptep)))
/* If pte changed from under us, retry */
if (!pte_same(huge_ptep_get(ptep), old_pte))
goto backout;

if (anon_rmap) {
Expand All @@ -5549,6 +5551,12 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
page_dup_file_rmap(page, true);
new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE)
&& (vma->vm_flags & VM_SHARED)));
/*
* If this pte was previously wr-protected, keep it wr-protected even
* if populated.
*/
if (unlikely(pte_marker_uffd_wp(old_pte)))
new_pte = huge_pte_wrprotect(huge_pte_mkuffd_wp(new_pte));
set_huge_pte_at(mm, haddr, ptep, new_pte);

hugetlb_count_add(pages_per_huge_page(h), mm);
Expand Down Expand Up @@ -5666,8 +5674,10 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
mutex_lock(&hugetlb_fault_mutex_table[hash]);

entry = huge_ptep_get(ptep);
if (huge_pte_none(entry)) {
ret = hugetlb_no_page(mm, vma, mapping, idx, address, ptep, flags);
/* PTE markers should be handled the same way as none pte */
if (huge_pte_none_mostly(entry)) {
ret = hugetlb_no_page(mm, vma, mapping, idx, address, ptep,
entry, flags);
goto out_mutex;
}

Expand Down

0 comments on commit e7e7aae

Please sign in to comment.