Allow claiming a custom value in plictool
This commit is contained in:
parent
af666c44ef
commit
407edf31ac
105
tools/plictool.c
105
tools/plictool.c
@ -22,12 +22,23 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
enum op { DUMP, CLAIM } operation = DUMP;
|
enum op { LIST, CLAIM } operation = LIST;
|
||||||
const char *plic_address_str = "0x40800000";
|
const char *plic_address_str = "0x40800000";
|
||||||
long ncontexts = 2L;
|
long ncontexts = 2L;
|
||||||
long maxsources = 1024L;
|
long maxsources = 1024L;
|
||||||
long nsources = 1024L;
|
long nsources = 1024L;
|
||||||
long claim_ctx = 0;
|
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
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
@ -37,12 +48,17 @@ usage(void)
|
|||||||
" plictool - dump PLIC information\n"
|
" plictool - dump PLIC information\n"
|
||||||
"\n"
|
"\n"
|
||||||
"SYNOPSIS\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"
|
"\n"
|
||||||
"DESCRIPTION\n"
|
"DESCRIPTION\n"
|
||||||
" Dumps information about the RISC-V PLIC interrupt controller.\n"
|
" Dumps information about the RISC-V PLIC interrupt controller.\n"
|
||||||
" Optional arguments:\n"
|
" Optional arguments:\n"
|
||||||
"\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"
|
" -a addr The starting address of the PLIC.\n"
|
||||||
" The default is 0x40800000.\n"
|
" The default is 0x40800000.\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -54,6 +70,8 @@ usage(void)
|
|||||||
"\n"
|
"\n"
|
||||||
" -C ctx Claim the interrupt on the given context.\n"
|
" -C ctx Claim the interrupt on the given context.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
" -w value Use this value to claim an interrupt.\n"
|
||||||
|
"\n"
|
||||||
"OUTPUT FORMAT\n"
|
"OUTPUT FORMAT\n"
|
||||||
" Information is printed for each source that has some bit set\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"
|
" 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
|
static void
|
||||||
claim_interrupt(void *base, long ctx)
|
claim_interrupt(void *base, uint32_t ctx, uint32_t *value)
|
||||||
{
|
{
|
||||||
size_t offset = 0x200004L + ctx * 0x1000;
|
size_t offset = 0x200004L + ctx * 0x1000;
|
||||||
uint32_t value = read_reg(base, offset);
|
uint32_t r = read_reg(base, offset);
|
||||||
printf("ctx=%ld claim=%u\n", ctx, value);
|
uint32_t w = value ? *value : r;
|
||||||
write_reg(base, offset, value);
|
write_reg(base, offset, w);
|
||||||
|
printf("claim ctx=%u r=%u w=%u\n", ctx, r, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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++) {
|
for (long s = 0; s < nsources; s++) {
|
||||||
|
source_read(&src, base, s, ncontexts);
|
||||||
int printed_source = 0;
|
int printed_source = 0;
|
||||||
|
|
||||||
uint32_t *pending_reg = base + 0x1000L + (s / 32L) * 4L;
|
uint32_t *pending_reg = base + 0x1000L + (s / 32L) * 4L;
|
||||||
@ -160,13 +227,20 @@ dump_sources(void *base)
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
const char *memfile = "/dev/mem";
|
||||||
int opt;
|
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) {
|
switch (opt) {
|
||||||
|
case 'f':
|
||||||
|
memfile = optarg;
|
||||||
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
plic_address_str = optarg;
|
plic_address_str = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'L': /* default operation */
|
||||||
|
operation = LIST;
|
||||||
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
nsources = atol(optarg);
|
nsources = atol(optarg);
|
||||||
break;
|
break;
|
||||||
@ -177,6 +251,10 @@ int main(int argc, char *argv[])
|
|||||||
operation = CLAIM;
|
operation = CLAIM;
|
||||||
claim_ctx = atol(optarg);
|
claim_ctx = atol(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'w':
|
||||||
|
claim_value = atol(optarg);
|
||||||
|
claim_pvalue = &claim_value;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
default: /* '?' */
|
default: /* '?' */
|
||||||
usage();
|
usage();
|
||||||
@ -188,11 +266,10 @@ int main(int argc, char *argv[])
|
|||||||
printf("plictool "VERSION" addr=0x%08llx nsrc=%ld nctx=%ld\n",
|
printf("plictool "VERSION" addr=0x%08llx nsrc=%ld nctx=%ld\n",
|
||||||
plic_address, nsources, ncontexts);
|
plic_address, nsources, ncontexts);
|
||||||
|
|
||||||
//int fd = open("test.bin", O_RDWR | O_SYNC);
|
int fd = open(memfile, O_RDWR | O_SYNC);
|
||||||
int fd = open("/dev/mem", O_RDWR | O_SYNC);
|
|
||||||
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
perror("cannot open /dev/mem");
|
fprintf(stderr, "cannot open %s: %s", memfile, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,9 +288,9 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (operation == CLAIM)
|
if (operation == CLAIM)
|
||||||
claim_interrupt(map_base, claim_ctx);
|
claim_interrupt(map_base, claim_ctx, claim_pvalue);
|
||||||
else if (operation == DUMP)
|
else if (operation == LIST)
|
||||||
dump_sources(map_base);
|
list_sources(map_base);
|
||||||
|
|
||||||
munmap(map_base, map_size);
|
munmap(map_base, map_size);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user