arch/riscv: Print the page table structure after construction

A new Kconfig option, DEBUG_PRINT_PAGE_TABLES, is added to control this
behaviour. It is currently only available on RISC-V, but other
architectures can use it, too, should the need arise.

Change-Id: I52a863d8bc814ab3ed3a1f141d0a77edc6e4044d
Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Reviewed-on: https://review.coreboot.org/16015
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Jonathan Neuschäfer
2016-08-22 19:37:15 +02:00
committed by Martin Roth
parent e53e488cf1
commit 538e44683b
3 changed files with 86 additions and 9 deletions

View File

@@ -1127,6 +1127,14 @@ config DEBUG_BOOT_STATE
Control debugging of the boot state machine. When selected displays Control debugging of the boot state machine. When selected displays
the state boundaries in ramstage. the state boundaries in ramstage.
config DEBUG_PRINT_PAGE_TABLES
bool "Print the page tables after construction"
default n
depends on ARCH_RISCV
help
After the page tables have been built, print them on the debug
console.
endmenu endmenu
# These probably belong somewhere else, but they are needed somewhere. # These probably belong somewhere else, but they are needed somewhere.

View File

@@ -63,7 +63,7 @@ size_t pte_ppn(pte_t pte);
pte_t ptd_create(uintptr_t ppn); pte_t ptd_create(uintptr_t ppn);
pte_t pte_create(uintptr_t ppn, int prot, int user); pte_t pte_create(uintptr_t ppn, int prot, int user);
void walk_page_table(void); void print_page_table(void);
void init_vm(uintptr_t virtMemStart, uintptr_t physMemStart, uintptr_t pageTableStart); void init_vm(uintptr_t virtMemStart, uintptr_t physMemStart, uintptr_t pageTableStart);
void mstatus_init(void); // need to setup mstatus so we know we have virtual memory void mstatus_init(void); // need to setup mstatus so we know we have virtual memory

View File

@@ -23,11 +23,77 @@
pte_t* root_page_table; pte_t* root_page_table;
void walk_page_table(void) { /* Indent the following text by 2*level spaces */
// TODO: implement a full walk to make sure memory was set up static void indent(int level)
//const size_t pte_per_page = RISCV_PGSIZE/sizeof(void*); {
pte_t* t = root_page_table; int i;
printk(BIOS_DEBUG, "root_page_table: %p\n", t); for (i = 0; i < level; i++)
printk(BIOS_DEBUG, " ");
}
/*
* Convert a page table index at a given page table level to a virtual address
* offset
*/
static uintptr_t index_to_virt_addr(int index, int level)
{
/*
* Index is at most RISCV_PGLEVEL_BITS bits wide (not considering the
* leading zeroes. If level==0, the below expression thus shifts index
* into the highest bits of a 64-bit number, and then shifts it down
* with sign extension.
*
* If level>0, then the expression should work as expected, without any
* magic.
*/
return ((intptr_t)index)
<< (64 - RISCV_PGLEVEL_BITS - level * RISCV_PGLEVEL_BITS)
>> (64 - VA_BITS);
}
/* Dump the page table structures to the console -- helper function */
static void print_page_table_at(pte_t *pt, intptr_t virt_addr, int level)
{
int i;
indent(level);
printk(BIOS_DEBUG, "Level %d page table at 0x%p\n", level, pt);
for (i = 0; i < RISCV_PGSIZE / sizeof(pte_t); i++) {
char urwx[8];
uintptr_t pointer;
intptr_t next_virt_addr;
if (!(pt[i] & PTE_V))
continue;
urwx[0] = (pt[i] & PTE_U)? 'u' : '-';
urwx[1] = (pt[i] & PTE_R)? 'r' : '-';
urwx[2] = (pt[i] & PTE_W)? 'w' : '-';
urwx[3] = (pt[i] & PTE_X)? 'x' : '-';
urwx[4] = '\0';
next_virt_addr = virt_addr + index_to_virt_addr(i, level);
pointer = ((uintptr_t)pt[i] >> 10) << RISCV_PGSHIFT;
indent(level + 1);
printk(BIOS_DEBUG, "Valid PTE at index %d (0x%016zx -> 0x%zx), ",
i, (size_t) next_virt_addr, (size_t) pointer);
if (PTE_TABLE(pt[i]))
printk(BIOS_DEBUG, "page table\n");
else
printk(BIOS_DEBUG, "protections %s\n", urwx);
if (PTE_TABLE(pt[i])) {
print_page_table_at((pte_t *)pointer, next_virt_addr, level + 1);
}
}
}
/* Print the page table structures to the console */
void print_page_table(void) {
print_page_table_at(root_page_table, 0, 0);
} }
void flush_tlb(void) void flush_tlb(void)
@@ -124,14 +190,17 @@ void initVirtualMemory(void) {
uintptr_t pageTableStart = 0x1400000; uintptr_t pageTableStart = 0x1400000;
init_vm(virtualStart, physicalStart, pageTableStart); init_vm(virtualStart, physicalStart, pageTableStart);
mb(); mb();
#if IS_ENABLED(CONFIG_DEBUG_PRINT_PAGE_TABLES)
printk(BIOS_DEBUG, "Finished initializing virtual memory, starting walk...\n"); printk(BIOS_DEBUG, "Finished initializing virtual memory, starting walk...\n");
walk_page_table(); print_page_table();
#else
printk(BIOS_DEBUG, "Finished initializing virtual memory\n");
#endif
} }
void mstatus_init(void) void mstatus_init(void)
{ {
// supervisor support is required
uintptr_t ms = 0; uintptr_t ms = 0;
ms = INSERT_FIELD(ms, MSTATUS_FS, 3); ms = INSERT_FIELD(ms, MSTATUS_FS, 3);
ms = INSERT_FIELD(ms, MSTATUS_XS, 3); ms = INSERT_FIELD(ms, MSTATUS_XS, 3);