mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
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:
parent
e53e488cf1
commit
538e44683b
3 changed files with 86 additions and 9 deletions
|
@ -1127,6 +1127,14 @@ config DEBUG_BOOT_STATE
|
|||
Control debugging of the boot state machine. When selected displays
|
||||
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
|
||||
|
||||
# These probably belong somewhere else, but they are needed somewhere.
|
||||
|
|
|
@ -63,7 +63,7 @@ size_t pte_ppn(pte_t pte);
|
|||
pte_t ptd_create(uintptr_t ppn);
|
||||
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 mstatus_init(void); // need to setup mstatus so we know we have virtual memory
|
||||
|
|
|
@ -23,11 +23,77 @@
|
|||
|
||||
pte_t* root_page_table;
|
||||
|
||||
void walk_page_table(void) {
|
||||
// TODO: implement a full walk to make sure memory was set up
|
||||
//const size_t pte_per_page = RISCV_PGSIZE/sizeof(void*);
|
||||
pte_t* t = root_page_table;
|
||||
printk(BIOS_DEBUG, "root_page_table: %p\n", t);
|
||||
/* Indent the following text by 2*level spaces */
|
||||
static void indent(int level)
|
||||
{
|
||||
int i;
|
||||
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)
|
||||
|
@ -124,14 +190,17 @@ void initVirtualMemory(void) {
|
|||
uintptr_t pageTableStart = 0x1400000;
|
||||
init_vm(virtualStart, physicalStart, pageTableStart);
|
||||
mb();
|
||||
|
||||
#if IS_ENABLED(CONFIG_DEBUG_PRINT_PAGE_TABLES)
|
||||
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)
|
||||
{
|
||||
// supervisor support is required
|
||||
|
||||
uintptr_t ms = 0;
|
||||
ms = INSERT_FIELD(ms, MSTATUS_FS, 3);
|
||||
ms = INSERT_FIELD(ms, MSTATUS_XS, 3);
|
||||
|
|
Loading…
Add table
Reference in a new issue