From 4de2bff12d967d91dd064e4a49e25ca4785f25e3 Mon Sep 17 00:00:00 2001 From: Tim Hutt Date: Fri, 2 Feb 2024 11:56:55 +0000 Subject: Improve PMP support This implements a lot of missing functionality for PMPs. * Support 64 PMPs as well as 0 and 16. * Support setting PMP grain * Return correct address bits on read (some read as 0 or 1 depending on the grain and match type) * Unlock PMPs on reset * Implement pmpcfg WARL legalisation Co-authored-by: Ben Fletcher --- c_emulator/riscv_platform.c | 15 ++++++++++----- c_emulator/riscv_platform.h | 4 +++- c_emulator/riscv_platform_impl.c | 4 +++- c_emulator/riscv_platform_impl.h | 4 +++- c_emulator/riscv_sim.c | 27 +++++++++++++++++++++++---- 5 files changed, 42 insertions(+), 12 deletions(-) (limited to 'c_emulator') diff --git a/c_emulator/riscv_platform.c b/c_emulator/riscv_platform.c index fbd63fa..253da35 100644 --- a/c_emulator/riscv_platform.c +++ b/c_emulator/riscv_platform.c @@ -47,6 +47,16 @@ bool sys_enable_vext(unit u) return rv_enable_vext; } +uint64_t sys_pmp_count(unit u) +{ + return rv_pmp_count; +} + +uint64_t sys_pmp_grain(unit u) +{ + return rv_pmp_grain; +} + bool sys_enable_writable_misa(unit u) { return rv_enable_writable_misa; @@ -67,11 +77,6 @@ bool plat_mtval_has_illegal_inst_bits(unit u) return rv_mtval_has_illegal_inst_bits; } -bool plat_enable_pmp(unit u) -{ - return rv_enable_pmp; -} - mach_bits plat_ram_base(unit u) { return rv_ram_base; diff --git a/c_emulator/riscv_platform.h b/c_emulator/riscv_platform.h index 4b6541f..38fac2f 100644 --- a/c_emulator/riscv_platform.h +++ b/c_emulator/riscv_platform.h @@ -9,10 +9,12 @@ bool sys_enable_writable_misa(unit); bool sys_enable_writable_fiom(unit); bool sys_enable_vext(unit); +uint64_t sys_pmp_count(unit); +uint64_t sys_pmp_grain(unit); + bool plat_enable_dirty_update(unit); bool plat_enable_misaligned_access(unit); bool plat_mtval_has_illegal_inst_bits(unit); -bool plat_enable_pmp(unit); mach_bits plat_ram_base(unit); mach_bits plat_ram_size(unit); diff --git a/c_emulator/riscv_platform_impl.c b/c_emulator/riscv_platform_impl.c index 15ff8ad..c2ae256 100644 --- a/c_emulator/riscv_platform_impl.c +++ b/c_emulator/riscv_platform_impl.c @@ -3,7 +3,9 @@ #include /* Settings of the platform implementation, with common defaults. */ -bool rv_enable_pmp = false; +uint64_t rv_pmp_count = 0; +uint64_t rv_pmp_grain = 0; + bool rv_enable_zfinx = false; bool rv_enable_rvc = true; bool rv_enable_next = false; diff --git a/c_emulator/riscv_platform_impl.h b/c_emulator/riscv_platform_impl.h index e5c562a..e3e4a96 100644 --- a/c_emulator/riscv_platform_impl.h +++ b/c_emulator/riscv_platform_impl.h @@ -8,7 +8,9 @@ #define DEFAULT_RSTVEC 0x00001000 -extern bool rv_enable_pmp; +extern uint64_t rv_pmp_count; +extern uint64_t rv_pmp_grain; + extern bool rv_enable_zfinx; extern bool rv_enable_rvc; extern bool rv_enable_next; diff --git a/c_emulator/riscv_sim.c b/c_emulator/riscv_sim.c index 13d1653..f3c6343 100644 --- a/c_emulator/riscv_sim.c +++ b/c_emulator/riscv_sim.c @@ -51,6 +51,8 @@ const char *RV32ISA = "RV32IMAC"; #define OPT_TRACE_OUTPUT 1000 #define OPT_ENABLE_WRITABLE_FIOM 1001 +#define OPT_PMP_COUNT 1002 +#define OPT_PMP_GRAIN 1003 static bool do_dump_dts = false; static bool do_show_times = false; @@ -119,7 +121,8 @@ char *sailcov_file = NULL; static struct option options[] = { {"enable-dirty-update", no_argument, 0, 'd' }, {"enable-misaligned", no_argument, 0, 'm' }, - {"enable-pmp", no_argument, 0, 'P' }, + {"pmp-count", required_argument, 0, OPT_PMP_COUNT }, + {"pmp-grain", required_argument, 0, OPT_PMP_GRAIN }, {"enable-next", no_argument, 0, 'N' }, {"ram-size", required_argument, 0, 'z' }, {"disable-compressed", no_argument, 0, 'C' }, @@ -236,6 +239,8 @@ static int process_args(int argc, char **argv) { int c; uint64_t ram_size = 0; + uint64_t pmp_count = 0; + uint64_t pmp_grain = 0; while (true) { c = getopt_long(argc, argv, "a" @@ -281,9 +286,23 @@ static int process_args(int argc, char **argv) fprintf(stderr, "enabling misaligned access.\n"); rv_enable_misaligned = true; break; - case 'P': - fprintf(stderr, "enabling PMP support.\n"); - rv_enable_pmp = true; + case OPT_PMP_COUNT: + pmp_count = atol(optarg); + fprintf(stderr, "PMP count: %lld\n", pmp_count); + if (pmp_count != 0 && pmp_count != 16 && pmp_count != 64) { + fprintf(stderr, "invalid PMP count: must be 0, 16 or 64"); + exit(1); + } + rv_pmp_count = pmp_count; + break; + case OPT_PMP_GRAIN: + pmp_grain = atol(optarg); + fprintf(stderr, "PMP grain: %lld\n", pmp_grain); + if (pmp_grain >= 64) { + fprintf(stderr, "invalid PMP grain: must less than 64"); + exit(1); + } + rv_pmp_grain = pmp_grain; break; case 'C': fprintf(stderr, "disabling RVC compressed instructions.\n"); -- cgit v1.1