[coreboot-gerrit] Patch set updated for coreboot: riscv: map first 4GiB of physical address space

Ronald G. Minnich (rminnich@gmail.com) gerrit at coreboot.org
Fri Nov 18 21:27:34 CET 2016


Ronald G. Minnich (rminnich at gmail.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17403

-gerrit

commit 7089067c22f2ecd233f0300d581d80d377ac5bf7
Author: Ronald G. Minnich <rminnich at gmail.com>
Date:   Fri Nov 4 11:27:25 2016 -0700

    riscv: map first 4GiB of physical address space
    
    o The first 4G of physical address space is now mapped at 0.
    o The first 4G of physical address space is now mapped at 1 << 38.
    o The first 4G of physical address space is now mapped at
      the top of memory minus 4G.
    
    Of these, we hope to remove the last one once the gcc toolchain
    can handle linking programs that can run at "top 33 bits
    of address not all ones (but bit 63 set)".
    
    Change-Id: I77b151720001bddad5563b0f8e1279abcea056fa
---
 src/arch/riscv/virtual_memory.c | 88 +++++++++++++++++++++++++++++++++++------
 1 file changed, 76 insertions(+), 12 deletions(-)

diff --git a/src/arch/riscv/virtual_memory.c b/src/arch/riscv/virtual_memory.c
index 6d93bd0..b698550 100644
--- a/src/arch/riscv/virtual_memory.c
+++ b/src/arch/riscv/virtual_memory.c
@@ -38,6 +38,7 @@ static int delegate = 0
 	| (1 << CAUSE_FAULT_STORE)
 	| (1 << CAUSE_USER_ECALL)
 	;
+
 pte_t* root_page_table;
 
 /* Indent the following text by 2*level spaces */
@@ -140,11 +141,58 @@ pte_t pte_create(uintptr_t ppn, int prot, int user)
 	return pte;
 }
 
+// The current RISCV *physical* addrss space is this:
+// o 0 - 2 GiB: miscellaneous IO devices
+// o 2 GiB - 4 GiB DRAM
+// o top 2048 bytes of memory: SBI (which we round out to a 4K page)
+// We have determined, also, that if code references a physical address
+// not backed by a device, we'll take a fault. In other words, we don't
+// need to finely map the memory-mapped devices as we would on an x86.
+// We can use GiB mappings for the IO space and we will take a trap
+// if we reference hardware that does not exist.
+//
+// The intent of the RISCV designers is that pages be set up in M mode
+// for lower privilege software. They have also told me that they
+// expect, unlike other platforms, that next level software use these
+// page tables.  Some kernels (Linux) prefer the old fashioned model,
+// where kernel starts with an identity (ID) map and sets up page tables as
+// it sees fit.  Other kernels (harvey) are fine with using whatever
+// firmware sets up.  We need to accommodate both. So, we set up the
+// identity map for Linux, but also set up the map for kernels that
+// are more willing to conform to the RISCV model.  The map is as
+// follows:
+//
+// ID map: map IO space and all of DRAM 1:1 using 1 GiB PTEs
+// I.e. we use 1 GiB PTEs for 4 GiB.
+// Linux/BSD uses this mapping just enough to replace it.
+//
+// The SBI page is the last page in the 64 bit address space.
+// map that using the middle_pts shown below.
+//
+// Top 2G map, including SBI page: map the 2 Gib - 4 GiB of physical
+// address space to 0xffffffff_80000000. This will be needed until the
+// GNU toolchain can compile code to run at 0xffffffc000000000,
+// i.e. the start of Sv39.
+//
+// Only Harvey/Plan 9 uses this Mapping, and temporarily.  It can
+// never be full removed as we need the 4KiB mapping for the SBI page.
+//
+// standard RISCV map long term: Map IO space, and all of DRAM, to the *lowest*
+// possible negative address for this implementation,
+// e.g. 0xffffffc000000000 for Sv39 CPUs. For now we can use GiB PTEs.
+//
+// RISCV map for now: map IO space, and all of DRAM, starting at
+// 0xffff_ffc0_0000_0000, i.e. just as for Sv39.
+//
+// It is our intent on Harvey (and eventually Akaros) that we use
+// this map, once the toolchain can correctly support it.
+// We have tested this arrangement and it lets us boot harvey to user mode.
 void init_vm(uintptr_t virtMemStart, uintptr_t physMemStart, pte_t *sbi_pt)
 {
 	memset(sbi_pt, 0, RISCV_PGSIZE);
 	// need to leave room for sbi page
-	uintptr_t memorySize = 0x7F000000; // 0xFFF... - 0xFFFFFFFF81000000 - RISCV_PGSIZE
+	// 0xFFF... - 0xFFFFFFFF81000000 - RISCV_PGSIZE
+	intptr_t memorySize = 0x7F000000;
 
 	// middle page table
 	pte_t* middle_pt = (void*)sbi_pt + RISCV_PGSIZE;
@@ -181,14 +229,22 @@ void init_vm(uintptr_t virtMemStart, uintptr_t physMemStart, pte_t *sbi_pt)
 	pte_t* sbi_pte = middle_pt + ((num_middle_pts << RISCV_PGLEVEL_BITS)-1);
 	*sbi_pte = ptd_create((uintptr_t)sbi_pt >> RISCV_PGSHIFT);
 
-	// IO space.
-	root_pt[0] = pte_create(0, PTE_W|PTE_R, 0);
-	root_pt[1] = pte_create(0x40000000>>RISCV_PGSHIFT,
-				PTE_W|PTE_R, 0);
+	// IO space. Identity mapped.
+	root_pt[0x000] = pte_create(0x00000000 >> RISCV_PGSHIFT,
+				PTE_R | PTE_W, 0);
+	root_pt[0x001] = pte_create(0x40000000 >> RISCV_PGSHIFT,
+				PTE_R | PTE_W, 0);
+	root_pt[0x002] = pte_create(0x80000000 >> RISCV_PGSHIFT,
+				PTE_R | PTE_W | PTE_X, 0);
+	root_pt[0x003] = pte_create(0xc0000000 >> RISCV_PGSHIFT,
+				PTE_R | PTE_W | PTE_X, 0);
+
+	// Negative address space map at 0xffffffc000000000
+	root_pt[0x100] = root_pt[0];
+	root_pt[0x101] = root_pt[1];
+	root_pt[0x102] = root_pt[2];
+	root_pt[0x103] = root_pt[3];
 
-	// Start of RAM
-	root_pt[2] = pte_create(0x80000000>>RISCV_PGSHIFT,
-				PTE_W|PTE_R, 0);
 	mb();
 	root_page_table = root_pt;
 	uintptr_t ptbr = ((uintptr_t) root_pt) >> RISCV_PGSHIFT;
@@ -213,9 +269,14 @@ void initVirtualMemory(void) {
 	}
 
 	// TODO: Figure out how to grab this from cbfs
+	// N.B. We used to map physical from 0x81000000,
+	// but since kernels need to be able to see the page tables
+	// created by firmware, we're going to map from start of RAM.
+	// All this is subject to change as we learn more. Much
+	// about RISCV is still in flux.
 	printk(BIOS_DEBUG, "Initializing virtual memory...\n");
-	uintptr_t physicalStart = 0x81000000;
-	uintptr_t virtualStart = 0xffffffff81000000;
+	uintptr_t physicalStart = 0x80000000;
+	uintptr_t virtualStart = 0xffffffff80000000;
 	init_vm(virtualStart, physicalStart, (pte_t *)_pagetables);
 	mb();
 	flush_tlb();
@@ -245,6 +306,9 @@ void mstatus_init(void)
 	 * 1.9. Right now there's no agreement on the values for these
 	 * architectural registers.
 	 */
-	//write_csr(mscounteren, 0b111);
-	//write_csr(mucounteren, 0b111);
+	// write_csr(mscounteren, 0b111);
+	// write_csr(mucounteren, 0b111);
+
+	// for SPIKE:
+	// write_csr(/*mscounteren*/0x321, 0b111);
 }



More information about the coreboot-gerrit mailing list