[coreboot-gerrit] New patch to review for coreboot: [WIP] arch/riscv: Virtual memory fixes

Jonathan Neuschäfer (j.neuschaefer@gmx.net) gerrit at coreboot.org
Mon Aug 1 23:05:56 CEST 2016


Jonathan Neuschäfer (j.neuschaefer at gmx.net) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16015

-gerrit

commit 777c596251c00fdb4ede33284c590860e1843c8d
Author: Jonathan Neuschäfer <j.neuschaefer at gmx.net>
Date:   Mon Aug 1 19:42:27 2016 +0200

    [WIP] arch/riscv: Virtual memory fixes
    
    - I implemented a function to walk the whole pagetable structure.
      Ideally we'd walk the pagetable for a specific virtual address
      whenever a trap from a lower-than-machine mode is received, so that
      pagetable misconfigurations are more easily caught.
    - plus some other fixes that I need to split up.
    
    Change-Id: I52a863d8bc814ab3ed3a1f141d0a77edc6e4044d
    Signed-off-by: Jonathan Neuschäfer <j.neuschaefer at gmx.net>
---
 src/arch/riscv/virtual_memory.c | 69 +++++++++++++++++++++++++++++++++++------
 1 file changed, 59 insertions(+), 10 deletions(-)

diff --git a/src/arch/riscv/virtual_memory.c b/src/arch/riscv/virtual_memory.c
index cda9057..eae0b26 100644
--- a/src/arch/riscv/virtual_memory.c
+++ b/src/arch/riscv/virtual_memory.c
@@ -20,13 +20,64 @@
 #include <stdint.h>
 #include <console/console.h>
 
+/* walk_page_table(address) */
+
 pte_t* root_page_table;
 
+static void indent(int level)
+{
+	int i;
+	for (i = 0; i < level; i++)
+		printk(BIOS_DEBUG, "  ");
+}
+
+static uintptr_t index_to_virt_addr(int index, int level)
+{
+	return ((intptr_t)index)
+		<< (64 - RISCV_PGLEVEL_BITS - level * RISCV_PGLEVEL_BITS)
+		>> (64 - VA_BITS);
+}
+
+static void walk_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);
+
+		indent(level+1);
+		printk(BIOS_DEBUG, "Valid PTE at index %d (0x%016zx), ",
+				i, (size_t) next_virt_addr);
+		if (PTE_TABLE(pt[i]))
+			printk(BIOS_DEBUG, "page table\n");
+		else
+			printk(BIOS_DEBUG, "protections %s\n", urwx);
+
+		if (PTE_TABLE(pt[i])) {
+			pointer = ((uintptr_t)pt[i] >> 10) << RISCV_PGSHIFT;
+			walk_page_table_at((pte_t *)pointer, next_virt_addr, level + 1);
+		}
+	}
+}
+
 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);
+	walk_page_table_at(root_page_table, 0, 0);
 }
 
 void flush_tlb(void)
@@ -70,7 +121,7 @@ void init_vm(uintptr_t virtMemStart, uintptr_t physMemStart, uintptr_t pageTable
 		root_pt[(1<<RISCV_PGLEVEL_BITS)-num_middle_pts+i] = ptd_create(((uintptr_t)middle_pt >> RISCV_PGSHIFT) + i);
 
 	// fill the middle page table
-	for (uintptr_t vaddr = virtMemStart, paddr = physMemStart; paddr < memorySize; vaddr += SUPERPAGE_SIZE, paddr += SUPERPAGE_SIZE) {
+	for (uintptr_t vaddr = virtMemStart, paddr = physMemStart; paddr < physMemStart+memorySize; vaddr += SUPERPAGE_SIZE, paddr += SUPERPAGE_SIZE) {
 		int l2_shift = RISCV_PGLEVEL_BITS + RISCV_PGSHIFT;
 		size_t l2_idx = (virtMemStart >> l2_shift) & ((1 << RISCV_PGLEVEL_BITS)-1);
 		l2_idx += ((vaddr - virtMemStart) >> l2_shift);
@@ -112,9 +163,9 @@ void initVirtualMemory(void) {
 	}
 
 	printk(BIOS_DEBUG, "Initializing virtual memory...\n");
-	uintptr_t physicalStart = 0x1000000; // TODO: Figure out how to grab this from cbfs
-	uintptr_t virtualStart = 0xffffffff81000000;
-	uintptr_t pageTableStart = 0x1400000;
+	uintptr_t physicalStart = 0x90000000; // TODO: Figure out how to grab this from cbfs
+	uintptr_t virtualStart = 0xffffffff80000000;
+	uintptr_t pageTableStart = 0x91400000;
 	init_vm(virtualStart, physicalStart, pageTableStart);
 	mb();
 	printk(BIOS_DEBUG, "Finished initializing virtual memory, starting walk...\n");
@@ -123,8 +174,6 @@ void initVirtualMemory(void) {
 
 void mstatus_init(void)
 {
-	// supervisor support is required
-
 	uintptr_t ms = 0;
 	ms = INSERT_FIELD(ms, MSTATUS_PRV, PRV_M);
 	ms = INSERT_FIELD(ms, MSTATUS_PRV1, PRV_S);



More information about the coreboot-gerrit mailing list