From 09c3c3a4d45ec8991116f5f3eafafffe5057ec24 Mon Sep 17 00:00:00 2001 From: Pawel Wieczorkiewicz Date: Tue, 14 Nov 2023 13:14:41 +0100 Subject: [PATCH] arch,pt: add get_va_mfn_order() functionality The functions traverse specified page tables and obtain a MFN and frame order for a specified virtual address. Signed-off-by: Pawel Wieczorkiewicz --- arch/x86/pagetables.c | 80 ++++++++++++++++++++++++++++++++++++ include/arch/x86/pagetable.h | 3 ++ 2 files changed, 83 insertions(+) diff --git a/arch/x86/pagetables.c b/arch/x86/pagetables.c index 3c0bd2b9..836afa93 100644 --- a/arch/x86/pagetables.c +++ b/arch/x86/pagetables.c @@ -446,6 +446,86 @@ int vunmap_user(void *va, mfn_t *mfn, unsigned int *order) { return err; } +static int get_va_mfn_order(const cr3_t *cr3_ptr, const void *va, mfn_t *mfn, + unsigned int *order) { + unsigned int _order; + mfn_t _mfn; + pgentry_t *tab; + + ASSERT(mfn || order); + if (mfn_invalid(cr3_ptr->mfn)) + return -EINVAL; + + tab = tmp_map_mfn(cr3_ptr->mfn); +#if defined(__x86_64__) + pml4_t *l4e = l4_table_entry((pml4_t *) tab, va); + if (mfn_invalid(l4e->mfn) || !l4e->P) + return -ENOENT; + + tab = tmp_map_mfn(l4e->mfn); +#endif + pdpe_t *l3e = l3_table_entry((pdpe_t *) tab, va); + if (mfn_invalid(l3e->mfn) || !l3e->P) + return -ENOENT; + + if (l3e->PS) { + _mfn = l3e->mfn; + _order = PAGE_ORDER_1G; + goto done; + } + + tab = tmp_map_mfn(l3e->mfn); + pde_t *l2e = l2_table_entry((pde_t *) tab, va); + if (mfn_invalid(l2e->mfn) || !l2e->P) + return -ENOENT; + + if (l2e->PS) { + _mfn = l2e->mfn; + _order = PAGE_ORDER_2M; + goto done; + } + + tab = tmp_map_mfn(l2e->mfn); + pte_t *l1e = l1_table_entry((pte_t *) tab, va); + if (mfn_invalid(l1e->mfn) || !l1e->P) + return -ENOENT; + + _mfn = l1e->mfn; + _order = PAGE_ORDER_4K; + +done: + if (mfn) + *mfn = _mfn; + if (order) + *order = _order; + + return 0; +} + +int get_kern_va_mfn_order(void *va, mfn_t *mfn, unsigned int *order) { + int err; + + dprintk("%s: va: 0x%p (cr3: 0x%p)\n", __func__, va, &cr3); + + spin_lock(&vmap_lock); + err = get_va_mfn_order(&cr3, va, mfn, order); + spin_unlock(&vmap_lock); + + return err; +} + +int get_user_va_mfn_order(void *va, mfn_t *mfn, unsigned int *order) { + int err; + + dprintk("%s: va: 0x%p (cr3: 0x%p)\n", __func__, va, &user_cr3); + + spin_lock(&vmap_lock); + err = get_va_mfn_order(&user_cr3, va, mfn, order); + spin_unlock(&vmap_lock); + + return err; +} + static inline void init_cr3(cr3_t *cr3_ptr) { memset(cr3_ptr, 0, sizeof(*cr3_ptr)); cr3_ptr->mfn = MFN_INVALID; diff --git a/include/arch/x86/pagetable.h b/include/arch/x86/pagetable.h index 0ca155cb..fb95e444 100644 --- a/include/arch/x86/pagetable.h +++ b/include/arch/x86/pagetable.h @@ -301,6 +301,9 @@ extern void dump_pagetables(cr3_t *cr3_ptr); extern void dump_kern_pagetable_va(void *va); extern void dump_user_pagetable_va(void *va); +extern int get_kern_va_mfn_order(void *va, mfn_t *mfn, unsigned int *order); +extern int get_user_va_mfn_order(void *va, mfn_t *mfn, unsigned int *order); + #endif /* __ASSEMBLY__ */ #endif /* KTF_PAGETABLE_H */