Add more operations to plictool
This commit is contained in:
parent
407edf31ac
commit
1cf4e576d6
@ -1,4 +1,4 @@
|
|||||||
CFLAGS=-static
|
CFLAGS=-Wall -static
|
||||||
PREFIX?=/usr/local
|
PREFIX?=/usr/local
|
||||||
bin=plictool csrtool memtool unalign
|
bin=plictool csrtool memtool unalign
|
||||||
|
|
||||||
|
378
tools/plictool.c
378
tools/plictool.c
@ -2,102 +2,58 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
* Author: Rodrigo Arias Mallo <rodrigo.arias@bsc.es> */
|
* Author: Rodrigo Arias Mallo <rodrigo.arias@bsc.es> */
|
||||||
|
|
||||||
/* Small utility to dump the state of the PLIC. */
|
/* Small utility to manage the PLIC. */
|
||||||
|
|
||||||
/* Changelog:
|
/* Changelog:
|
||||||
* v0.0.1 (2024-09-03): Initial version.
|
* v0.0.1 (2024-09-03): Initial version.
|
||||||
* v0.0.2 (2024-09-04): Print contexts in another line and masked information.
|
* v0.0.2 (2024-09-04): Print contexts in another line and masked information.
|
||||||
* v0.0.3 (2024-09-04): Make output format more clear and add manual.
|
* v0.0.3 (2024-09-04): Make output format more clear and add manual.
|
||||||
* v0.0.4 (2024-09-30): Implement support for claiming an interrupt.
|
* v0.0.4 (2024-09-30): Implement support for claiming an interrupt.
|
||||||
|
* v0.0.5 (2024-10-02): Support other read/write operations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VERSION "v0.0.4"
|
#define VERSION "v0.0.5"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
enum op { LIST, CLAIM } operation = LIST;
|
int operation;
|
||||||
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;
|
|
||||||
uint32_t claim_value = 0;
|
long context = -1;
|
||||||
uint32_t *claim_pvalue = NULL;
|
long source = -1;
|
||||||
|
long value = -1;
|
||||||
|
bool value_set = NULL;
|
||||||
|
|
||||||
|
struct ctx {
|
||||||
|
uint32_t threshold;
|
||||||
|
};
|
||||||
|
|
||||||
struct source_ctx {
|
struct source_ctx {
|
||||||
unsigned enabled;
|
bool enabled;
|
||||||
unsigned threshold;
|
bool masked;
|
||||||
unsigned masked;
|
uint32_t threshold;
|
||||||
|
const char *state;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct source {
|
struct source {
|
||||||
|
bool pending;
|
||||||
|
bool show;
|
||||||
|
uint32_t priority;
|
||||||
|
struct source_ctx *ctx;
|
||||||
|
long ncontexts;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
printf(
|
|
||||||
"NAME\n"
|
|
||||||
" plictool - dump PLIC information\n"
|
|
||||||
"\n"
|
|
||||||
"SYNOPSIS\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"
|
|
||||||
" -s nsources Limit the number of sources to print.\n"
|
|
||||||
" The default is 1024.\n"
|
|
||||||
"\n"
|
|
||||||
" -c ncontexts Limit the number of contexts to print.\n"
|
|
||||||
" The default is 15872.\n"
|
|
||||||
"\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"
|
|
||||||
" enabled. The the following attributes are printed:\n"
|
|
||||||
"\n"
|
|
||||||
" src source number\n"
|
|
||||||
" pend pending bit\n"
|
|
||||||
" prio priority of the source\n"
|
|
||||||
"\n"
|
|
||||||
" Additionally, for each enabled context of the source the\n"
|
|
||||||
" following attributes are printed for that context:\n"
|
|
||||||
"\n"
|
|
||||||
" ctx context number\n"
|
|
||||||
" thre threshold value\n"
|
|
||||||
" masked the source is masked (prio <= thre)\n"
|
|
||||||
"\n"
|
|
||||||
"AUTHOR\n"
|
|
||||||
" Rodrigo Arias Mallo <rodrigo.arias@bsc.es>\n"
|
|
||||||
"\n"
|
|
||||||
"SEE ALSO\n"
|
|
||||||
" See https://github.com/riscv/riscv-plic-spec/\n"
|
|
||||||
"\n"
|
|
||||||
);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
read_reg(void *base, size_t offset)
|
read_reg(void *base, size_t offset)
|
||||||
{
|
{
|
||||||
@ -112,14 +68,89 @@ write_reg(void *base, size_t offset, uint32_t value)
|
|||||||
*p = value;
|
*p = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
uint32_t
|
||||||
claim_interrupt(void *base, uint32_t ctx, uint32_t *value)
|
claim_get(void *base, uint32_t ctx)
|
||||||
{
|
{
|
||||||
size_t offset = 0x200004L + ctx * 0x1000;
|
return read_reg(base, 0x200004L + ctx * 0x1000);
|
||||||
uint32_t r = read_reg(base, offset);
|
}
|
||||||
uint32_t w = value ? *value : r;
|
|
||||||
write_reg(base, offset, w);
|
static void
|
||||||
printf("claim ctx=%u r=%u w=%u\n", ctx, r, w);
|
claim_set(void *base, uint32_t ctx, uint32_t value)
|
||||||
|
{
|
||||||
|
write_reg(base, 0x200004L + ctx * 0x1000, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
thre_get(void *base, uint32_t ctx)
|
||||||
|
{
|
||||||
|
return read_reg(base, 0x200000L + (ctx * 0x1000L));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
thre_set(void *base, uint32_t ctx, uint32_t value)
|
||||||
|
{
|
||||||
|
write_reg(base, 0x200000L + (ctx * 0x1000L), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
prio_get(void *base, uint32_t s)
|
||||||
|
{
|
||||||
|
return read_reg(base, s * 4L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
prio_set(void *base, uint32_t s, uint32_t value)
|
||||||
|
{
|
||||||
|
write_reg(base, s * 4L, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
pending_get(void *base, uint32_t s)
|
||||||
|
{
|
||||||
|
uint32_t offset = 0x1000L + (s / 32L) * 4L;
|
||||||
|
uint32_t pending = read_reg(base, offset);
|
||||||
|
long shift = s % 32L;
|
||||||
|
|
||||||
|
return (pending >> shift) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pending_set(void *base, uint32_t s, uint32_t value)
|
||||||
|
{
|
||||||
|
uint32_t offset = 0x1000L + (s / 32L) * 4L;
|
||||||
|
uint32_t pending = read_reg(base, offset);
|
||||||
|
long shift = s % 32L;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
pending |= (1L << shift);
|
||||||
|
else
|
||||||
|
pending &= ~(1L << shift);
|
||||||
|
|
||||||
|
write_reg(base, offset, pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
enable_get(void *base, uint32_t c, uint32_t s)
|
||||||
|
{
|
||||||
|
size_t off_en = 0x2000L + 0x80L * c + (s / 32L) * 4L;
|
||||||
|
uint32_t enabled_reg = read_reg(base, off_en);
|
||||||
|
long shift = s % 32L;
|
||||||
|
return (enabled_reg >> shift) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enable_set(void *base, uint32_t c, uint32_t s, uint32_t value)
|
||||||
|
{
|
||||||
|
size_t off_en = 0x2000L + 0x80L * c + (s / 32L) * 4L;
|
||||||
|
uint32_t enabled_reg = read_reg(base, off_en);
|
||||||
|
long shift = s % 32L;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
enabled_reg |= (1L << shift);
|
||||||
|
else
|
||||||
|
enabled_reg &= ~(1L << shift);
|
||||||
|
|
||||||
|
write_reg(base, off_en, enabled_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -127,6 +158,7 @@ source_init(struct source *src, long ncontexts)
|
|||||||
{
|
{
|
||||||
memset(src, 0, sizeof(struct source));
|
memset(src, 0, sizeof(struct source));
|
||||||
src->ctx = calloc(ncontexts, sizeof(struct source_ctx));
|
src->ctx = calloc(ncontexts, sizeof(struct source_ctx));
|
||||||
|
src->ncontexts = ncontexts;
|
||||||
if (src->ctx == NULL) {
|
if (src->ctx == NULL) {
|
||||||
perror("calloc failed");
|
perror("calloc failed");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -134,95 +166,98 @@ source_init(struct source *src, long ncontexts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
source_reset(struct source *src, long ncontexts)
|
source_reset(struct source *src)
|
||||||
{
|
{
|
||||||
memset(src, 0, sizeof(struct source));
|
src->pending = false;
|
||||||
memset(src->ctx, 0, ncontexts * sizeof(struct source_ctx));
|
src->show = false;
|
||||||
|
src->priority = 0;
|
||||||
|
|
||||||
|
memset(src->ctx, 0, src->ncontexts * sizeof(struct source_ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
source_free(struct source *src, long ncontexts)
|
source_free(struct source *src)
|
||||||
{
|
{
|
||||||
free(src->ctx);
|
free(src->ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
source_read(struct source *src, void *base, long s, long ncontexts)
|
source_read(struct source *src, void *base, long s)
|
||||||
{
|
{
|
||||||
uint32_t pending_reg = read_reg(base, 0x1000L + (s / 32L) * 4L)
|
uint32_t pending_reg = read_reg(base, 0x1000L + (s / 32L) * 4L);
|
||||||
long shift = s % 32L;
|
long shift = s % 32L;
|
||||||
src->pending = (pending_reg >> shift) & 1;
|
src->pending = (pending_reg >> shift) & 1;
|
||||||
src->priority = read_reg(base, 0x0000L + (s * 4L));
|
src->priority = read_reg(base, 0x0000L + (s * 4L));
|
||||||
|
|
||||||
for (long c = 0; c < ncontexts; c++) {
|
bool ctx_show = 0;
|
||||||
|
for (long c = 0; c < src->ncontexts; c++) {
|
||||||
struct source_ctx *ctx = &src->ctx[c];
|
struct source_ctx *ctx = &src->ctx[c];
|
||||||
|
|
||||||
size_t off_en = 0x2000L + 0x80L * c + (s / 32L) * 4L;
|
size_t off_en = 0x2000L + 0x80L * c + (s / 32L) * 4L;
|
||||||
uint32_t enabled_reg = reg_read(base, off_en);
|
uint32_t enabled_reg = read_reg(base, off_en);
|
||||||
ctx->enabled = (enable_reg >> shift) & 1;
|
ctx->enabled = (enabled_reg >> shift) & 1;
|
||||||
ctx->threshold = read_reg(base, 0x200000L + (c * 0x1000L));
|
ctx->threshold = read_reg(base, 0x200000L + (c * 0x1000L));
|
||||||
ctx->masked = priority <= threshold;
|
ctx->masked = src->priority <= ctx->threshold;
|
||||||
|
ctx_show = ctx_show || ctx->enabled;
|
||||||
|
|
||||||
|
if (!ctx->enabled)
|
||||||
|
ctx->state = "-";
|
||||||
|
else if (ctx->masked)
|
||||||
|
ctx->state = "masked";
|
||||||
|
else
|
||||||
|
ctx->state = "firing";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Show the source if it has some bit to non-zero */
|
||||||
|
src->show = src->pending || src->priority || ctx_show;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
list_sources(void *base)
|
list_sources(void *base)
|
||||||
{
|
{
|
||||||
struct source src;
|
printf("Source\tPend\tPrio");
|
||||||
|
for (long i = 0; i < ncontexts; i++) {
|
||||||
source_init(&src, ncontexts);
|
uint32_t threshold = read_reg(base, 0x200000L + (i * 0x1000L));
|
||||||
for (long s = 0; s < nsources; s++) {
|
printf("\tC%ld(%u)", i, threshold);
|
||||||
source_read(&src, base, s, ncontexts);
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
int first_context = 1;
|
struct source s;
|
||||||
int enabled_contexts = 0;
|
source_init(&s, ncontexts);
|
||||||
int unmasked = 0;
|
for (long i = 0; i < nsources; i++) {
|
||||||
for (long c = 0; c < ncontexts; c++) {
|
source_reset(&s);
|
||||||
uint32_t *enable_reg = base + 0x2000L + 0x80L * c + (s / 32L) * 4L;
|
source_read(&s, base, i);
|
||||||
uint32_t enabled = ((*enable_reg) >> shift) & 1;
|
|
||||||
uint32_t *threshold_reg = base + 0x200000L + (c * 0x1000L);
|
|
||||||
uint32_t threshold = *threshold_reg;
|
|
||||||
|
|
||||||
if (!enabled)
|
if (!s.show)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!printed_source) {
|
printf("%ld\t%s\t%u", i, s.pending ? "yes" : "-", s.priority);
|
||||||
printf(fmt, s, pending, priority);
|
|
||||||
printed_source = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (long j = 0; j < ncontexts; j++)
|
||||||
|
printf("\t%s", s.ctx[j].state);
|
||||||
|
|
||||||
int is_masked = priority <= threshold;
|
|
||||||
|
|
||||||
if (!is_masked)
|
|
||||||
unmasked++;
|
|
||||||
|
|
||||||
const char *masked = is_masked ? "masked" : "unmasked";
|
|
||||||
|
|
||||||
printf("\n ctx=%ld thre=%u %s",
|
|
||||||
c, threshold, masked);
|
|
||||||
enabled_contexts++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (printed_source)
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
source_free(&s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage(void)
|
||||||
|
{
|
||||||
|
printf("plictool "VERSION" -- Rodrigo Arias Mallo <rodrigo.arias@bsc.es>\n");
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"Usage:\n"
|
||||||
|
" plictool [-a addr] [-L] [-n nsrc] [-x nctx] # List (default)\n"
|
||||||
|
" plictool [-a addr] -C ctx [-w value] # Claim\n"
|
||||||
|
" plictool [-a addr] -T ctx [-w value] # Threshold\n"
|
||||||
|
" plictool [-a addr] -I src [-w value] # Priority\n"
|
||||||
|
" plictool [-a addr] -P src [-w value] # Pending\n"
|
||||||
|
" plictool [-a addr] -E src -c ctx [-w value] # Enabled\n"
|
||||||
|
" plictool -v # Version\n"
|
||||||
|
);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@ -230,41 +265,70 @@ int main(int argc, char *argv[])
|
|||||||
const char *memfile = "/dev/mem";
|
const char *memfile = "/dev/mem";
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "f:a:hLs:c:C:w:")) != -1) {
|
while ((opt = getopt(argc, argv, "f:a:LC:T:P:I:E:n:x:c:w:vh")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
/* Common flags */
|
||||||
case 'f':
|
case 'f':
|
||||||
memfile = optarg;
|
memfile = optarg;
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
plic_address_str = optarg;
|
plic_address_str = optarg;
|
||||||
break;
|
break;
|
||||||
case 'L': /* default operation */
|
case 'n':
|
||||||
operation = LIST;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
nsources = atol(optarg);
|
nsources = atol(optarg);
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'x':
|
||||||
ncontexts = atol(optarg);
|
ncontexts = atol(optarg);
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C': /* claim */
|
||||||
operation = CLAIM;
|
case 'T': /* threshold */
|
||||||
claim_ctx = atol(optarg);
|
operation = opt;
|
||||||
|
context = atol(optarg);
|
||||||
|
break;
|
||||||
|
case 'P': /* pending */
|
||||||
|
case 'I': /* priority */
|
||||||
|
case 'E': /* enable */
|
||||||
|
operation = opt;
|
||||||
|
source = atol(optarg);
|
||||||
|
break;
|
||||||
|
case 'L': /* list */
|
||||||
|
operation = opt;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
context = atol(optarg);
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
claim_value = atol(optarg);
|
value = atol(optarg);
|
||||||
claim_pvalue = &claim_value;
|
value_set = true;
|
||||||
break;
|
break;
|
||||||
|
case 'v':
|
||||||
|
printf("plictool "VERSION"\n");
|
||||||
|
exit(0);
|
||||||
case 'h':
|
case 'h':
|
||||||
default: /* '?' */
|
default: /* '?' */
|
||||||
usage();
|
usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation == 'P' || operation == 'I' || operation == 'E') {
|
||||||
|
if (source < 0) {
|
||||||
|
fprintf(stderr, "missing source\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation == 'C' || operation == 'T' || operation == 'E') {
|
||||||
|
if (context < 0) {
|
||||||
|
fprintf(stderr, "missing context\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long plic_address = strtoull(plic_address_str, NULL, 16);
|
unsigned long long plic_address = strtoull(plic_address_str, NULL, 16);
|
||||||
|
|
||||||
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(memfile, O_RDWR | O_SYNC);
|
int fd = open(memfile, O_RDWR | O_SYNC);
|
||||||
|
|
||||||
@ -287,10 +351,34 @@ int main(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operation == CLAIM)
|
if (operation == 'C') { /* claim */
|
||||||
claim_interrupt(map_base, claim_ctx, claim_pvalue);
|
if (value_set)
|
||||||
else if (operation == LIST)
|
claim_set(map_base, context, value);
|
||||||
|
else
|
||||||
|
printf("%u\n", claim_get(map_base, context));
|
||||||
|
} else if (operation == 'T') { /* threshold */
|
||||||
|
if (value_set)
|
||||||
|
thre_set(map_base, context, value);
|
||||||
|
else
|
||||||
|
printf("%u\n", thre_get(map_base, context));
|
||||||
|
} else if (operation == 'I') { /* priority */
|
||||||
|
if (value_set)
|
||||||
|
prio_set(map_base, source, value);
|
||||||
|
else
|
||||||
|
printf("%u\n", prio_get(map_base, source));
|
||||||
|
} else if (operation == 'P') { /* pending */
|
||||||
|
if (value_set)
|
||||||
|
pending_set(map_base, source, value);
|
||||||
|
else
|
||||||
|
printf("%u\n", pending_get(map_base, source));
|
||||||
|
} else if (operation == 'E') { /* enable */
|
||||||
|
if (value_set)
|
||||||
|
enable_set(map_base, context, source, value);
|
||||||
|
else
|
||||||
|
printf("%u\n", enable_get(map_base, context, source));
|
||||||
|
} else /* list */ {
|
||||||
list_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