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:
parent
62a0cd246d
commit
9ffaaae5ad
3 changed files with 61 additions and 0 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue