Skip to content

Commit

Permalink
WIP riscv32 supervisor mode
Browse files Browse the repository at this point in the history
Kinda a fatal flaw with the way riscv assumes physmap starts at address
0, so will require some rethinking, probably
  • Loading branch information
travisg committed May 24, 2024
1 parent 7791ec0 commit 94bce26
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 28 deletions.
2 changes: 2 additions & 0 deletions arch/riscv/include/arch/riscv/asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
#define REGOFF(x) ((x) * 4)
#define STR sw
#define LDR lw
#define RISCV_XLEN_BYTES_LOG 2
#else
#define REGOFF(x) ((x) * 8)
#define STR sd
#define LDR ld
#define RISCV_XLEN_BYTES_LOG 3
#endif

#define RISCV_XLEN_BYTES (__riscv_xlen / 8)
Expand Down
12 changes: 5 additions & 7 deletions arch/riscv/include/arch/riscv/mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,12 @@
#ifndef ASSEMBLY
#include <stdint.h>
#include <arch/defines.h>
#include <lk/utils.h>

// RISC-V specific mmu #defines and structures here
typedef uintptr_t riscv_pte_t;
#endif

#define KB (1024UL)
#define MB (1024UL*1024UL)
#define GB (1024UL*1024UL*1024UL)

// some constants based on our particular implementation
#if RISCV_MMU == 48
#define RISCV_MMU_PT_LEVELS 4
Expand All @@ -44,7 +41,7 @@ typedef uintptr_t riscv_pte_t;
#define RISCV_MMU_PT_LEVELS 2
#define RISCV_MMU_PT_SHIFT 10
#define RISCV_MMU_PT_ENTRIES 1024 // 1 << PT_SHIFT
#define RISCV_MMU_CANONICAL_MASK UINT32_MASK
#define RISCV_MMU_CANONICAL_MASK UINT32_MAX
#define RISCV_MMU_PPN_BITS 32
#define RISCV_MMU_PHYSMAP_BASE_VIRT (KERNEL_ASPACE_BASE)
#define RISCV_MMU_PHYSMAP_PAGE_SIZE (1UL << 30)
Expand All @@ -57,8 +54,9 @@ typedef uintptr_t riscv_pte_t;

// number of page table entries for the kernel and user half
// TODO: compute directly from KERNEL/USER_ASPACE_SIZE
#define RISCV_MMU_USER_PT_ENTRIES 256
#define RISCV_MMU_KERNEL_PT_ENTRIES 256
#define RISCV_MMU_USER_PT_ENTRIES (RISCV_MMU_PT_ENTRIES / 2)
#define RISCV_MMU_KERNEL_PT_ENTRIES (RISCV_MMU_PT_ENTRIES / 2)
#define RISCV_MMU_KERNEL_PT_ENTRY (RISCV_MMU_USER_PT_ENTRIES)

// page table bits
#define RISCV_PTE_V (1 << 0) // valid
Expand Down
12 changes: 5 additions & 7 deletions arch/riscv/mmu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,23 @@

#include <kernel/vm.h>

#if __riscv_xlen == 32
#error "32 bit mmu not supported yet"
#endif

// global, generally referenced in start.S

// the one main kernel top page table, used by the kernel address space
// when no user space is active. bottom user space parts are empty.
riscv_pte_t kernel_pgtable[512] __ALIGNED(PAGE_SIZE);
riscv_pte_t kernel_pgtable[RISCV_MMU_PT_ENTRIES] __ALIGNED(PAGE_SIZE);
paddr_t kernel_pgtable_phys; // filled in by start.S

// trampoline top level page table is like the kernel page table but additionally
// holds an identity map of the bottom RISCV_MMU_PHYSMAP_SIZE bytes of ram.
// used at early bootup and when starting secondary processors.
riscv_pte_t trampoline_pgtable[512] __ALIGNED(PAGE_SIZE);
riscv_pte_t trampoline_pgtable[RISCV_MMU_PT_ENTRIES] __ALIGNED(PAGE_SIZE);
paddr_t trampoline_pgtable_phys; // filled in by start.S

// pre-allocate kernel 2nd level page tables.
// this makes it very easy to keep user space top level address space page tables
// in sync, since they can simply take a copy of the kernel ones.
riscv_pte_t kernel_l2_pgtable[512][RISCV_MMU_KERNEL_PT_ENTRIES] __ALIGNED(PAGE_SIZE);
riscv_pte_t kernel_l2_pgtable[RISCV_MMU_PT_ENTRIES][RISCV_MMU_KERNEL_PT_ENTRIES] __ALIGNED(PAGE_SIZE);
paddr_t kernel_l2_pgtable_phys; // filled in by start.S

// initial memory mappings. VM uses to construct mappings after the fact
Expand Down Expand Up @@ -110,6 +106,8 @@ void riscv_set_satp(uint asid, paddr_t pt) {
satp = RISCV_SATP_MODE_SV48 << RISCV_SATP_MODE_SHIFT;
#elif RISCV_MMU == 39
satp = RISCV_SATP_MODE_SV39 << RISCV_SATP_MODE_SHIFT;
#elif RISCV_MMU == 32
satp = RISCV_SATP_MODE_SV32 << RISCV_SATP_MODE_SHIFT;
#endif

// make sure the asid is in range
Expand Down
31 changes: 18 additions & 13 deletions arch/riscv/start.S
Original file line number Diff line number Diff line change
Expand Up @@ -157,31 +157,34 @@ LOCAL_FUNCTION(_mmu_init)

// store the physical address of the pgtable for future use
lla t1, trampoline_pgtable_phys
sd t0, (t1)
STR t0, (t1)

// do the same for the main kernel pgtable
lla t2, kernel_pgtable
lla t1, kernel_pgtable_phys
sd t2, (t1)
STR t2, (t1)

// and the 2nd level tables
lla t2, kernel_l2_pgtable
lla t1, kernel_l2_pgtable_phys
sd t2, (t1)
STR t2, (t1)

// compute kernel pgtable pointer (index 256)
addi t1, t0, (8 * 128)
addi t1, t1, (8 * 128)
// compute kernel pgtable pointer (index 256 or 512)
li t1, RISCV_MMU_KERNEL_PT_ENTRY
slli t1, t1, RISCV_XLEN_BYTES_LOG
add t1, t1, t0

// page table entry: address 0, A, D, G, XWR, V
li t2, (0 | (1<<7) | (1<<6) | (1<<5) | (1<<3) | (1<<2) | (1<<1) | (1<<0))
li t2, (0 | RISCV_PTE_D | RISCV_PTE_A | RISCV_PTE_G | RISCV_PTE_X | RISCV_PTE_W | RISCV_PTE_R | RISCV_PTE_V)

// num interations and increment count
#if RISCV_MMU == 48 || RISCV_MMU == 39
#if RISCV_MMU == 48 || RISCV_MMU == 39 || RISCV_MMU == 32
// RV48: map the first 512GB of the physical address space at the
// bottom of the kernel address space using a single terapage
// RV39: map the first 64GB of the physical address space at the
// bottom of the kernel address space using 64 1GB gigapages
// RV39: map the first 1GB of the physical address space at the
// bottom of the kernel address space using 1GB gigapages
li t3, RISCV_MMU_PHYSMAP_PAGE_COUNT
li t4, (RISCV_MMU_PHYSMAP_PAGE_SIZE >> 2)
#else
Expand All @@ -192,11 +195,11 @@ LOCAL_FUNCTION(_mmu_init)
// write both to t0 (index 0 of the kernel page table) and
// t1 (starting index of kernel space)
0:
sd t2, (t1)
sd t2, (t0)
STR t2, (t1)
STR t2, (t0)
add t2, t2, t4
addi t0, t0, 8
addi t1, t1, 8
addi t0, t0, RISCV_XLEN_BYTES
addi t1, t1, RISCV_XLEN_BYTES
addi t3, t3, -1
bnez t3, 0b

Expand All @@ -212,6 +215,8 @@ LOCAL_FUNCTION(_mmu_init)
li t2, (RISCV_SATP_MODE_SV48 << RISCV_SATP_MODE_SHIFT)
#elif RISCV_MMU == 39
li t2, (RISCV_SATP_MODE_SV39 << RISCV_SATP_MODE_SHIFT)
#elif RISCV_MMU == 32
li t2, (RISCV_SATP_MODE_SV32 << RISCV_SATP_MODE_SHIFT)
#else
#error implement
#endif
Expand All @@ -228,7 +233,7 @@ LOCAL_FUNCTION(_mmu_init)

// bounce to the high address
lla t0, .Lhigh_addr
ld t0, (t0)
LDR t0, (t0)
jr t0

// the full virtual address of the .Lhigh label
Expand Down
2 changes: 1 addition & 1 deletion lib/fdtwalk/helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <libfdt.h>
#include <lk/cpp.h>
#include <lk/err.h>
#include <lk/utils.h>
#include <lk/trace.h>
#include <stdio.h>
#include <sys/types.h>
Expand Down Expand Up @@ -89,7 +90,6 @@ status_t fdtwalk_setup_memory(const void *fdt, paddr_t fdt_phys, paddr_t default
/* trim size on certain platforms */
#if ARCH_ARM || (ARCH_RISCV && __riscv_xlen == 32)
/* only use the first 1GB on ARM32 */
const auto GB = 1024*1024*1024UL;
if (mem[i].base - MEMBASE > GB) {
printf("trimming memory to 1GB\n");
continue;
Expand Down
11 changes: 11 additions & 0 deletions project/qemu-virt-riscv32-supervisor-test.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# main project for qemu-riscv32
MODULES += \
app/shell
SUBARCH := 32
RISCV_MODE := supervisor

include project/virtual/test.mk
include project/virtual/fs.mk
include project/virtual/minip.mk
include project/target/qemu-virt-riscv.mk

0 comments on commit 94bce26

Please sign in to comment.