From 407edf31ac1e3f24e7db88c84c95f7ab01c50abd Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Mallo Date: Wed, 2 Oct 2024 07:35:19 +0200 Subject: [PATCH] Allow claiming a custom value in plictool --- tools/plictool.c | 105 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 14 deletions(-) diff --git a/tools/plictool.c b/tools/plictool.c index 6041d65..3b51124 100644 --- a/tools/plictool.c +++ b/tools/plictool.c @@ -22,12 +22,23 @@ #include #include -enum op { DUMP, CLAIM } operation = DUMP; +enum op { LIST, CLAIM } operation = LIST; const char *plic_address_str = "0x40800000"; long ncontexts = 2L; long maxsources = 1024L; long nsources = 1024L; long claim_ctx = 0; +uint32_t claim_value = 0; +uint32_t *claim_pvalue = NULL; + +struct source_ctx { + unsigned enabled; + unsigned threshold; + unsigned masked; +}; + +struct source { +}; static void usage(void) @@ -37,12 +48,17 @@ usage(void) " plictool - dump PLIC information\n" "\n" "SYNOPSIS\n" -" plictool [-a addr] [-s nsources] [-c ncontexts] [-C ctx]\n" +" plictool [-a addr] [-L] [-s nsources] [-c ncontexts]\n" +" plictool [-a addr] [-C] [-c context] [-w value]\n" "\n" "DESCRIPTION\n" " Dumps information about the RISC-V PLIC interrupt controller.\n" " Optional arguments:\n" "\n" +" -L Show PLIC information (default operation).\n" +"\n" +" -C context Claim an interrupt on the given context.\n" +"\n" " -a addr The starting address of the PLIC.\n" " The default is 0x40800000.\n" "\n" @@ -54,6 +70,8 @@ usage(void) "\n" " -C ctx Claim the interrupt on the given context.\n" "\n" +" -w value Use this value to claim an interrupt.\n" +"\n" "OUTPUT FORMAT\n" " Information is printed for each source that has some bit set\n" " in the pending or priority registers, or it has some context\n" @@ -95,18 +113,67 @@ write_reg(void *base, size_t offset, uint32_t value) } static void -claim_interrupt(void *base, long ctx) +claim_interrupt(void *base, uint32_t ctx, uint32_t *value) { size_t offset = 0x200004L + ctx * 0x1000; - uint32_t value = read_reg(base, offset); - printf("ctx=%ld claim=%u\n", ctx, value); - write_reg(base, offset, value); + uint32_t r = read_reg(base, offset); + uint32_t w = value ? *value : r; + write_reg(base, offset, w); + printf("claim ctx=%u r=%u w=%u\n", ctx, r, w); } static void -dump_sources(void *base) +source_init(struct source *src, long ncontexts) { + memset(src, 0, sizeof(struct source)); + src->ctx = calloc(ncontexts, sizeof(struct source_ctx)); + if (src->ctx == NULL) { + perror("calloc failed"); + exit(1); + } +} + +static void +source_reset(struct source *src, long ncontexts) +{ + memset(src, 0, sizeof(struct source)); + memset(src->ctx, 0, ncontexts * sizeof(struct source_ctx)); +} + + +static void +source_free(struct source *src, long ncontexts) +{ + free(src->ctx); +} + +static void +source_read(struct source *src, void *base, long s, long ncontexts) +{ + uint32_t pending_reg = read_reg(base, 0x1000L + (s / 32L) * 4L) + long shift = s % 32L; + src->pending = (pending_reg >> shift) & 1; + src->priority = read_reg(base, 0x0000L + (s * 4L)); + + for (long c = 0; c < ncontexts; c++) { + struct source_ctx *ctx = &src->ctx[c]; + + size_t off_en = 0x2000L + 0x80L * c + (s / 32L) * 4L; + uint32_t enabled_reg = reg_read(base, off_en); + ctx->enabled = (enable_reg >> shift) & 1; + ctx->threshold = read_reg(base, 0x200000L + (c * 0x1000L)); + ctx->masked = priority <= threshold; + } +} + +static void +list_sources(void *base) +{ + struct source src; + + source_init(&src, ncontexts); for (long s = 0; s < nsources; s++) { + source_read(&src, base, s, ncontexts); int printed_source = 0; uint32_t *pending_reg = base + 0x1000L + (s / 32L) * 4L; @@ -160,13 +227,20 @@ dump_sources(void *base) int main(int argc, char *argv[]) { + const char *memfile = "/dev/mem"; int opt; - while ((opt = getopt(argc, argv, "a:hs:c:C:")) != -1) { + while ((opt = getopt(argc, argv, "f:a:hLs:c:C:w:")) != -1) { switch (opt) { + case 'f': + memfile = optarg; + break; case 'a': plic_address_str = optarg; break; + case 'L': /* default operation */ + operation = LIST; + break; case 's': nsources = atol(optarg); break; @@ -177,6 +251,10 @@ int main(int argc, char *argv[]) operation = CLAIM; claim_ctx = atol(optarg); break; + case 'w': + claim_value = atol(optarg); + claim_pvalue = &claim_value; + break; case 'h': default: /* '?' */ usage(); @@ -188,11 +266,10 @@ int main(int argc, char *argv[]) printf("plictool "VERSION" addr=0x%08llx nsrc=%ld nctx=%ld\n", plic_address, nsources, ncontexts); - //int fd = open("test.bin", O_RDWR | O_SYNC); - int fd = open("/dev/mem", O_RDWR | O_SYNC); + int fd = open(memfile, O_RDWR | O_SYNC); if (fd == -1) { - perror("cannot open /dev/mem"); + fprintf(stderr, "cannot open %s: %s", memfile, strerror(errno)); exit(1); } @@ -211,9 +288,9 @@ int main(int argc, char *argv[]) } if (operation == CLAIM) - claim_interrupt(map_base, claim_ctx); - else if (operation == DUMP) - dump_sources(map_base); + claim_interrupt(map_base, claim_ctx, claim_pvalue); + else if (operation == LIST) + list_sources(map_base); munmap(map_base, map_size);