[coreboot-gerrit] Patch set updated for coreboot: RISCV: Clean up the common architectural code

Ronald G. Minnich (rminnich@gmail.com) gerrit at coreboot.org
Fri Oct 21 22:10:21 CEST 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/17058

-gerrit

commit 875f92dbf018fa72d9311e707681b2f2266b0ad3
Author: Ronald G. Minnich <rminnich at gmail.com>
Date:   Wed Oct 19 08:07:13 2016 -0700

    RISCV: Clean up the common architectural code
    
    We provide a standard payload that makes the jump from machine to
    supervisor mode; the days of kernels running in machine mode are over.
    
    We do some small tweaks to the virtual memory code. We temporarily
    disable two functions that won't work on some targets as register
    numbers changed between 1.7 and 1.9. Once lowrisc catches up
    we'll reenable them.
    
    We add the PAGETABLES to the memlayout.ld and use _pagetables in the virtual
    memory setup code.
    
    We now use the _stack and _estack from memlayout so we know where things are.
    As time goes on maybe we can kill all the magic numbers.
    
    I'm getting a confusing error on the bootblock that I hope Julius can
    explain to me:
        LINK       cbfs/fallback/bootblock.debug
    /home/rminnich/projects/riscv/coreboot/util/crossgcc/xgcc/bin/riscv64-elf-ld.bfd: build/cbfs/fallback/bootblock.debug:
     warning: allocated section `.data' not in segment
        OBJCOPY    cbfs/fallback/bootblock.elf
    /home/rminnich/projects/riscv/coreboot/util/crossgcc/xgcc/bin/riscv64-elf-objcopy: build/cbfs/fallback/stEfxjQH:
    warning: allocated section `.data' not in segment
    /home/rminnich/projects/riscv/coreboot/util/crossgcc/xgcc/bin/riscv64-elf-objcopy: build/cbfs/fallback/st5PV1nG:
    warning: allocated section `.data' not in segment
        OBJCOPY    bootblock.raw.bin
    /home/rminnich/projects/riscv/coreboot/util/crossgcc/xgcc/bin/riscv64-elf-objcopy: build/cbfs/fallback/bootblock.elf.tmp:
     warning: allocated section `.data' not in segment
    
    Also:
    Performing operation on 'BOOTBLOCK' region...
    W: Written area will abut bottom of target region: any unused space will keep its current contents
    
    Couple of WTFs here, any advice anyone?
    
    Change-Id: I6caadfa9627fa35e31580492be01d4af908d31d9
    Signed-off-by: Ronald G. Minnich <rminnich at gmail.com>
---
 src/arch/riscv/Makefile.inc                      |  1 +
 src/arch/riscv/boot.c                            |  3 ++
 src/arch/riscv/bootblock.S                       | 11 +++---
 src/arch/riscv/include/arch/memlayout.h          |  4 +--
 src/arch/riscv/include/vm.h                      | 13 ++-----
 src/arch/riscv/payload.S                         | 28 +++++++++++++++
 src/arch/riscv/virtual_memory.c                  | 46 ++++++++++++++++--------
 src/mainboard/emulation/qemu-riscv/memlayout.ld  |  1 +
 src/mainboard/emulation/spike-riscv/memlayout.ld |  3 +-
 9 files changed, 78 insertions(+), 32 deletions(-)

diff --git a/src/arch/riscv/Makefile.inc b/src/arch/riscv/Makefile.inc
index 4bab459..cf6ce99 100644
--- a/src/arch/riscv/Makefile.inc
+++ b/src/arch/riscv/Makefile.inc
@@ -96,6 +96,7 @@ ramstage-y += misc.c
 ramstage-y += boot.c
 ramstage-y += tables.c
 ramstage-y += sbi.S
+ramstage-y += payload.S
 ramstage-y += \
 	$(top)/src/lib/memchr.c \
 	$(top)/src/lib/memcmp.c \
diff --git a/src/arch/riscv/boot.c b/src/arch/riscv/boot.c
index 7435490..8464bac 100644
--- a/src/arch/riscv/boot.c
+++ b/src/arch/riscv/boot.c
@@ -13,6 +13,7 @@
  * GNU General Public License for more details.
  */
 
+#include <lib.h>
 #include <program_loading.h>
 #include <vm.h>
 #include <arch/encoding.h>
@@ -21,9 +22,11 @@
 void arch_prog_run(struct prog *prog)
 {
 	void (*doit)(void *) = prog_entry(prog);
+	void riscvpayload(void);
 
 	if (ENV_RAMSTAGE && prog_type(prog) == PROG_PAYLOAD) {
 		initVirtualMemory();
+		riscvpayload();
 	}
 
 	doit(prog_entry_arg(prog));
diff --git a/src/arch/riscv/bootblock.S b/src/arch/riscv/bootblock.S
index 514511e..63df92b 100644
--- a/src/arch/riscv/bootblock.S
+++ b/src/arch/riscv/bootblock.S
@@ -19,13 +19,16 @@
 
 .section ".text._start", "ax", %progbits
 
+.globl _stack
+.global _estack
 .globl _start
 _start:
 
-#define STACK_START 0x80800000 /* 2GiB + 8MiB */
-#define STACK_SIZE  0x0000fff0
 
-	li sp, STACK_START + STACK_SIZE
+
+	# N.B. This only works on low 4G of the address space
+	# and the stack must be page-aligned.
+	la sp, _estack
 
 	# make room for HLS and initialize it
 	addi sp, sp, -64 // MENTRY_FRAME_SIZE
@@ -33,7 +36,7 @@ _start:
 	call hls_init
 
 	# poison the stack
-	li t1, STACK_START
+	la t1, _stack
 	li t0, 0xdeadbeef
 	sd t0, 0(t1)
 
diff --git a/src/arch/riscv/include/arch/memlayout.h b/src/arch/riscv/include/arch/memlayout.h
index 4d2af59..5d01141 100644
--- a/src/arch/riscv/include/arch/memlayout.h
+++ b/src/arch/riscv/include/arch/memlayout.h
@@ -18,8 +18,8 @@
 #ifndef __ARCH_MEMLAYOUT_H
 #define __ARCH_MEMLAYOUT_H
 
-/* TODO: Double-check that that's the correct alignment for our ABI. */
-#define STACK(addr, size) REGION(stack, addr, size, 8)
+#define STACK(addr, size) REGION(stack, addr, size, 4096)
+#define PAGETABLES(addr, size) REGION(pagetables, addr, size, 4096)
 
 /* TODO: Need to add DMA_COHERENT region like on ARM? */
 
diff --git a/src/arch/riscv/include/vm.h b/src/arch/riscv/include/vm.h
index bee2ed4..c3de47a 100644
--- a/src/arch/riscv/include/vm.h
+++ b/src/arch/riscv/include/vm.h
@@ -37,16 +37,6 @@
 #define VA_BITS 39
 #define MEGAPAGE_SIZE (SUPERPAGE_SIZE << RISCV_PGLEVEL_BITS)
 
-#define PROT_READ 1
-#define PROT_WRITE 2
-#define PROT_EXEC 4
-
-#define MAP_PRIVATE 0x2
-#define MAP_FIXED 0x10
-#define MAP_ANONYMOUS 0x20
-#define MAP_POPULATE 0x8000
-#define MREMAP_FIXED 0x2
-
 #define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1)))
 #define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))))
 
@@ -66,7 +56,8 @@ pte_t pte_create(uintptr_t ppn, int prot, int user);
 
 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,
+		pte_t *pageTableStart);
 void mstatus_init(void); // need to setup mstatus so we know we have virtual memory
 
 void flush_tlb(void);
diff --git a/src/arch/riscv/payload.S b/src/arch/riscv/payload.S
new file mode 100644
index 0000000..f66f729
--- /dev/null
+++ b/src/arch/riscv/payload.S
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+	.global riscvpayload
+riscvpayload:
+	/* Jump to 0xffffffff81000000 in S-mode */
+	li t0, 0xffffffff81000000
+	csrw mepc, t0
+	csrr t0, mstatus
+	li t1, ~(3<<11)
+	and t0, t0, t1
+	li t2,  (1<<11)
+	or t0, t0, t2
+	csrw mstatus, t0
+
+	// We're still in toolchain no mans land.
+	.word 0x30200073
+	//mret
diff --git a/src/arch/riscv/virtual_memory.c b/src/arch/riscv/virtual_memory.c
index be8b488..3cc4505 100644
--- a/src/arch/riscv/virtual_memory.c
+++ b/src/arch/riscv/virtual_memory.c
@@ -22,6 +22,7 @@
 #include <stdint.h>
 #include <vm.h>
 
+extern pte_t _pagetables[];
 pte_t* root_page_table;
 
 /* Indent the following text by 2*level spaces */
@@ -94,7 +95,7 @@ static void print_page_table_at(pte_t *pt, intptr_t virt_addr, int level)
 
 /* Print the page table structures to the console */
 void print_page_table(void) {
-	print_page_table_at(root_page_table, 0, 0);
+	print_page_table_at((void *)(read_csr(sptbr) << RISCV_PGSHIFT), 0, 0);
 }
 
 void flush_tlb(void)
@@ -115,17 +116,17 @@ pte_t ptd_create(uintptr_t ppn)
 pte_t pte_create(uintptr_t ppn, int prot, int user)
 {
 	pte_t pte = (ppn << PTE_PPN_SHIFT) | PTE_R | PTE_V;
-	if (prot & PROT_WRITE)
+	if (prot & PTE_W)
 		pte |= PTE_W;
-	if (prot & PROT_EXEC)
+	if (prot & PTE_X)
 		pte |= PTE_X;
 	if (user)
 		pte |= PTE_U;
 	return pte;
 }
 
-void init_vm(uintptr_t virtMemStart, uintptr_t physMemStart, uintptr_t pageTableStart) {
-	pte_t* sbi_pt = (pte_t*) pageTableStart;
+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
@@ -147,21 +148,32 @@ void init_vm(uintptr_t virtMemStart, uintptr_t physMemStart, uintptr_t pageTable
 		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);
-		middle_pt[l2_idx] = pte_create(paddr >> RISCV_PGSHIFT, PROT_READ|PROT_WRITE|PROT_EXEC, 0);
+		middle_pt[l2_idx] = pte_create(paddr >> RISCV_PGSHIFT,
+					       PTE_R|PTE_W|PTE_X, 0);
 	}
 
 	// map SBI at top of vaddr space
-	uintptr_t num_sbi_pages = 1; // only need to map a single page for sbi interface
+	// only need to map a single page for sbi interface
+	uintptr_t num_sbi_pages = 1;
 	uintptr_t sbiStartAddress = (uintptr_t) &sbi_page;
 	uintptr_t sbiAddr = sbiStartAddress;
 	for (uintptr_t i = 0; i < num_sbi_pages; i++) {
 		uintptr_t idx = (1 << RISCV_PGLEVEL_BITS) - num_sbi_pages + i;
-		sbi_pt[idx] = pte_create(sbiAddr >> RISCV_PGSHIFT, PROT_READ|PROT_EXEC, 0);
+		sbi_pt[idx] = pte_create(sbiAddr >> RISCV_PGSHIFT,
+					 PTE_R|PTE_X, 0);
 		sbiAddr += RISCV_PGSIZE;
 	}
 	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);
+
+	// 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;
@@ -185,12 +197,13 @@ void initVirtualMemory(void) {
 		printk(BIOS_DEBUG, "-----------------------------\n");
 	}
 
+	// TODO: Figure out how to grab this from cbfs
 	printk(BIOS_DEBUG, "Initializing virtual memory...\n");
-	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);
+	uintptr_t physicalStart = 0x81000000;
+	uintptr_t virtualStart = 0xffffffff81000000;
+	init_vm(virtualStart, physicalStart, _pagetables);
 	mb();
+	flush_tlb();
 
 #if IS_ENABLED(CONFIG_DEBUG_PRINT_PAGE_TABLES)
 	printk(BIOS_DEBUG, "Finished initializing virtual memory, starting walk...\n");
@@ -220,7 +233,12 @@ void mstatus_init(void)
 			| (1 << CAUSE_USER_ECALL)
 	);
 
+
 	/* Enable all user/supervisor-mode counters */
-	write_csr(mscounteren, 0b111);
-	write_csr(mucounteren, 0b111);
+	/* We'll turn these on once lowrisc gets their bitstream up to
+	 * 1.9. Right now there's no agreement on the values for these
+	 * architectural registers.
+	 */
+	//write_csr(mscounteren, 0b111);
+	//write_csr(mucounteren, 0b111);
 }
diff --git a/src/mainboard/emulation/qemu-riscv/memlayout.ld b/src/mainboard/emulation/qemu-riscv/memlayout.ld
index 615d1f2..8cc6d41 100644
--- a/src/mainboard/emulation/qemu-riscv/memlayout.ld
+++ b/src/mainboard/emulation/qemu-riscv/memlayout.ld
@@ -24,5 +24,6 @@ SECTIONS
 	ROMSTAGE(0x20000, 128K)
 	STACK(0x40000, 0x3ff00)
 	PRERAM_CBMEM_CONSOLE(0x80000, 8K)
+	PAGETABLES(0x80000+8K, 60K)
 	RAMSTAGE(0x100000, 16M)
 }
diff --git a/src/mainboard/emulation/spike-riscv/memlayout.ld b/src/mainboard/emulation/spike-riscv/memlayout.ld
index 8d35a64..8596723 100644
--- a/src/mainboard/emulation/spike-riscv/memlayout.ld
+++ b/src/mainboard/emulation/spike-riscv/memlayout.ld
@@ -23,7 +23,8 @@ SECTIONS
 {
 	DRAM_START(START)
 	BOOTBLOCK(START, 64K)
-	STACK(START + 8M, 64K)
+	STACK(START + 8M, 4K)
+	PAGETABLES(START + 8M + 4K, 60K)
 	ROMSTAGE(START + 8M + 64K, 128K)
 	PRERAM_CBMEM_CONSOLE(START + 8M + 192k, 8K)
 	RAMSTAGE(START + 8M + 200K, 256K)



More information about the coreboot-gerrit mailing list