Skip to content

Commit 47b8def

Browse files
kvaneeshmpe
authored andcommitted
powerpc/mm: Avoid calling arch_enter/leave_lazy_mmu() in set_ptes
With commit 9fee28b ("powerpc: implement the new page table range API") we added set_ptes to powerpc architecture. The implementation included calling arch_enter/leave_lazy_mmu() calls. The patch removes the usage of arch_enter/leave_lazy_mmu() because set_pte is not supposed to be used when updating a pte entry. Powerpc architecture uses this rule to skip the expensive tlb invalidate which is not needed when you are setting up the pte for the first time. See commit 56eecdb ("mm: Use ptep/pmdp_set_numa() for updating _PAGE_NUMA bit") for more details The patch also makes sure we are not using the interface to update a valid/present pte entry by adding VM_WARN_ON check all the ptes we are setting up. Furthermore, we add a comment to set_pte_filter to clarify it can only update folio-related flags and cannot filter pfn specific details in pte filtering. Removal of arch_enter/leave_lazy_mmu() also will avoid nesting of these functions that are not supported. For ex: remap_pte_range() -> arch_enter_lazy_mmu() -> set_ptes() -> arch_enter_lazy_mmu() -> arch_leave_lazy_mmu() -> arch_leave_lazy_mmu() Fixes: 9fee28b ("powerpc: implement the new page table range API") Signed-off-by: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://msgid.link/20231024143604.16749-1-aneesh.kumar@linux.ibm.com
1 parent daa9ada commit 47b8def

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

arch/powerpc/mm/pgtable.c

+22-10
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ static pte_t set_pte_filter_hash(pte_t pte) { return pte; }
104104
/* Embedded type MMU with HW exec support. This is a bit more complicated
105105
* as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so
106106
* instead we "filter out" the exec permission for non clean pages.
107+
*
108+
* This is also called once for the folio. So only work with folio->flags here.
107109
*/
108110
static inline pte_t set_pte_filter(pte_t pte)
109111
{
@@ -190,29 +192,39 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma,
190192
void set_ptes(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
191193
pte_t pte, unsigned int nr)
192194
{
193-
/*
194-
* Make sure hardware valid bit is not set. We don't do
195-
* tlb flush for this update.
196-
*/
197-
VM_WARN_ON(pte_hw_valid(*ptep) && !pte_protnone(*ptep));
198195

199196
/* Note: mm->context.id might not yet have been assigned as
200197
* this context might not have been activated yet when this
201-
* is called.
198+
* is called. Filter the pte value and use the filtered value
199+
* to setup all the ptes in the range.
202200
*/
203201
pte = set_pte_filter(pte);
204202

205-
/* Perform the setting of the PTE */
206-
arch_enter_lazy_mmu_mode();
203+
/*
204+
* We don't need to call arch_enter/leave_lazy_mmu_mode()
205+
* because we expect set_ptes to be only be used on not present
206+
* and not hw_valid ptes. Hence there is no translation cache flush
207+
* involved that need to be batched.
208+
*/
207209
for (;;) {
210+
211+
/*
212+
* Make sure hardware valid bit is not set. We don't do
213+
* tlb flush for this update.
214+
*/
215+
VM_WARN_ON(pte_hw_valid(*ptep) && !pte_protnone(*ptep));
216+
217+
/* Perform the setting of the PTE */
208218
__set_pte_at(mm, addr, ptep, pte, 0);
209219
if (--nr == 0)
210220
break;
211221
ptep++;
212-
pte = __pte(pte_val(pte) + (1UL << PTE_RPN_SHIFT));
213222
addr += PAGE_SIZE;
223+
/*
224+
* increment the pfn.
225+
*/
226+
pte = pfn_pte(pte_pfn(pte) + 1, pte_pgprot((pte)));
214227
}
215-
arch_leave_lazy_mmu_mode();
216228
}
217229

218230
void unmap_kernel_page(unsigned long va)

0 commit comments

Comments
 (0)