x86: additional debug output for page faults

Page faults will additionally dump out some interesting
page directory and page table flags for the faulting
memory address.

Intended to help determine whether the page tables have been
configured incorrectly as we enable memory protection features.

This only happens if CONFIG_EXCEPTION_DEBUG is turned on.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-08-01 13:04:43 -07:00 committed by Anas Nashif
commit 9ffaaae5ad
3 changed files with 61 additions and 0 deletions

View file

@ -212,6 +212,29 @@ EXC_FUNC_NOCODE(IV_MACHINE_CHECK);
#define PK BIT(5)
#define SGX BIT(15)
#ifdef CONFIG_X86_MMU
static void dump_entry_flags(u32_t flags)
{
printk("0x%03x %s %s %s\n", flags,
flags & MMU_ENTRY_PRESENT ? "Present" : "Non-present",
flags & MMU_ENTRY_WRITE ? "Writable" : "Read-only",
flags & MMU_ENTRY_USER ? "User" : "Supervisor");
}
static void dump_mmu_flags(void *addr)
{
u32_t pde_flags, pte_flags;
_x86_mmu_get_flags(addr, &pde_flags, &pte_flags);
printk("PDE: ");
dump_entry_flags(pde_flags);
printk("PTE: ");
dump_entry_flags(pte_flags);
}
#endif
FUNC_NORETURN void page_fault_handler(const NANO_ESF *pEsf)
{
u32_t err, cr2;
@ -227,6 +250,10 @@ FUNC_NORETURN void page_fault_handler(const NANO_ESF *pEsf)
err & ID ? "executed" : (err & WR ? "wrote" : "read"),
cr2);
#ifdef CONFIG_X86_MMU
dump_mmu_flags((void *)cr2);
#endif
_NanoFatalErrorHandler(_NANO_ERR_CPU_EXCEPTION, pEsf);
}
_EXCEPTION_CONNECT_CODE(page_fault_handler, IV_PAGE_FAULT);

View file

@ -65,6 +65,26 @@ static inline u32_t check_pte_flags(union x86_mmu_pte pte,
}
void _x86_mmu_get_flags(void *addr, u32_t *pde_flags, u32_t *pte_flags)
{
int pde_index, pte_index;
union x86_mmu_pde *pde;
union x86_mmu_pte *pte;
struct x86_mmu_page_table *pt;
pde_index = MMU_PDE_NUM(addr);
pte_index = MMU_PAGE_NUM(addr);
pde = &X86_MMU_PD->entry[pde_index];
pt = (struct x86_mmu_page_table *)(pde->pt.page_table << 12);
pte = &pt->entry[pte_index];
*pde_flags = pde->pt.value & ~MMU_PDE_PAGE_TABLE_MASK;
*pte_flags = pte->value & ~MMU_PTE_PAGE_MASK;
}
/**
* @brief check page table entry flags
*

View file

@ -589,6 +589,20 @@ extern u32_t __mmu_tables_start;
#define X86_MMU_PD ((struct x86_mmu_page_directory *)\
(void *)&__mmu_tables_start)
/**
* @brief Fetch page table flags for a particular page
*
* Given a memory address, return the flags for the containing page's
* PDE and PTE entries. Intended for debugging.
*
* @param addr Memory address to example
* @param pde_flags Output parameter for page directory entry flags
* @param pte_flags Output parameter for page table entry flags
*/
void _x86_mmu_get_flags(void *addr, u32_t *pde_flags, u32_t *pte_flags);
/**
* @brief set flags in the MMU page tables
*