From 639d0e496b1f28b3978824d10c8ae67439aa6027 Mon Sep 17 00:00:00 2001 From: "TOIDA,Suguru" Date: Fri, 30 Nov 2018 09:18:01 +0900 Subject: [PATCH] ContiguousPTE[3/12] modify move_pte_range Change-Id: I20878c97bea768d1f09ab0580d744a58c070be2c --- arch/arm64/kernel/memory.c | 40 +++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/memory.c b/arch/arm64/kernel/memory.c index bbc8c0a6..054a9397 100644 --- a/arch/arm64/kernel/memory.c +++ b/arch/arm64/kernel/memory.c @@ -2601,7 +2601,7 @@ static int move_one_page(void *arg0, page_table_t pt, pte_t *ptep, { int error; struct move_args *args = arg0; - const size_t pgsize = (size_t)1 << pgshift; + size_t pgsize = (size_t)1 << pgshift; uintptr_t dest; pte_t apte; uintptr_t phys; @@ -2621,6 +2621,20 @@ static int move_one_page(void *arg0, page_table_t pt, pte_t *ptep, apte = PTE_NULL; pte_xchg(ptep, &apte); + // check attributes before clearing to PTE_NULL + if (pte_is_contiguous(&apte)) { + // check if ptep is an entry of contiguous pte head + if (page_is_contiguous_head(ptep, pgsize)) { + int level = pgsize_to_tbllv(pgsize); + + pgsize = tbllv_to_contpgsize(level); + pgshift = tbllv_to_contpgshift(level); + } else { + error = 0; + goto out; + } + } + phys = apte & PT_PHYSMASK; attr = apte & ~PT_PHYSMASK; @@ -2645,6 +2659,8 @@ int move_pte_range(page_table_t pt, struct process_vm *vm, { int error; struct move_args args; + pte_t *ptep; + size_t pgsize; dkprintf("move_pte_range(%p,%p,%p,%#lx)\n", pt, src, dest, size); args.src = (uintptr_t)src; @@ -2652,6 +2668,28 @@ int move_pte_range(page_table_t pt, struct process_vm *vm, args.vm = vm; args.range = range; + ptep = ihk_mc_pt_lookup_pte(pt, src, 0, NULL, &pgsize, NULL); + if (ptep && pte_is_contiguous(ptep)) { + if (!page_is_contiguous_head(ptep, pgsize)) { + // start pte is not contiguous head + error = split_contiguous_pages(ptep, pgsize); + if (error) { + goto out; + } + } + } + + ptep = ihk_mc_pt_lookup_pte(pt, src + size - 1, 0, NULL, &pgsize, NULL); + if (ptep && pte_is_contiguous(ptep)) { + if (!page_is_contiguous_tail(ptep, pgsize)) { + // end pte is not contiguous tail + error = split_contiguous_pages(ptep, pgsize); + if (error) { + goto out; + } + } + } + error = visit_pte_range(pt, src, src+size, 0, VPTEF_SKIP_NULL, &move_one_page, &args); flush_tlb(); /* XXX: TLB flush */