Commit a4a61ee4 authored by Nanyong Sun's avatar Nanyong Sun
Browse files

mm: HVO: introduce helper function to update and flush pgtable

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I9JCV4

Reference: https://lore.kernel.org/all/20240113094436.2506396-2-sunnanyong@huawei.com/



---------------------------

Add pmd/pte update and tlb flush helper function to update page
table. This refactoring patch is designed to facilitate each
architecture to implement its own special logic in preparation
for the arm64 architecture to follow the necessary break-before-make
sequence when updating page tables.

Signed-off-by: default avatarNanyong Sun <sunnanyong@huawei.com>
Reviewed-by: default avatarMuchun Song <songmuchun@bytedance.com>
parent d9d2e017
Loading
Loading
Loading
Loading
+39 −8
Original line number Diff line number Diff line
@@ -37,6 +37,37 @@ struct vmemmap_remap_walk {
	struct list_head	*vmemmap_pages;
};

#ifndef vmemmap_update_pmd
static inline void vmemmap_update_pmd(unsigned long addr,
				      pmd_t *pmdp, pte_t *ptep)
{
	pmd_populate_kernel(&init_mm, pmdp, ptep);
}
#endif

#ifndef vmemmap_update_pte
static inline void vmemmap_update_pte(unsigned long addr,
				      pte_t *ptep, pte_t pte)
{
	set_pte_at(&init_mm, addr, ptep, pte);
}
#endif

#ifndef vmemmap_flush_tlb_all
static inline void vmemmap_flush_tlb_all(void)
{
	flush_tlb_all();
}
#endif

#ifndef vmemmap_flush_tlb_range
static inline void vmemmap_flush_tlb_range(unsigned long start,
					   unsigned long end)
{
	flush_tlb_kernel_range(start, end);
}
#endif

static int split_vmemmap_huge_pmd(pmd_t *pmd, unsigned long start)
{
	pmd_t __pmd;
@@ -79,8 +110,8 @@ static int split_vmemmap_huge_pmd(pmd_t *pmd, unsigned long start)

		/* Make pte visible before pmd. See comment in pmd_install(). */
		smp_wmb();
		pmd_populate_kernel(&init_mm, pmd, pgtable);
		flush_tlb_kernel_range(start, start + PMD_SIZE);
		vmemmap_update_pmd(start, pmd, pgtable);
		vmemmap_flush_tlb_range(start, start + PMD_SIZE);
	} else {
		pte_free_kernel(&init_mm, pgtable);
	}
@@ -198,7 +229,7 @@ static int vmemmap_remap_range(unsigned long start, unsigned long end,
			return ret;
	} while (pgd++, addr = next, addr != end);

	flush_tlb_kernel_range(start, end);
	vmemmap_flush_tlb_range(start, end);

	return 0;
}
@@ -244,15 +275,15 @@ static void vmemmap_remap_pte(pte_t *pte, unsigned long addr,

		/*
		 * Makes sure that preceding stores to the page contents from
		 * vmemmap_remap_free() become visible before the set_pte_at()
		 * write.
		 * vmemmap_remap_free() become visible before the
		 * vmemmap_update_pte() write.
		 */
		smp_wmb();
	}

	entry = mk_pte(walk->reuse_page, pgprot);
	list_add_tail(&page->lru, walk->vmemmap_pages);
	set_pte_at(&init_mm, addr, pte, entry);
	vmemmap_update_pte(addr, pte, entry);
}

/*
@@ -291,10 +322,10 @@ static void vmemmap_restore_pte(pte_t *pte, unsigned long addr,

	/*
	 * Makes sure that preceding stores to the page contents become visible
	 * before the set_pte_at() write.
	 * before the vmemmap_update_pte() write.
	 */
	smp_wmb();
	set_pte_at(&init_mm, addr, pte, mk_pte(page, pgprot));
	vmemmap_update_pte(addr, pte, mk_pte(page, pgprot));
}

/**