diff --git a/arch/x86/core/fatal.c b/arch/x86/core/fatal.c index 21156365f35..d7c7e2b20df 100644 --- a/arch/x86/core/fatal.c +++ b/arch/x86/core/fatal.c @@ -237,61 +237,6 @@ static void log_exception(uintptr_t vector, uintptr_t code) } } -#ifdef CONFIG_X86_MMU -static bool dump_entry_flags(const char *name, u64_t flags) -{ - if ((flags & Z_X86_MMU_P) == 0) { - LOG_ERR("%s: Non-present", name); - return false; - } else { - LOG_ERR("%s: 0x%016llx %s, %s, %s", name, flags, - flags & MMU_ENTRY_WRITE ? - "Writable" : "Read-only", - flags & MMU_ENTRY_USER ? - "User" : "Supervisor", - flags & MMU_ENTRY_EXECUTE_DISABLE ? - "Execute Disable" : "Execute Enabled"); - return true; - } -} - -static void dump_mmu_flags(struct x86_page_tables *ptables, uintptr_t addr) -{ - u64_t entry; - -#ifdef CONFIG_X86_64 - entry = *z_x86_get_pml4e(ptables, addr); - if (!dump_entry_flags("PML4E", entry)) { - return; - } - - entry = *z_x86_pdpt_get_pdpte(z_x86_pml4e_get_pdpt(entry), addr); - if (!dump_entry_flags("PDPTE", entry)) { - return; - } -#else - /* 32-bit doesn't have anything interesting in the PDPTE except - * the present bit - */ - entry = *z_x86_get_pdpte(ptables, addr); - if ((entry & Z_X86_MMU_P) == 0) { - LOG_ERR("PDPTE: Non-present"); - return; - } -#endif - - entry = *z_x86_pd_get_pde(z_x86_pdpte_get_pd(entry), addr); - if (!dump_entry_flags(" PDE", entry)) { - return; - } - - entry = *z_x86_pt_get_pte(z_x86_pde_get_pt(entry), addr); - if (!dump_entry_flags(" PTE", entry)) { - return; - } -} -#endif /* CONFIG_X86_MMU */ - /* Page fault error code flags */ #define PRESENT BIT(0) #define WR BIT(1) @@ -331,11 +276,12 @@ static void dump_page_fault(z_arch_esf_t *esf) #ifdef CONFIG_X86_MMU #ifdef CONFIG_USERSPACE if (err & US) { - dump_mmu_flags(z_x86_thread_page_tables_get(_current), cr2); + z_x86_dump_mmu_flags(z_x86_thread_page_tables_get(_current), + cr2); } else #endif /* CONFIG_USERSPACE */ { - dump_mmu_flags(&z_x86_kernel_ptables, cr2); + z_x86_dump_mmu_flags(&z_x86_kernel_ptables, cr2); } #endif /* CONFIG_X86_MMU */ } diff --git a/arch/x86/core/x86_mmu.c b/arch/x86/core/x86_mmu.c index 10fe0b06541..2c3273f4032 100644 --- a/arch/x86/core/x86_mmu.c +++ b/arch/x86/core/x86_mmu.c @@ -12,6 +12,8 @@ #include #include #include +#include +LOG_MODULE_DECLARE(os); /* Despite our use of PAE page tables, we do not (and will never) actually * support PAE. Use a 64-bit x86 target if you have that much RAM. @@ -116,6 +118,59 @@ static inline void pte_update_addr(u64_t *pte, uintptr_t addr) * Not trying to capture every flag, just the most interesting stuff, * Present, write, XD, user, in typically encountered combinations. */ +static bool dump_entry_flags(const char *name, u64_t flags) +{ + if ((flags & Z_X86_MMU_P) == 0) { + LOG_ERR("%s: Non-present", name); + return false; + } + + LOG_ERR("%s: 0x%016llx %s, %s, %s", name, flags, + flags & MMU_ENTRY_WRITE ? + "Writable" : "Read-only", + flags & MMU_ENTRY_USER ? + "User" : "Supervisor", + flags & MMU_ENTRY_EXECUTE_DISABLE ? + "Execute Disable" : "Execute Enabled"); + return true; +} + +void z_x86_dump_mmu_flags(struct x86_page_tables *ptables, uintptr_t addr) +{ + u64_t entry; + +#ifdef CONFIG_X86_64 + entry = *z_x86_get_pml4e(ptables, addr); + if (!dump_entry_flags("PML4E", entry)) { + return; + } + + entry = *z_x86_pdpt_get_pdpte(z_x86_pml4e_get_pdpt(entry), addr); + if (!dump_entry_flags("PDPTE", entry)) { + return; + } +#else + /* 32-bit doesn't have anything interesting in the PDPTE except + * the present bit + */ + entry = *z_x86_get_pdpte(ptables, addr); + if ((entry & Z_X86_MMU_P) == 0) { + LOG_ERR("PDPTE: Non-present"); + return; + } +#endif + + entry = *z_x86_pd_get_pde(z_x86_pdpte_get_pd(entry), addr); + if (!dump_entry_flags(" PDE", entry)) { + return; + } + + entry = *z_x86_pt_get_pte(z_x86_pde_get_pt(entry), addr); + if (!dump_entry_flags(" PTE", entry)) { + return; + } +} + static char get_entry_code(u64_t value) { char ret; diff --git a/include/arch/x86/mmustructs.h b/include/arch/x86/mmustructs.h index f744d7699a6..d15074332e8 100644 --- a/include/arch/x86/mmustructs.h +++ b/include/arch/x86/mmustructs.h @@ -328,6 +328,14 @@ static inline u64_t *z_x86_get_pte(struct x86_page_tables *ptables, return z_x86_pt_get_pte(z_x86_get_pt(ptables, addr), addr); } +/** + * Dump out page table entries for a particular memory address + * + * For the provided memory address, dump out the P, W, XD, US flags + * at each paging level to the error log. + */ +void z_x86_dump_mmu_flags(struct x86_page_tables *ptables, uintptr_t addr); + /** * Debug function for dumping out page tables *