When unmapping pages, it is not sufficient to compare the size of the
page to the size of the region to be unmapped to know whether a
hugepage needs to be split. That approach does not split hugepages
when the region to be unmapped is larger than a hugepage but does not
cover the entire hugepage, resulting in areas outside the region to be
unmapped and leaving areas inside the region mapped.

Instead of comparing the size of the region to the size of the page,
check if the region overlaps only part of the page and split the
hugepage if it does.

Fixes: 1f7784032531 ("core: Add support for creating page tables with 
hugepages")
Signed-off-by: Chase Conklin <[email protected]>
---
 hypervisor/paging.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/hypervisor/paging.c b/hypervisor/paging.c
index 4a24c1f6..83cdcf00 100644
--- a/hypervisor/paging.c
+++ b/hypervisor/paging.c
@@ -389,7 +389,20 @@ int paging_destroy(const struct paging_structures 
*pg_structs,
                        if (!paging->entry_valid(pte, PAGE_PRESENT_FLAGS))
                                break;
                        if (paging->get_phys(pte, virt) != INVALID_PHYS_ADDR) {
-                               if (paging->page_size <= size)
+                               unsigned long page_start, page_end, region_end;
+                               /*
+                                * If the region to be unmapped doesn't fully
+                                * cover the hugepage, the hugepage will need to
+                                * be split.
+                                */
+                               page_size = paging->page_size ?
+                                       paging->page_size : PAGE_SIZE;
+                               page_start = virt & ~(page_size-1);
+                               page_end = page_start + page_size;
+                               region_end = virt + size;
+
+                               if (virt <= page_start &&
+                                   region_end >= page_end)
                                        break;
 
                                err = split_hugepage(pg_structs->hv_paging,
-- 
2.22.0

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jailhouse-dev/20200115173217.3256-1-chase.conklin%40arm.com.

Reply via email to