lkml.org 
[lkml]   [2023]   [Sep]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
SubjectRe: [syzbot] [mm?] BUG: Bad page map (7)
From
On 9/11/23 06:26, Matthew Wilcox wrote:
> @@ -231,7 +235,10 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
> if (--nr == 0)
> break;
> ptep++;
> - pte = __pte(pte_val(pte) + (1UL << PFN_PTE_SHIFT));
> + if (__pte_needs_invert(pte_val(pte)))
> + pte = __pte(pte_val(pte) - (1UL << PFN_PTE_SHIFT));
> + else
> + pte = __pte(pte_val(pte) + (1UL << PFN_PTE_SHIFT));
> }
> arch_leave_lazy_mmu_mode();
> }

This is much better than a whole x86 fork of set_ptes(). But it's still
a bit wonky because it exposes the PTE inversion logic to generic code.

Could we do something like this instead? It'll (probably) end up
repeating the PTE inversion logic each way though the loop, so it's less
efficient than what you have above. But unless I buggered something, it
"just works" without exposing any of the inversion logic to generic code.

The trick is that pte_pfn() undoes the inversion and then pfn_pte()
re-does it on each trip through the loop.

static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte, unsigned int nr)
{
pgprot_t prot = pte_pgprot(x);
unsigned long pfn = pte_pfn(pte);

page_table_check_ptes_set(mm, ptep, pte, nr);

arch_enter_lazy_mmu_mode();
for (;;) {
set_pte(ptep, pte);
if (--nr == 0)
break;
ptep++;
pfn++;
pte = pfn_pte(pfn, pgprot);
}
arch_leave_lazy_mmu_mode();
}

Obviously completely untested. :)

\
 
 \ /
  Last update: 2023-09-11 23:57    [W:0.395 / U:0.024 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site