/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC) * SPDX-License-Identifier: MIT * Author: Rodrigo Arias Mallo */ /* Small utility to dump the state of the PLIC. */ /* Changelog: * v0.0.1 (2024-09-03): Initial version. */ #include #include #include #include #include #include #include #include const char *plic_address_str = "0x40800000"; long ncontexts = 15872L; long maxsources = 1024L; long nsources = 1024L; static void usage(void) { printf("plictool v0.0.1 - Rodrigo Arias Mallo \n"); printf( "Usage: plictool [-a addr] [-s nsources] [-c ncontexts]\n"); exit(1); } void dump_sources(void *base) { for (long s = 0; s < nsources; s++) { int printed_source = 0; uint32_t *pending_reg = base + 0x1000L + (s / 32L) * 4L; long shift = s % 32L; uint32_t pending = ((*pending_reg) >> shift) & 1; uint32_t *priority_reg = base + 0x0000L + (s * 4L); uint32_t priority = *priority_reg; const char *fmt = "src=%ld pend=%u prio=%u"; if (pending || priority) { printf(fmt, s, pending, priority); printed_source = 1; } int first_context = 1; for (long c = 0; c < ncontexts; c++) { uint32_t *enable_reg = base + 0x2000L + 0x80L * c + (s / 32L) * 4L; uint32_t enabled = ((*enable_reg) >> shift) & 1; uint32_t *threshold_reg = base + 0x200000L + (c * 0x1000L); uint32_t threshold = *threshold_reg; if (!enabled) continue; if (!printed_source) { printf(fmt, s, pending, priority); printed_source = 1; } printf(" ctx=%ld thre=%u", c, threshold); } if (printed_source) printf("\n"); } } int main(int argc, char *argv[]) { int opt; while ((opt = getopt(argc, argv, "a:hs:c:")) != -1) { switch (opt) { case 'a': plic_address_str = optarg; break; case 's': nsources = atol(optarg); break; case 'c': ncontexts = atol(optarg); break; case 'h': default: /* '?' */ usage(); } } off_t plic_address = (off_t) strtoll(plic_address_str, NULL, 16); printf("plic=0x%08x nsources=%ld ncontexts=%ld\n", plic_address, nsources, ncontexts); int fd = open("/dev/mem", O_RDWR | O_SYNC); if (fd == -1) { perror("cannot open /dev/mem"); exit(1); } size_t map_size = 0x4000000UL; void *map_base = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, plic_address); if (map_base == MAP_FAILED) { perror("mmap failed"); if (errno == EPERM) { fprintf(stderr, "Have you disabled 'CONFIG_STRICT_DEVMEM' and " "'CONFIG_IO_STRICT_DEVMEM' in the kernel config?\n" "Hint: zgrep STRICT_DEVMEM /proc/config.gz\n"); } exit(1); } dump_sources(map_base); munmap(map_base, map_size); close(fd); return 0; }