From 7389e46cd013e0cd23af8a6531e9e104b5a31d09 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sat, 30 Apr 2016 17:39:13 -0700 Subject: Move DRAM to high addresses --- bbl/bbl.c | 8 ++++---- bbl/bbl.lds | 2 +- machine/bits.h | 2 ++ machine/configstring.c | 3 ++- machine/emulation.c | 4 ++-- machine/encoding.h | 17 +++++++++++------ machine/fp_emulation.c | 4 ++-- machine/machine.mk.in | 1 + machine/mentry.S | 8 +++++++- machine/sbi_impl.c | 2 +- pk/file.c | 12 ++++++------ pk/mmap.c | 39 +++++++++++++++++---------------------- pk/mmap.h | 4 ++++ pk/pk.c | 2 +- pk/pk.lds | 2 +- pk/syscall.c | 22 +++++++++++----------- 16 files changed, 73 insertions(+), 59 deletions(-) diff --git a/bbl/bbl.c b/bbl/bbl.c index cd52fc1..af2483f 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -11,7 +11,7 @@ static volatile int elf_loaded; static void supervisor_vm_init() { - uintptr_t highest_va = -first_free_paddr; + uintptr_t highest_va = DRAM_BASE - first_free_paddr; mem_size = MIN(mem_size, highest_va - info.first_user_vaddr) & -MEGAPAGE_SIZE; pte_t* sbi_pt = (pte_t*)(info.first_vaddr_after_user + info.load_offset); @@ -30,7 +30,7 @@ static void supervisor_vm_init() #endif for (uintptr_t vaddr = info.first_user_vaddr, paddr = vaddr + info.load_offset, end = info.first_vaddr_after_user; - paddr < mem_size; vaddr += MEGAPAGE_SIZE, paddr += MEGAPAGE_SIZE) { + paddr < DRAM_BASE + mem_size; vaddr += MEGAPAGE_SIZE, paddr += MEGAPAGE_SIZE) { int l2_shift = RISCV_PGLEVEL_BITS + RISCV_PGSHIFT; size_t l2_idx = (info.first_user_vaddr >> l2_shift) & ((1 << RISCV_PGLEVEL_BITS)-1); l2_idx += ((vaddr - info.first_user_vaddr) >> l2_shift); @@ -39,11 +39,11 @@ static void supervisor_vm_init() // map SBI at top of vaddr space extern char _sbi_end; - uintptr_t num_sbi_pages = ((uintptr_t)&_sbi_end - 1) / RISCV_PGSIZE + 1; + uintptr_t num_sbi_pages = ((uintptr_t)&_sbi_end - DRAM_BASE - 1) / RISCV_PGSIZE + 1; assert(num_sbi_pages <= (1 << RISCV_PGLEVEL_BITS)); 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(i, PTE_TYPE_SRX_GLOBAL); + sbi_pt[idx] = pte_create((DRAM_BASE / RISCV_PGSIZE) + i, PTE_TYPE_SRX_GLOBAL); } pte_t* sbi_pte = middle_pt + ((num_middle_pts << RISCV_PGLEVEL_BITS)-1); assert(!*sbi_pte); diff --git a/bbl/bbl.lds b/bbl/bbl.lds index 5ccdf22..c06aa13 100644 --- a/bbl/bbl.lds +++ b/bbl/bbl.lds @@ -10,7 +10,7 @@ SECTIONS /*--------------------------------------------------------------------*/ /* Begining of code and text segment */ - . = 0; + . = 0x80000000; _ftext = .; PROVIDE( eprol = . ); diff --git a/machine/bits.h b/machine/bits.h index 72514ae..e550f80 100644 --- a/machine/bits.h +++ b/machine/bits.h @@ -21,11 +21,13 @@ # define SLL32 sllw # define STORE sd # define LOAD ld +# define LWU lwu # define LOG_REGBYTES 3 #else # define SLL32 sll # define STORE sw # define LOAD lw +# define LWU lw # define LOG_REGBYTES 2 #endif #define REGBYTES (1 << LOG_REGBYTES) diff --git a/machine/configstring.c b/machine/configstring.c index d2f2a84..e134398 100644 --- a/machine/configstring.c +++ b/machine/configstring.c @@ -8,6 +8,7 @@ static void query_mem(const char* config_string) query_result res = query_config_string(config_string, "ram{0{addr"); assert(res.start); uintptr_t base = get_uint(res); + assert(base == DRAM_BASE); res = query_config_string(config_string, "ram{0{size"); mem_size = get_uint(res); } @@ -46,7 +47,7 @@ static void query_harts(const char* config_string) void parse_config_string() { - const char* s = (const char*)read_csr(mcfgaddr); + const char* s = *(const char* const*)CONFIG_STRING_ADDR; query_mem(s); query_rtc(s); query_harts(s); diff --git a/machine/emulation.c b/machine/emulation.c index 70169fd..ad74fb4 100644 --- a/machine/emulation.c +++ b/machine/emulation.c @@ -75,8 +75,8 @@ void illegal_insn_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc) write_csr(mepc, mepc + 4); - extern int32_t illegal_insn_trap_table[]; - int32_t* pf = (void*)illegal_insn_trap_table + (insn & 0x7c); + extern uint32_t illegal_insn_trap_table[]; + uint32_t* pf = (void*)illegal_insn_trap_table + (insn & 0x7c); emulation_func f = (emulation_func)(uintptr_t)*pf; f(regs, mcause, mepc, mstatus, insn); } diff --git a/machine/encoding.h b/machine/encoding.h index b219309..5cb7ff5 100644 --- a/machine/encoding.h +++ b/machine/encoding.h @@ -67,9 +67,12 @@ #define IRQ_COP 12 #define IRQ_HOST 13 -#define DEFAULT_RSTVEC 0x0 -#define DEFAULT_NMIVEC 0x4 -#define DEFAULT_MTVEC 0x8 +#define DEFAULT_RSTVEC 0x00001000 +#define DEFAULT_NMIVEC 0x00001004 +#define DEFAULT_MTVEC 0x00001010 +#define CONFIG_STRING_ADDR 0x0000100C +#define EXT_IO_BASE 0x40000000 +#define DRAM_BASE 0x80000000 // page table entry (PTE) fields #define PTE_V 0x001 // Valid @@ -668,13 +671,13 @@ #define CSR_MSTIME_DELTA 0x705 #define CSR_MSINSTRET_DELTA 0x706 #define CSR_MCYCLE 0xf00 +#define CSR_MTIME 0xf01 #define CSR_MINSTRET 0xf02 #define CSR_MISA 0xf10 #define CSR_MVENDORID 0xf11 #define CSR_MARCHID 0xf12 #define CSR_MIMPID 0xf13 -#define CSR_MCFGADDR 0xf14 -#define CSR_MHARTID 0xf15 +#define CSR_MHARTID 0xf14 #define CSR_MTOHOST 0x7c0 #define CSR_MFROMHOST 0x7c1 #define CSR_MRESET 0x7c2 @@ -688,6 +691,7 @@ #define CSR_MSTIME_DELTAH 0x785 #define CSR_MSINSTRET_DELTAH 0x786 #define CSR_MCYCLEH 0xf80 +#define CSR_MTIMEH 0xf81 #define CSR_MINSTRETH 0xf82 #define CAUSE_MISALIGNED_FETCH 0x0 #define CAUSE_FAULT_FETCH 0x1 @@ -972,12 +976,12 @@ DECLARE_CSR(mscycle_delta, CSR_MSCYCLE_DELTA) DECLARE_CSR(mstime_delta, CSR_MSTIME_DELTA) DECLARE_CSR(msinstret_delta, CSR_MSINSTRET_DELTA) DECLARE_CSR(mcycle, CSR_MCYCLE) +DECLARE_CSR(mtime, CSR_MTIME) DECLARE_CSR(minstret, CSR_MINSTRET) DECLARE_CSR(misa, CSR_MISA) DECLARE_CSR(mvendorid, CSR_MVENDORID) DECLARE_CSR(marchid, CSR_MARCHID) DECLARE_CSR(mimpid, CSR_MIMPID) -DECLARE_CSR(mcfgaddr, CSR_MCFGADDR) DECLARE_CSR(mhartid, CSR_MHARTID) DECLARE_CSR(mtohost, CSR_MTOHOST) DECLARE_CSR(mfromhost, CSR_MFROMHOST) @@ -992,6 +996,7 @@ DECLARE_CSR(mscycle_deltah, CSR_MSCYCLE_DELTAH) DECLARE_CSR(mstime_deltah, CSR_MSTIME_DELTAH) DECLARE_CSR(msinstret_deltah, CSR_MSINSTRET_DELTAH) DECLARE_CSR(mcycleh, CSR_MCYCLEH) +DECLARE_CSR(mtimeh, CSR_MTIMEH) DECLARE_CSR(minstreth, CSR_MINSTRETH) #endif #ifdef DECLARE_CAUSE diff --git a/machine/fp_emulation.c b/machine/fp_emulation.c index 7523a29..f1ed919 100644 --- a/machine/fp_emulation.c +++ b/machine/fp_emulation.c @@ -45,8 +45,8 @@ DECLARE_EMULATION_FUNC(emulate_fp) if (unlikely((mstatus & MSTATUS_FS) == 0)) return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); - extern int32_t fp_emulation_table[]; - int32_t* pf = (void*)fp_emulation_table + ((insn >> 25) & 0x7c); + extern uint32_t fp_emulation_table[]; + uint32_t* pf = (void*)fp_emulation_table + ((insn >> 25) & 0x7c); emulation_func f = (emulation_func)(uintptr_t)*pf; SETUP_STATIC_ROUNDING(insn); diff --git a/machine/machine.mk.in b/machine/machine.mk.in index 4628954..6568dc5 100644 --- a/machine/machine.mk.in +++ b/machine/machine.mk.in @@ -4,6 +4,7 @@ machine_subproject_deps = \ machine_hdrs = \ atomic.h \ bits.h \ + configstring.h \ emulation.h \ encoding.h \ fp_emulation.h \ diff --git a/machine/mentry.S b/machine/mentry.S index 49f163b..bbc1c2a 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -89,7 +89,7 @@ trap_vector: STORE t2, 7*REGBYTES(sp) add t1, t0, t1 # t1 <- %hi(trap_table)[mcause] STORE s0, 8*REGBYTES(sp) - lw t1, %pcrel_lo(1b)(t1) # t1 <- trap_table[mcause] + LWU t1, %pcrel_lo(1b)(t1) # t1 <- trap_table[mcause] STORE s1, 9*REGBYTES(sp) mv a0, sp # a0 <- regs STORE a2,12*REGBYTES(sp) @@ -223,6 +223,12 @@ do_reset: li x31, 0 csrw mscratch, x0 + # write mtvec and make sure it sticks + la t0, trap_vector + csrw mtvec, t0 + csrr t1, mtvec +1:bne t0, t1, 1b + # sp <- end of first full page after the end of the binary la sp, _end + 2*RISCV_PGSIZE - 1 li t0, -RISCV_PGSIZE diff --git a/machine/sbi_impl.c b/machine/sbi_impl.c index 07844e0..f5ed8c9 100644 --- a/machine/sbi_impl.c +++ b/machine/sbi_impl.c @@ -5,7 +5,7 @@ uintptr_t __sbi_query_memory(uintptr_t id, memory_block_info *p) { if (id == 0) { p->base = first_free_paddr; - p->size = mem_size - p->base; + p->size = mem_size + DRAM_BASE - p->base; return 0; } diff --git a/pk/file.c b/pk/file.c index 9176f1a..53087c3 100644 --- a/pk/file.c +++ b/pk/file.c @@ -91,7 +91,7 @@ file_t* file_openat(int dirfd, const char* fn, int flags, int mode) return ERR_PTR(-ENOMEM); size_t fn_size = strlen(fn)+1; - long ret = frontend_syscall(SYS_openat, dirfd, (long)fn, fn_size, flags, mode, 0, 0); + long ret = frontend_syscall(SYS_openat, dirfd, va2pa(fn), fn_size, flags, mode, 0, 0); if (ret >= 0) { f->kfd = ret; @@ -120,31 +120,31 @@ int fd_close(int fd) ssize_t file_read(file_t* f, void* buf, size_t size) { populate_mapping(buf, size, PROT_WRITE); - return frontend_syscall(SYS_read, f->kfd, (uintptr_t)buf, size, 0, 0, 0, 0); + return frontend_syscall(SYS_read, f->kfd, va2pa(buf), size, 0, 0, 0, 0); } ssize_t file_pread(file_t* f, void* buf, size_t size, off_t offset) { populate_mapping(buf, size, PROT_WRITE); - return frontend_syscall(SYS_pread, f->kfd, (uintptr_t)buf, size, offset, 0, 0, 0); + return frontend_syscall(SYS_pread, f->kfd, va2pa(buf), size, offset, 0, 0, 0); } ssize_t file_write(file_t* f, const void* buf, size_t size) { populate_mapping(buf, size, PROT_READ); - return frontend_syscall(SYS_write, f->kfd, (uintptr_t)buf, size, 0, 0, 0, 0); + return frontend_syscall(SYS_write, f->kfd, va2pa(buf), size, 0, 0, 0, 0); } ssize_t file_pwrite(file_t* f, const void* buf, size_t size, off_t offset) { populate_mapping(buf, size, PROT_READ); - return frontend_syscall(SYS_pwrite, f->kfd, (uintptr_t)buf, size, offset, 0, 0, 0); + return frontend_syscall(SYS_pwrite, f->kfd, va2pa(buf), size, offset, 0, 0, 0); } int file_stat(file_t* f, struct stat* s) { struct frontend_stat buf; - long ret = frontend_syscall(SYS_fstat, f->kfd, (uintptr_t)&buf, 0, 0, 0, 0, 0); + long ret = frontend_syscall(SYS_fstat, f->kfd, va2pa(&buf), 0, 0, 0, 0, 0); copy_stat(s, &buf); return ret; } diff --git a/pk/mmap.c b/pk/mmap.c index 2f6a202..9f886ed 100644 --- a/pk/mmap.c +++ b/pk/mmap.c @@ -85,26 +85,21 @@ static size_t pt_idx(uintptr_t addr, int level) return idx & ((1 << RISCV_PGLEVEL_BITS) - 1); } -static pte_t* __maybe_create_root_page_table() +static pte_t* __walk_create(uintptr_t addr); + +static pte_t* __attribute__((noinline)) __continue_walk_create(uintptr_t addr, pte_t* pte) { - if (!root_page_table) - root_page_table = (void*)__page_alloc(); - return root_page_table; + *pte = ptd_create(ppn(__page_alloc())); + return __walk_create(addr); } static pte_t* __walk_internal(uintptr_t addr, int create) { - pte_t* t = __maybe_create_root_page_table(); + pte_t* t = root_page_table; for (int i = (VA_BITS - RISCV_PGSHIFT) / RISCV_PGLEVEL_BITS - 1; i > 0; i--) { size_t idx = pt_idx(addr, i); - if (!(t[idx] & PTE_V)) { - if (!create) - return 0; - uintptr_t page = __page_alloc(); - t[idx] = ptd_create(ppn(page)); - } - else - kassert(PTE_TABLE(t[idx])); + if (unlikely(!(t[idx] & PTE_V))) + return create ? __continue_walk_create(addr, &t[idx]) : 0; t = (pte_t*)(pte_ppn(t[idx]) << RISCV_PGSHIFT); } return &t[pt_idx(addr, 0)]; @@ -176,7 +171,7 @@ int __valid_user_range(uintptr_t vaddr, size_t len) { if (vaddr + len < vaddr) return 0; - return vaddr >= first_free_paddr && vaddr + len <= current.mmap_max; + return vaddr + len <= current.mmap_max; } static int __handle_page_fault(uintptr_t vaddr, int prot) @@ -190,7 +185,7 @@ static int __handle_page_fault(uintptr_t vaddr, int prot) return -1; else if (!(*pte & PTE_V)) { - uintptr_t ppn = vpn; + uintptr_t ppn = vpn + (first_free_paddr / RISCV_PGSIZE); vmr_t* v = (vmr_t*)*pte; *pte = pte_create(ppn, prot_to_type(PROT_READ|PROT_WRITE, 0)); @@ -407,16 +402,16 @@ uintptr_t pk_vm_init() { size_t mem_pages = mem_size >> RISCV_PGSHIFT; free_pages = MAX(8, mem_pages >> (RISCV_PGLEVEL_BITS-1)); - first_free_page = mem_size - free_pages * RISCV_PGSIZE; + first_free_page = first_free_paddr; + first_free_paddr += free_pages * RISCV_PGSIZE; - __map_kernel_range(0, 0, first_free_paddr, PROT_READ|PROT_WRITE|PROT_EXEC); - __map_kernel_range(first_free_page, first_free_page, free_pages * RISCV_PGSIZE, PROT_READ|PROT_WRITE); + root_page_table = (void*)__page_alloc(); + __map_kernel_range(DRAM_BASE, DRAM_BASE, first_free_paddr - DRAM_BASE, PROT_READ|PROT_WRITE|PROT_EXEC); - // keep user addresses positive - current.mmap_max = MIN(first_free_page, (uintptr_t)INTPTR_MAX + 1); - current.brk_max = current.mmap_max; + current.mmap_max = current.brk_max = + MIN(DRAM_BASE, mem_size - (first_free_paddr - DRAM_BASE)); - size_t stack_size = RISCV_PGSIZE * CLAMP(mem_size/(RISCV_PGSIZE*32), 1, 256); + size_t stack_size = RISCV_PGSIZE * 64; size_t stack_bottom = __do_mmap(current.mmap_max - stack_size, stack_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); kassert(stack_bottom != (uintptr_t)-1); current.stack_top = stack_bottom + stack_size; diff --git a/pk/mmap.h b/pk/mmap.h index e3c2035..3fc3186 100644 --- a/pk/mmap.h +++ b/pk/mmap.h @@ -5,6 +5,7 @@ #include "syscall.h" #include "encoding.h" #include "file.h" +#include "mtrap.h" #include #define PROT_NONE 0 @@ -31,4 +32,7 @@ uintptr_t do_mremap(uintptr_t addr, size_t old_size, size_t new_size, int flags) uintptr_t do_mprotect(uintptr_t addr, size_t length, int prot); uintptr_t do_brk(uintptr_t addr); +#define va2pa(va) ({ uintptr_t __va = (uintptr_t)(va); \ + __va >= DRAM_BASE ? __va : __va + first_free_paddr; }) + #endif diff --git a/pk/pk.c b/pk/pk.c index 6878811..ab2e119 100644 --- a/pk/pk.c +++ b/pk/pk.c @@ -70,7 +70,7 @@ typedef union { static size_t parse_args(arg_buf* args) { - long r = frontend_syscall(SYS_getmainvars, (uintptr_t)args, sizeof(*args), 0, 0, 0, 0, 0); + long r = frontend_syscall(SYS_getmainvars, va2pa(args), sizeof(*args), 0, 0, 0, 0, 0); kassert(r == 0); uint64_t* pk_argv = &args->buf[1]; // pk_argv[0] is the proxy kernel itself. skip it and any flags. diff --git a/pk/pk.lds b/pk/pk.lds index 0897e50..522e4a8 100644 --- a/pk/pk.lds +++ b/pk/pk.lds @@ -10,7 +10,7 @@ SECTIONS /*--------------------------------------------------------------------*/ /* Begining of code and text segment */ - . = 0; + . = 0x80000000; _ftext = .; PROVIDE( eprol = . ); diff --git a/pk/syscall.c b/pk/syscall.c index 1c9e234..9f2be88 100644 --- a/pk/syscall.c +++ b/pk/syscall.c @@ -111,8 +111,8 @@ int sys_renameat(int old_fd, const char *old_path, int new_fd, const char *new_p if(old_kfd != -1 && new_kfd != -1) { size_t old_size = strlen(old_path)+1; size_t new_size = strlen(new_path)+1; - return frontend_syscall(SYS_renameat, old_kfd, (uintptr_t)old_path, old_size, - new_kfd, (uintptr_t)new_path, new_size, 0); + return frontend_syscall(SYS_renameat, old_kfd, va2pa(old_path), old_size, + new_kfd, va2pa(new_path), new_size, 0); } return -EBADF; } @@ -191,7 +191,7 @@ long sys_lstat(const char* name, void* st) { struct frontend_stat buf; size_t name_size = strlen(name)+1; - long ret = frontend_syscall(SYS_lstat, (uintptr_t)name, name_size, (uintptr_t)&buf, 0, 0, 0, 0); + long ret = frontend_syscall(SYS_lstat, va2pa(name), name_size, va2pa(&buf), 0, 0, 0, 0); copy_stat(st, &buf); return ret; } @@ -202,7 +202,7 @@ long sys_fstatat(int dirfd, const char* name, void* st, int flags) if (kfd != -1) { struct frontend_stat buf; size_t name_size = strlen(name)+1; - long ret = frontend_syscall(SYS_fstatat, kfd, (uintptr_t)name, name_size, (uintptr_t)&buf, flags, 0, 0); + long ret = frontend_syscall(SYS_fstatat, kfd, va2pa(name), name_size, va2pa(&buf), flags, 0, 0); copy_stat(st, &buf); return ret; } @@ -219,7 +219,7 @@ long sys_faccessat(int dirfd, const char *name, int mode) int kfd = at_kfd(dirfd); if (kfd != -1) { size_t name_size = strlen(name)+1; - return frontend_syscall(SYS_faccessat, kfd, (uintptr_t)name, name_size, mode, 0, 0, 0); + return frontend_syscall(SYS_faccessat, kfd, va2pa(name), name_size, mode, 0, 0, 0); } return -EBADF; } @@ -236,8 +236,8 @@ long sys_linkat(int old_dirfd, const char* old_name, int new_dirfd, const char* if (old_kfd != -1 && new_kfd != -1) { size_t old_size = strlen(old_name)+1; size_t new_size = strlen(new_name)+1; - return frontend_syscall(SYS_linkat, old_kfd, (uintptr_t)old_name, old_size, - new_kfd, (uintptr_t)new_name, new_size, + return frontend_syscall(SYS_linkat, old_kfd, va2pa(old_name), old_size, + new_kfd, va2pa(new_name), new_size, flags); } return -EBADF; @@ -253,7 +253,7 @@ long sys_unlinkat(int dirfd, const char* name, int flags) int kfd = at_kfd(dirfd); if (kfd != -1) { size_t name_size = strlen(name)+1; - return frontend_syscall(SYS_unlinkat, kfd, (uintptr_t)name, name_size, flags, 0, 0, 0); + return frontend_syscall(SYS_unlinkat, kfd, va2pa(name), name_size, flags, 0, 0, 0); } return -EBADF; } @@ -268,7 +268,7 @@ long sys_mkdirat(int dirfd, const char* name, int mode) int kfd = at_kfd(dirfd); if (kfd != -1) { size_t name_size = strlen(name)+1; - return frontend_syscall(SYS_mkdirat, kfd, (uintptr_t)name, name_size, mode, 0, 0, 0); + return frontend_syscall(SYS_mkdirat, kfd, va2pa(name), name_size, mode, 0, 0, 0); } return -EBADF; } @@ -281,7 +281,7 @@ long sys_mkdir(const char* name, int mode) long sys_getcwd(const char* buf, size_t size) { populate_mapping(buf, size, PROT_WRITE); - return frontend_syscall(SYS_getcwd, (uintptr_t)buf, size, 0, 0, 0, 0, 0); + return frontend_syscall(SYS_getcwd, va2pa(buf), size, 0, 0, 0, 0, 0); } size_t sys_brk(size_t pos) @@ -384,7 +384,7 @@ ssize_t sys_writev(int fd, const long* iov, int cnt) int sys_chdir(const char *path) { - return frontend_syscall(SYS_chdir, (uintptr_t)path, 0, 0, 0, 0, 0, 0); + return frontend_syscall(SYS_chdir, va2pa(path), 0, 0, 0, 0, 0, 0); } int sys_getdents(int fd, void* dirbuf, int count) -- cgit v1.1