x86: expose APIs for dumping MMU entry flags

Add two new non-static APIs for dumping out the
page table entries for a specified memory address,
and move to the main MMU code. Has debugging uses
when trying to figure out why memory domains are not
set up correctly.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2019-11-19 12:49:39 -08:00 committed by Anas Nashif
commit e45c6eeebc
3 changed files with 66 additions and 57 deletions

View file

@ -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 */
}

View file

@ -12,6 +12,8 @@
#include <init.h>
#include <ctype.h>
#include <string.h>
#include <logging/log.h>
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;

View file

@ -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
*