When the kpkeys_hardened_pgtables feature is enabled, special care
is required when allocating page table pages while splitting the
linear map.

Indicate that such pages are being allocated by passing
__GFP_PGTABLE_SPLIT and use the appropriate interface to prepare the
kpkeys_hardened_pgtables allocator in
split_kernel_leaf_mapping().

Signed-off-by: Kevin Brodsky <[email protected]>
---
 arch/arm64/mm/mmu.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index ea1cb1875257..2cee0b7f8a56 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -707,7 +707,7 @@ static int split_kernel_leaf_mapping_locked(unsigned long 
addr)
        if (!pud_present(pud))
                goto out;
        if (pud_leaf(pud)) {
-               ret = split_pud(pudp, pud, GFP_PGTABLE_KERNEL, true);
+               ret = split_pud(pudp, pud, GFP_PGTABLE_KERNEL | 
__GFP_PGTABLE_SPLIT, true);
                if (ret)
                        goto out;
        }
@@ -732,7 +732,7 @@ static int split_kernel_leaf_mapping_locked(unsigned long 
addr)
                 */
                if (ALIGN_DOWN(addr, PMD_SIZE) == addr)
                        goto out;
-               ret = split_pmd(pmdp, pmd, GFP_PGTABLE_KERNEL, true);
+               ret = split_pmd(pmdp, pmd, GFP_PGTABLE_KERNEL | 
__GFP_PGTABLE_SPLIT, true);
                if (ret)
                        goto out;
        }
@@ -800,7 +800,18 @@ int split_kernel_leaf_mapping(unsigned long start, 
unsigned long end)
        if (start != PAGE_ALIGN(start) || end != PAGE_ALIGN(end))
                return -EINVAL;
 
+kpkeys_retry:
+       ret = kpkeys_prepare_direct_map_split();
+       if (ret)
+               return ret;
+
        mutex_lock(&pgtable_split_lock);
+
+       if (!kpkeys_ready_for_direct_map_split()) {
+               mutex_unlock(&pgtable_split_lock);
+               goto kpkeys_retry;
+       }
+
        lazy_mmu_mode_enable();
 
        /*
-- 
2.51.2


Reply via email to