Ronald G. Minnich (rminnich@gmail.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17233
-gerrit
commit 051344c46114ce4906edff89e6b5dc6930b91f17 Author: Ronald G. Minnich rminnich@gmail.com Date: Fri Nov 4 11:27:25 2016 -0700
riscv: map first 2GiB of physical memory at the top of virtual address space
We were mapping physical to virtual 1:1, which makes no sense; most kernels want to start at high negative address space.
Doing it this way ensures that we're following the intent of the RISCV designers, i.e that virtual addresses are correct at the start; and that the kernel does not have to unmap the low physical addresses once it starts.
Change-Id: I8c577ad885891b4c33c20077995abbd90f355f1c Signed-off-by: Ronald G. Minnich rminnich@gmail.com --- src/arch/riscv/virtual_memory.c | 43 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-)
diff --git a/src/arch/riscv/virtual_memory.c b/src/arch/riscv/virtual_memory.c index 999d73c..7091f02 100644 --- a/src/arch/riscv/virtual_memory.c +++ b/src/arch/riscv/virtual_memory.c @@ -168,12 +168,40 @@ void init_vm(uintptr_t virtMemStart, uintptr_t physMemStart, pte_t *sbi_pt)
// IO space. root_pt[0] = pte_create(0, PTE_W|PTE_R, 0); - root_pt[1] = pte_create(0x40000000>>RISCV_PGSHIFT, + root_pt[1] = pte_create(0x40000000 >> RISCV_PGSHIFT, PTE_W|PTE_R, 0);
// Start of RAM - root_pt[2] = pte_create(0x80000000>>RISCV_PGSHIFT, - PTE_W|PTE_R, 0); + // + // A RISCV goal is that Machine or Hypervisor modes be able + // start a Supervisor (kernel) at the C entry point. The + // intent is that firmware creates the virtual memory maps for + // the kernel to use. + // + // Question: what is the virtual address of physical memory + // for a kernel? Hey, glad you asked! In most kernels out + // there, physical memory is mapped at the top of the virtual + // address space. The express intent of the RISCV designers + // (I asked them) is that we be able to enter a kernel at + // main() in C, with no assembly needed. + // + // This is a neat idea that may not quite work out. For + // example: where's the stack go? Once you start in + // Supervisor mode, you are using virtual addresses set up by + // coreboot. So you can't use the coreboot stack, it's mapped + // to low physical addresses. You *should* not use the + // coreboot stack, your kernel may need it in a different + // place. So the kernel needs to change the stack, in ... a + // bit of startup assembly code, what else? Oh well. Map + // physical to high virtual. It's the most common way to + // go. Kernels that want to put kernel virtual addresses based + // at 0 will need to fixup page tables in ... a bit of startup + // assembly code :-) + // + // TODO: use a constant for the number of PTEs per page, when + // (hopefully) newer RISCV toolchains define that constant. + root_pt[0x1ff] = pte_create(0x80000000 >> RISCV_PGSHIFT, + PTE_R | PTE_W | PTE_X, 0); mb(); root_page_table = root_pt; uintptr_t ptbr = ((uintptr_t) root_pt) >> RISCV_PGSHIFT; @@ -198,9 +226,14 @@ void initVirtualMemory(void) { }
// TODO: Figure out how to grab this from cbfs + // N.B. We used to map phsyical 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();