arch/riscv: Add functions to read/write memory on behalf of supervisor/user mode

Normally machine-mode code operates completely within physical address
space. When emulating less privileged memory accesses (e.g. when the
hardware doesn't support unaligned read/write), it is useful to access
memory through the MMU (and with virtual addresses); this patch
implements this functionality using the MPRV bit.

Change-Id: Ic3b3301f348769faf3ee3ef2a78935dfbcbd15fd
Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Reviewed-on: https://review.coreboot.org/16260
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
Jonathan Neuschäfer 2016-08-22 19:37:15 +02:00 committed by Ronald G. Minnich
parent cafb10c672
commit f643d661e1
1 changed files with 47 additions and 0 deletions

View File

@ -30,6 +30,7 @@
#include <string.h>
#include <stdint.h>
#include <arch/encoding.h>
#define SUPERPAGE_SIZE ((uintptr_t)(RISCV_PGSIZE << RISCV_PGLEVEL_BITS))
#define VM_CHOICE VM_SV39
@ -70,4 +71,50 @@ void mstatus_init(void); // need to setup mstatus so we know we have virtual mem
void flush_tlb(void);
#define DEFINE_MPRV_READ(name, type, insn) \
static inline type name(type *p); \
static inline type name(type *p) \
{ \
int mprv = MSTATUS_MPRV; \
type value; \
asm ( \
"csrs mstatus, %1\n" \
STRINGIFY(insn) " %0, 0(%2)\n" \
"csrc mstatus, %1\n" \
: "=r"(value) : "r"(mprv), "r"(p) : "memory" \
); \
return value; \
}
#define DEFINE_MPRV_WRITE(name, type, insn) \
static inline void name(type *p, type value); \
static inline void name(type *p, type value) \
{ \
int mprv = MSTATUS_MPRV; \
asm ( \
"csrs mstatus, %0\n" \
STRINGIFY(insn) " %1, 0(%2)\n" \
"csrc mstatus, %0\n" \
:: "r"(mprv), "r"(value), "r"(p) : "memory" \
); \
}
DEFINE_MPRV_READ(mprv_read_u8, uint8_t, lbu)
DEFINE_MPRV_READ(mprv_read_u16, uint16_t, lhu)
DEFINE_MPRV_READ(mprv_read_u32, uint32_t, lwu)
DEFINE_MPRV_READ(mprv_read_u64, uint32_t, ld)
DEFINE_MPRV_READ(mprv_read_long, long, ld)
DEFINE_MPRV_READ(mprv_read_ulong, unsigned long, ld)
DEFINE_MPRV_WRITE(mprv_write_u8, uint8_t, sb)
DEFINE_MPRV_WRITE(mprv_write_u16, uint16_t, sh)
DEFINE_MPRV_WRITE(mprv_write_u32, uint32_t, sw)
DEFINE_MPRV_WRITE(mprv_write_u64, uint64_t, sd)
DEFINE_MPRV_WRITE(mprv_write_long, long, sd)
DEFINE_MPRV_WRITE(mprv_write_ulong, unsigned long, sd)
#undef DEFINE_MPRV_READ
#undef DEFINE_MPRV_WRITE
#endif