diff --git a/hypervisor/arch/x86/guest/ept.c b/hypervisor/arch/x86/guest/ept.c index 070a672f4..df56747ee 100644 --- a/hypervisor/arch/x86/guest/ept.c +++ b/hypervisor/arch/x86/guest/ept.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -444,30 +444,30 @@ void walk_ept_table(struct acrn_vm *vm, pge_handler cb) uint64_t i, j, k, m; for (i = 0UL; i < PTRS_PER_PGTL3E; i++) { - pml4e = pml4e_offset((uint64_t *)get_eptp(vm), i << PML4E_SHIFT); + pml4e = pgtl3e_offset((uint64_t *)get_eptp(vm), i << PML4E_SHIFT); if (!table->pgentry_present(*pml4e)) { continue; } for (j = 0UL; j < PTRS_PER_PGTL2E; j++) { - pdpte = pdpte_offset(pml4e, j << PDPTE_SHIFT); + pdpte = pgtl2e_offset(pml4e, j << PDPTE_SHIFT); if (!table->pgentry_present(*pdpte)) { continue; } - if (pdpte_large(*pdpte) != 0UL) { + if (is_pgtl_large(*pdpte) != 0UL) { cb(pdpte, PGTL2_SIZE); continue; } for (k = 0UL; k < PTRS_PER_PGTL1E; k++) { - pde = pde_offset(pdpte, k << PDE_SHIFT); + pde = pgtl1e_offset(pdpte, k << PDE_SHIFT); if (!table->pgentry_present(*pde)) { continue; } - if (pde_large(*pde) != 0UL) { + if (is_pgtl_large(*pde) != 0UL) { cb(pde, PGTL1_SIZE); continue; } for (m = 0UL; m < PTRS_PER_PGTL0E; m++) { - pte = pte_offset(pde, m << PTE_SHIFT); + pte = pgtl0e_offset(pde, m << PTE_SHIFT); if (table->pgentry_present(*pte)) { cb(pte, PGTL0_SIZE); } diff --git a/hypervisor/arch/x86/guest/guest_memory.c b/hypervisor/arch/x86/guest/guest_memory.c index 9ab27816a..d32a22791 100644 --- a/hypervisor/arch/x86/guest/guest_memory.c +++ b/hypervisor/arch/x86/guest/guest_memory.c @@ -14,6 +14,7 @@ #include #include #include +#include struct page_walk_info { uint64_t top_entry; /* Top level paging structure entry */ diff --git a/hypervisor/arch/x86/guest/optee.c b/hypervisor/arch/x86/guest/optee.c index c75f4d4f7..4cb58bec1 100644 --- a/hypervisor/arch/x86/guest/optee.c +++ b/hypervisor/arch/x86/guest/optee.c @@ -16,6 +16,7 @@ #include #include #include +#include int is_tee_vm(struct acrn_vm *vm) { diff --git a/hypervisor/arch/x86/guest/ve820.c b/hypervisor/arch/x86/guest/ve820.c index e2d86fd86..150998cfe 100644 --- a/hypervisor/arch/x86/guest/ve820.c +++ b/hypervisor/arch/x86/guest/ve820.c @@ -13,6 +13,7 @@ #include #include #include +#include #define ENTRY_GPA_L 2U #define ENTRY_GPA_HI 8U diff --git a/hypervisor/arch/x86/guest/vept.c b/hypervisor/arch/x86/guest/vept.c index 48c458caf..3bcce94cc 100644 --- a/hypervisor/arch/x86/guest/vept.c +++ b/hypervisor/arch/x86/guest/vept.c @@ -79,18 +79,18 @@ static void free_sept_table(uint64_t *shadow_eptp) if (shadow_eptp) { for (i = 0UL; i < PTRS_PER_PML4E; i++) { - shadow_pml4e = pml4e_offset(shadow_eptp, i << PML4E_SHIFT); + shadow_pml4e = pgtl3e_offset(shadow_eptp, i << PML4E_SHIFT); if (!is_present_ept_entry(*shadow_pml4e)) { continue; } for (j = 0UL; j < PTRS_PER_PDPTE; j++) { - shadow_pdpte = pdpte_offset(shadow_pml4e, j << PDPTE_SHIFT); + shadow_pdpte = pgtl2e_offset(shadow_pml4e, j << PDPTE_SHIFT); if (!is_present_ept_entry(*shadow_pdpte) || is_leaf_ept_entry(*shadow_pdpte, PGT_LVL2)) { continue; } for (k = 0UL; k < PTRS_PER_PDE; k++) { - shadow_pde = pde_offset(shadow_pdpte, k << PDE_SHIFT); + shadow_pde = pgtl1e_offset(shadow_pdpte, k << PDE_SHIFT); if (!is_present_ept_entry(*shadow_pde) || is_leaf_ept_entry(*shadow_pde, PGT_LVL1)) { continue; diff --git a/hypervisor/arch/x86/mmu.c b/hypervisor/arch/x86/mmu.c index 7379be71c..29d2ee13e 100644 --- a/hypervisor/arch/x86/mmu.c +++ b/hypervisor/arch/x86/mmu.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/hypervisor/arch/x86/pgtable.c b/hypervisor/arch/x86/pgtable.c new file mode 100644 index 000000000..fc593b2c2 --- /dev/null +++ b/hypervisor/arch/x86/pgtable.c @@ -0,0 +1,32 @@ +#include +#include + +uint64_t arch_pgtl_page_paddr(uint64_t pgtle) +{ + return pgtle & PFN_MASK; +} + +/** + * @brief Check whether specified page table entry is pointing to huge page. + * + * PS(Page Size) flag indicates whether maps a 1-GByte page or 2MByte page or references a page directory table. This function + * checks this flag. This function is typically used in the context of setting up or modifying page tables where it's + * necessary to distinguish between large and regular page mappings. + * + * It returns the value that bit 7 is 1 if the specified pte maps a 1-GByte or 2MByte page, and 0 if references a page table. + * + * @param[in] pgtle The page directory pointer table entry to check. + * + * @return The value of PS flag in the PDPTE. + * + * @retval PAGE_PSE indicating mapping to a 1-GByte or 2MByte page. + * @retval 0 indicating reference to a page directory table. + * + * @pre N/A + * + * @post N/A + */ +uint64_t arch_pgtl_large(uint64_t pgtle) +{ + return pgtle & PAGE_PSE; +} diff --git a/hypervisor/common/mmu.c b/hypervisor/common/mmu.c index 2f80d01fa..176c48322 100644 --- a/hypervisor/common/mmu.c +++ b/hypervisor/common/mmu.c @@ -198,20 +198,21 @@ static inline void construct_pgentry(uint64_t *pte, void *pg_page, uint64_t prot static void modify_or_del_pgtl0(uint64_t *pgtl1e, uint64_t vaddr_start, uint64_t vaddr_end, uint64_t prot_set, uint64_t prot_clr, const struct pgtable *table, uint32_t type) { - uint64_t *pgtl0_page = pde_page_vaddr(*pgtl1e); + uint64_t *pgtl0_page = page_addr(*pgtl1e); uint64_t vaddr = vaddr_start; - uint64_t index = pte_index(vaddr); + uint64_t index = pgtl0e_index(vaddr); dev_dbg(DBG_LEVEL_MMU, "%s, vaddr: [0x%lx - 0x%lx]\n", __func__, vaddr, vaddr_end); for (; index < PTRS_PER_PGTL0E; index++) { uint64_t *pgtl0e = pgtl0_page + index; if (!table->pgentry_present(*pgtl0e)) { - /*suppress warning message for low memory (< 1MBytes),as service VM - * will update MTTR attributes for this region by default whether it - * is present or not. + /*FIXME: For x86, need to suppress warning message for low memory (< 1MBytes), + * as service VM will update MTTR attributes for this region by default + * whether it is present or not. if add the WA in the function update_ept_mem_type(), + * then no need to suppress the warning here. */ - if ((type == MR_MODIFY) && (vaddr >= MEM_1M)) { + if (type == MR_MODIFY) { pr_warn("%s, vaddr: 0x%lx pgtl0e is not present.\n", __func__, vaddr); } } else { @@ -237,9 +238,9 @@ static void modify_or_del_pgtl0(uint64_t *pgtl1e, uint64_t vaddr_start, uint64_t static void modify_or_del_pgtl1(uint64_t *pgtl2e, uint64_t vaddr_start, uint64_t vaddr_end, uint64_t prot_set, uint64_t prot_clr, const struct pgtable *table, uint32_t type) { - uint64_t *pgtl1_page = pdpte_page_vaddr(*pgtl2e); + uint64_t *pgtl1_page = page_addr(*pgtl2e); uint64_t vaddr = vaddr_start; - uint64_t index = pde_index(vaddr); + uint64_t index = pgtl1e_index(vaddr); dev_dbg(DBG_LEVEL_MMU, "%s, vaddr: [0x%lx - 0x%lx]\n", __func__, vaddr, vaddr_end); for (; index < PTRS_PER_PGTL1E; index++) { @@ -251,7 +252,7 @@ static void modify_or_del_pgtl1(uint64_t *pgtl2e, uint64_t vaddr_start, uint64_t pr_warn("%s, addr: 0x%lx pgtl1e is not present.\n", __func__, vaddr); } } else { - if (pde_large(*pgtl1e) != 0UL) { + if (is_pgtl_large(*pgtl1e) != 0UL) { if ((vaddr_next > vaddr_end) || (!mem_aligned_check(vaddr, PGTL1_SIZE))) { split_large_page(pgtl1e, PGT_LVL1, vaddr, table); } else { @@ -284,9 +285,9 @@ static void modify_or_del_pgtl1(uint64_t *pgtl2e, uint64_t vaddr_start, uint64_t static void modify_or_del_pgtl2(const uint64_t *pgtl3e, uint64_t vaddr_start, uint64_t vaddr_end, uint64_t prot_set, uint64_t prot_clr, const struct pgtable *table, uint32_t type) { - uint64_t *pgtl2_page = pml4e_page_vaddr(*pgtl3e); + uint64_t *pgtl2_page = page_addr(*pgtl3e); uint64_t vaddr = vaddr_start; - uint64_t index = pdpte_index(vaddr); + uint64_t index = pgtl2e_index(vaddr); dev_dbg(DBG_LEVEL_MMU, "%s, vaddr: [0x%lx - 0x%lx]\n", __func__, vaddr, vaddr_end); for (; index < PTRS_PER_PGTL2E; index++) { @@ -298,7 +299,7 @@ static void modify_or_del_pgtl2(const uint64_t *pgtl3e, uint64_t vaddr_start, ui pr_warn("%s, vaddr: 0x%lx pgtl2e is not present.\n", __func__, vaddr); } } else { - if (pdpte_large(*pgtl2e) != 0UL) { + if (is_pgtl_large(*pgtl2e) != 0UL) { if ((vaddr_next > vaddr_end) || (!mem_aligned_check(vaddr, PGTL2_SIZE))) { split_large_page(pgtl2e, PGT_LVL2, vaddr, table); @@ -390,7 +391,7 @@ void pgtable_modify_or_del_map(uint64_t *pgtl3_page, uint64_t vaddr_base, uint64 while (vaddr < vaddr_end) { vaddr_next = (vaddr & PGTL3_MASK) + PGTL3_SIZE; - pgtl3e = pml4e_offset(pgtl3_page, vaddr); + pgtl3e = pgtl3e_offset(pgtl3_page, vaddr); if ((!table->pgentry_present(*pgtl3e)) && (type == MR_MODIFY)) { ASSERT(false, "invalid op, pgtl3e not present"); } else { @@ -407,10 +408,10 @@ void pgtable_modify_or_del_map(uint64_t *pgtl3_page, uint64_t vaddr_base, uint64 static void add_pgtl0(const uint64_t *pgtl1e, uint64_t paddr_start, uint64_t vaddr_start, uint64_t vaddr_end, uint64_t prot, const struct pgtable *table) { - uint64_t *pgtl0_page = pde_page_vaddr(*pgtl1e); + uint64_t *pgtl0_page = page_addr(*pgtl1e); uint64_t vaddr = vaddr_start; uint64_t paddr = paddr_start; - uint64_t index = pte_index(vaddr); + uint64_t index = pgtl0e_index(vaddr); dev_dbg(DBG_LEVEL_MMU, "%s, paddr: 0x%lx, vaddr: [0x%lx - 0x%lx]\n", __func__, paddr, vaddr_start, vaddr_end); @@ -438,10 +439,10 @@ static void add_pgtl0(const uint64_t *pgtl1e, uint64_t paddr_start, uint64_t vad static void add_pgtl1(const uint64_t *pgtl2e, uint64_t paddr_start, uint64_t vaddr_start, uint64_t vaddr_end, uint64_t prot, const struct pgtable *table) { - uint64_t *pgtl1_page = pdpte_page_vaddr(*pgtl2e); + uint64_t *pgtl1_page = page_addr(*pgtl2e); uint64_t vaddr = vaddr_start; uint64_t paddr = paddr_start; - uint64_t index = pde_index(vaddr); + uint64_t index = pgtl1e_index(vaddr); uint64_t local_prot = prot; dev_dbg(DBG_LEVEL_MMU, "%s, paddr: 0x%lx, vaddr: [0x%lx - 0x%lx]\n", @@ -450,7 +451,7 @@ static void add_pgtl1(const uint64_t *pgtl2e, uint64_t paddr_start, uint64_t vad uint64_t *pgtl1e = pgtl1_page + index; uint64_t vaddr_next = (vaddr & PGTL1_MASK) + PGTL1_SIZE; - if (pde_large(*pgtl1e) != 0UL) { + if (is_pgtl_large(*pgtl1e) != 0UL) { pr_fatal("%s, pgtl1e 0x%lx is already present!\n", __func__, vaddr); } else { if (!table->pgentry_present(*pgtl1e)) { @@ -488,10 +489,10 @@ static void add_pgtl1(const uint64_t *pgtl2e, uint64_t paddr_start, uint64_t vad static void add_pgtl2(const uint64_t *pgtl3e, uint64_t paddr_start, uint64_t vaddr_start, uint64_t vaddr_end, uint64_t prot, const struct pgtable *table) { - uint64_t *pgtl2_page = pml4e_page_vaddr(*pgtl3e); + uint64_t *pgtl2_page = page_addr(*pgtl3e); uint64_t vaddr = vaddr_start; uint64_t paddr = paddr_start; - uint64_t index = pdpte_index(vaddr); + uint64_t index = pgtl2e_index(vaddr); uint64_t local_prot = prot; dev_dbg(DBG_LEVEL_MMU, "%s, paddr: 0x%lx, vaddr: [0x%lx - 0x%lx]\n", __func__, paddr, vaddr, vaddr_end); @@ -499,7 +500,7 @@ static void add_pgtl2(const uint64_t *pgtl3e, uint64_t paddr_start, uint64_t vad uint64_t *pgtl2e = pgtl2_page + index; uint64_t vaddr_next = (vaddr & PGTL2_MASK) + PGTL2_SIZE; - if (pdpte_large(*pgtl2e) != 0UL) { + if (is_pgtl_large(*pgtl2e) != 0UL) { pr_fatal("%s, pgtl2e 0x%lx is already present!\n", __func__, vaddr); } else { if (!table->pgentry_present(*pgtl2e)) { @@ -587,7 +588,7 @@ void pgtable_add_map(uint64_t *pgtl3_page, uint64_t paddr_base, uint64_t vaddr_b while (vaddr < vaddr_end) { vaddr_next = (vaddr & PGTL3_MASK) + PGTL3_SIZE; - pgtl3e = pml4e_offset(pgtl3_page, vaddr); + pgtl3e = pgtl3e_offset(pgtl3_page, vaddr); if (!table->pgentry_present(*pgtl3e)) { void *pgtl2_page = alloc_page(table->pool); construct_pgentry(pgtl3e, pgtl2_page, table->get_default_access_right(), table); @@ -679,8 +680,8 @@ void *pgtable_create_trusty_root(const struct pgtable *table, * copy PTPDEs from normal world EPT to secure world EPT, * and remove execute access attribute in these entries */ - dest_pdpte_p = pml4e_page_vaddr(sworld_pml4e); - src_pdpte_p = pml4e_page_vaddr(nworld_pml4e); + dest_pdpte_p = page_addr(sworld_pml4e); + src_pdpte_p = page_addr(nworld_pml4e); for (i = 0U; i < (uint16_t)(PTRS_PER_PGTL2E - 1UL); i++) { pdpte = get_pgentry(src_pdpte_p); if ((pdpte & prot_table_present) != 0UL) { @@ -735,25 +736,25 @@ const uint64_t *pgtable_lookup_entry(uint64_t *pgtl3_page, uint64_t addr, uint64 bool present = true; uint64_t *pgtl3e, *pgtl2e, *pgtl1e, *pgtl0e; - pgtl3e = pml4e_offset(pgtl3_page, addr); + pgtl3e = pgtl3e_offset(pgtl3_page, addr); present = table->pgentry_present(*pgtl3e); if (present) { - pgtl2e = pdpte_offset(pgtl3e, addr); + pgtl2e = pgtl2e_offset(pgtl3e, addr); present = table->pgentry_present(*pgtl2e); if (present) { - if (pdpte_large(*pgtl2e) != 0UL) { + if (is_pgtl_large(*pgtl2e) != 0UL) { *pg_size = PGTL2_SIZE; pret = pgtl2e; } else { - pgtl1e = pde_offset(pgtl2e, addr); + pgtl1e = pgtl1e_offset(pgtl2e, addr); present = table->pgentry_present(*pgtl1e); if (present) { - if (pde_large(*pgtl1e) != 0UL) { + if (is_pgtl_large(*pgtl1e) != 0UL) { *pg_size = PGTL1_SIZE; pret = pgtl1e; } else { - pgtl0e = pte_offset(pgtl1e, addr); + pgtl0e = pgtl0e_offset(pgtl1e, addr); present = table->pgentry_present(*pgtl0e); if (present) { *pg_size = PGTL0_SIZE; diff --git a/hypervisor/debug/uart16550.c b/hypervisor/debug/uart16550.c index a8fe8edb8..7c96fdb43 100644 --- a/hypervisor/debug/uart16550.c +++ b/hypervisor/debug/uart16550.c @@ -134,18 +134,18 @@ static void early_pgtable_map_uart(uint64_t addr) CPU_CR_READ(cr3, &value); /*assumpiton for map high mmio in early pagetable is that it is only used for 2MB page since 1G page may not available when memory width is 39bit */ - pml4e = pml4e_offset((uint64_t *)value, addr); + pml4e = pgtl3e_offset((uint64_t *)value, addr); /* address is above 512G */ if(!(*pml4e & PAGE_PRESENT)) { *pml4e = hva2hpa_early(uart_pdpte_page) + (PAGE_PRESENT|PAGE_RW); } - pdpte = pdpte_offset(pml4e, addr); + pdpte = pgtl2e_offset(pml4e, addr); if(!(*pdpte & PAGE_PRESENT)) { *(pdpte) = hva2hpa_early(uart_pde_page) + (PAGE_PRESENT|PAGE_RW); - pde = pde_offset(pdpte, addr); + pde = pgtl1e_offset(pdpte, addr); *pde = (addr & PGTL1_MASK) + (PAGE_PRESENT|PAGE_RW|PAGE_PSE); } else if(!(*pdpte & PAGE_PSE)) { - pde = pde_offset(pdpte, addr); + pde = pgtl1e_offset(pdpte, addr); if(!(*pde & PAGE_PRESENT)) { *pde = (addr & PGTL1_MASK) + (PAGE_PRESENT|PAGE_RW|PAGE_PSE); } diff --git a/hypervisor/include/arch/x86/asm/pgtable.h b/hypervisor/include/arch/x86/asm/pgtable.h index 09b8d8f0e..d64f479f2 100644 --- a/hypervisor/include/arch/x86/asm/pgtable.h +++ b/hypervisor/include/arch/x86/asm/pgtable.h @@ -7,7 +7,6 @@ #define PGTABLE_H #include -#include /** * @addtogroup hwmgmt_page @@ -195,192 +194,6 @@ static inline uint64_t hva2hpa_early(void *x) return (uint64_t)x; } -static inline uint64_t pml4e_index(uint64_t address) -{ - return (address >> PML4E_SHIFT) & (PTRS_PER_PML4E - 1UL); -} - -static inline uint64_t pdpte_index(uint64_t address) -{ - return (address >> PDPTE_SHIFT) & (PTRS_PER_PDPTE - 1UL); -} - -static inline uint64_t pde_index(uint64_t address) -{ - return (address >> PDE_SHIFT) & (PTRS_PER_PDE - 1UL); -} - -static inline uint64_t pte_index(uint64_t address) -{ - return (address >> PTE_SHIFT) & (PTRS_PER_PTE - 1UL); -} - -static inline uint64_t *pml4e_page_vaddr(uint64_t pml4e) -{ - return hpa2hva(pml4e & PML4E_PFN_MASK); -} - -static inline uint64_t *pdpte_page_vaddr(uint64_t pdpte) -{ - return hpa2hva(pdpte & PDPTE_PFN_MASK); -} - -static inline uint64_t *pde_page_vaddr(uint64_t pde) -{ - return hpa2hva(pde & PDE_PFN_MASK); -} - -/** - * @brief Calculate the page map level-4 table entry(PML4E) for a specified input address. - * - * The page map level-4 table(PML4T) contains 512 entries, each of which points to a page directory pointer table(PDPT). - * Address has the index to the PML4E in PML4T. This function is used to calculate the address of PML4E. It is typically - * used during the page translation process. - * - * It will return a pointer to the page map level-4 table entry(PML4E). - * - * @param[in] pml4_page A pointer to a page map level-4 table(PML4T) page. - * @param[in] addr The address value for which the page map level-4 table entry(PML4E) address is to be calculated. - * For hypervisor's MMU, it is the host virtual address. - * For each VM's EPT, it is the guest physical address. - * - * @return A pointer to the PML4E. - * - * @pre pml4_page != NULL - * - * @post N/A - */ -static inline uint64_t *pml4e_offset(uint64_t *pml4_page, uint64_t addr) -{ - return pml4_page + pml4e_index(addr); -} - -/** - * @brief Calculate the page directory pointer table entry(PDPTE) for a specified input address. - * - * The page directory pointer table(PDPT) is referenced by a page map level-4 table entry(PML4E) and echo entry(PDPTE) - * in PDPT points to a page directory table(PDT). Address has the index to the PDPTE in PDPT. This function is used to - * calculate the address of PDPTE. It is typically used during the page translation process. - * - * It will return a pointer to the page directory pointer table entry(PDPTE). - * - * @param[in] pml4e A pointer to a page map level-4 table entry(PML4E). - * @param[in] addr The address for which the page directory pointer table entry(PDPTE) address is to be calculated. - * For hypervisor's MMU, it is the host virtual address. - * For each VM's EPT, it is the guest physical address. - * - * @return A pointer to the PDPTE. - * - * @pre pml4e != NULL - * - * @post N/A - */ -static inline uint64_t *pdpte_offset(const uint64_t *pml4e, uint64_t addr) -{ - return pml4e_page_vaddr(*pml4e) + pdpte_index(addr); -} - -/** - * @brief Calculate the page directory table entry(PDE) for a specified input address. - * - * The page directory table(PDT) is referenced by a page directory pointer table entry(PDPTE) and echo entry(PDE) in PDT - * points to a page table(PT). Address has the index to the PDE in PDT. This function is used to calculate the address - * of PDE. It is typically used during the page translation process. - * - * It will return a pointer to the page directory table entry(PDE). - * - * @param[in] pdpte A pointer to a page directory pointer table entry(PDPTE). - * @param[in] addr The address for which the page directory table entry(PDE) address is to be calculated. - * For hypervisor's MMU, it is the host virtual address. - * For each VM's EPT, it is the guest physical address. - * - * @return A pointer to the PDE. - * - * @pre pdpte != NULL - * - * @post N/A - */ -static inline uint64_t *pde_offset(const uint64_t *pdpte, uint64_t addr) -{ - return pdpte_page_vaddr(*pdpte) + pde_index(addr); -} - -/** - * @brief Calculate the page table entry(PTE) for a specified input address. - * - * The page table entry(PTE) is the entry that maps a page. This function is used to calculate the address of the PTE. - * It is typically used during the page translation process. The function is essential for managing memory access - * permissions and for implementing memory systems. - * - * It will return the address of a page table entry(PTE). - * - * @param[in] pde A pointer to a page directory entry(PDE). - * @param[in] addr The address for which the page table entry(PTE) address is to be calculated. - * For hypervisor's MMU, it is the host virtual address. - * For each VM's EPT, it is the guest physical address. - * - * @return A pointer to the page table entry(PTE). - * - * @pre pde != NULL - * - * @post N/A - */ -static inline uint64_t *pte_offset(const uint64_t *pde, uint64_t addr) -{ - return pde_page_vaddr(*pde) + pte_index(addr); -} - -/** - * @brief Check whether the PS flag of the specified page directory table entry(PDE) is 1 or not. - * - * PS(Page Size) flag in PDE indicates whether maps a 2-MByte page or references a page table. This function checks this - * flag. This function is typically used in the context of setting up or modifying page tables where it's necessary to - * distinguish between large and regular page mappings. - * - * It returns the value that bit 7 is 1 if the specified PDE maps a 2-MByte page, or 0 if references a page table. - * - * @param[in] pde The page directory table entry(PDE) to check. - * - * @return The value of PS flag in the PDE. - * - * @retval PAGE_PSE indicating mapping to a 2-MByte page. - * @retval 0 indicating reference to a page table. - * - * @pre N/A - * - * @post N/A - */ -static inline uint64_t pde_large(uint64_t pde) -{ - return pde & PAGE_PSE; -} - -/** - * @brief Check whether the PS flag of the specified page directory pointer table entry(PDPTE) is 1 or not. - * - * PS(Page Size) flag in PDPTE indicates whether maps a 1-GByte page or references a page directory table. This function - * checks this flag. This function is typically used in the context of setting up or modifying page tables where it's - * necessary to distinguish between large and regular page mappings. - * - * It returns the value that bit 7 is 1 if the specified PDPTE maps a 1-GByte page, and 0 if references a page table. - * - * @param[in] pdpte The page directory pointer table entry(PDPTE) to check. - * - * @return The value of PS flag in the PDPTE. - * - * @retval PAGE_PSE indicating mapping to a 1-GByte page. - * @retval 0 indicating reference to a page directory table. - * - * @pre N/A - * - * @post N/A - */ -static inline uint64_t pdpte_large(uint64_t pdpte) -{ - return pdpte & PAGE_PSE; -} - - void *pgtable_create_trusty_root(const struct pgtable *table, void *nworld_pml4_page, uint64_t prot_table_present, uint64_t prot_clr); diff --git a/hypervisor/include/common/pgtable.h b/hypervisor/include/common/pgtable.h index 5eb81501d..52b705afe 100644 --- a/hypervisor/include/common/pgtable.h +++ b/hypervisor/include/common/pgtable.h @@ -8,6 +8,10 @@ #ifndef COMMON_PGTABLE_H #define COMMON_PGTABLE_H #include +#include + +uint64_t arch_pgtl_page_paddr(uint64_t pgtle); +uint64_t arch_pgtl_large(uint64_t pgtle); /** * @brief Translate a host physical address to a host virtual address. @@ -66,4 +70,135 @@ static inline uint64_t round_page_down(uint64_t addr) { return (addr & PAGE_MASK); } + +static inline uint64_t pgtl3e_index(uint64_t address) +{ + return (address >> PGTL3_SHIFT) & (PTRS_PER_PGTL3E - 1UL); +} + +static inline uint64_t pgtl2e_index(uint64_t address) +{ + return (address >> PGTL2_SHIFT) & (PTRS_PER_PGTL2E- 1UL); +} + +static inline uint64_t pgtl1e_index(uint64_t address) +{ + return (address >> PGTL1_SHIFT) & (PTRS_PER_PGTL1E - 1UL); +} + +static inline uint64_t pgtl0e_index(uint64_t address) +{ + return (address >> PGTL0_SHIFT) & (PTRS_PER_PGTL0E - 1UL); +} + +static inline uint64_t *page_addr(uint64_t pgtle) +{ + return hpa2hva(arch_pgtl_page_paddr(pgtle)); +} + +static inline uint64_t is_pgtl_large(uint64_t pgtle) +{ + return arch_pgtl_large(pgtle); +} + +/** + * @brief Calculate the page map PGT_LVL3 table entry for a specified input address. + * + * The page map PGT_LVL3 table contains 512 entries, each of which points to a PGT_LVL2 page table. + * Address has the index to the PGT_LVL3 entry. This function is used to calculate the address of PGT_LVL3 entry. + * It is typically used during the page translation process. + * + * It will return a pointer to the page map PGT_LVL3 table entry. + * + * @param[in] pgtl3_page A pointer to a PGT_LVL3 page. + * @param[in] addr The address value for which the page map PGT_LVL3 table entry address is to be calculated. + * For hypervisor's MMU, it is the host virtual address. + * For each VM's stage 2 tranlation, it is the guest physical address. + * + * @return A pointer to the PGT_LVL3 entry. + * + * @pre pgtl3_page != NULL + * + * @post N/A + */ +static inline uint64_t *pgtl3e_offset(uint64_t *pgtl3_page, uint64_t addr) +{ + return pgtl3_page + pgtl3e_index(addr); +} + +/** + * @brief Calculate the PGT_LVL2 page table entry for a specified input address. + * + * The PGT_LVL2 page table is referenced by a page map PGT_LVL3 table entry and echo entry + * in PGT_LVL2 points to a PGT_LVL1 page table. Address has the index to the PGT_LVL2 entry. This function is used to + * calculate the address of PGT_LVL2 entry. It is typically used during the page translation process. + * + * It will return a pointer to the PGT_LVL2 page table entry. + * + * @param[in] pgtl3e A pointer to a PGT_LVL3 page map table entry. + * @param[in] addr The address for which the PGT_LVL2 page table entry address is to be calculated. + * For hypervisor's MMU, it is the host virtual address. + * For each VM's stage2 tranlation, it is the guest physical address. + * + * @return A pointer to the PGT_LVL2 entry. + * + * @pre pgtl3e != NULL + * + * @post N/A + */ +static inline uint64_t *pgtl2e_offset(const uint64_t *pgtl3e, uint64_t addr) +{ + return page_addr(*pgtl3e) + pgtl2e_index(addr); +} + +/** + * @brief Calculate the PGT_LVL1 page table entry for a specified input address. + * + * The PGT_LVL1 page table is referenced by a PGT_LVL2 page table entry and echo entry + * points to a page table. Address has the index to the entry in PGT_LVL1 page table . This function + * is used to calculate the address of PDE. It is typically used during the page translation process. + * + * It will return a pointer to the PGT_LVL1 page table entry. + * + * @param[in] pgtl2e A pointer to a PGT_LVL2 page table entry. + * @param[in] addr The address for which the PGT_LVL1 page table entry address is to be calculated. + * For hypervisor's MMU, it is the host virtual address. + * For each VM's stage 2 translation, it is the guest physical address. + * + * @return A pointer to the PGT_LVL1 page table entry. + * + * @pre pgtl2e != NULL + * + * @post N/A + */ +static inline uint64_t *pgtl1e_offset(const uint64_t *pgtl2e, uint64_t addr) +{ + return page_addr(*pgtl2e) + pgtl1e_index(addr); +} + +/** + * @brief Calculate the PGT_LVL0 page table entry for a specified input address. + * + * The PGT_LVL0 page table entry is the entry that maps a page. This function is used to calculate + * the address of the PGT_LVL0 entry. It is typically used during the page translation process. + * The function is essential for managing memory access permissions and for implementing memory systems. + * + * It will return the address of a PGT_LVL0 page table entry. + * + * @param[in] pgtl1e A pointer to a PGT_LVL1 page table entry. + * @param[in] addr The address for which the PGT_LVL1 page table entry address is to be calculated. + * For hypervisor's MMU, it is the host virtual address. + * For each VM's stage 2 translation, it is the guest physical address. + * + * @return A pointer to the PGT_LVL0 page table entry. + * + * @pre pgtl1e != NULL + * + * @post N/A + */ +static inline uint64_t *pgtl0e_offset(const uint64_t *pgtl1e, uint64_t addr) +{ + return page_addr(*pgtl1e) + pgtl0e_index(addr); +} + #endif /* COMMON_PGTABLE_H*/