23 #include <sys/ioctl.h>
30 #include <sys/epoll.h>
36 static uint32_t entrypoint;
38 #define dbg(fmt, ...) if (g_debug) { \
39 fprintf(stderr, "nmctl: " fmt, ##__VA_ARGS__); \
42 #define err(fmt, ...) if (g_debug) { \
43 fprintf(stderr, "nmctl: " fmt, ##__VA_ARGS__); \
57 ret = ioctl(h->
iofd, IOCTL_NMC3_GET_NAME, name);
63 ret = ioctl(h->
iofd, IOCTL_NMC3_GET_TYPE, type);
69 struct nmc_core_stats stats;
71 ret = ioctl(h->
iofd, IOCTL_NMC3_GET_STATS, &stats);
81 printf(
"%d. name: %s type: %s (%s) appid: %s\n",
82 h->
id, name, type, status, appid
87 printf(
" Initcode version: %x, %s\n", codever,
91 printf(
" IRQs Recv: HP: %d LP: %d\n",
92 stats.irqs_recv[NMC_IRQ_HP],
93 stats.irqs_recv[NMC_IRQ_LP]
96 printf(
" IRQs Sent: NMI: %d HP: %d LP: %d\n",
97 stats.irqs_sent[NMC_IRQ_NMI],
98 stats.irqs_sent[NMC_IRQ_HP],
99 stats.irqs_sent[NMC_IRQ_LP]
110 printf(
"Booting core %d with %s ipl\n", h->
id, (optarg ?
"debug" :
"production"));
114 fprintf(stderr,
"Failed to boot core #%d\n", h->
id);
124 printf(
"=== Init code registers dump ===\n");
165 printf(
"ABS file %s loaded, ok\n", optarg);
167 printf(
"Failed to load ABS file %s\n", optarg);
179 printf(
"NMC app now started!\n");
181 printf(
"Failed to start app!\n");
195 if (strcmp(optarg,
"nmi")==0)
197 else if (strcmp(optarg,
"lp")==0)
199 else if (strcmp(optarg,
"hp")==0)
211 printf(
"Monitoring events, CTRL+C to terminate\n");
216 if (evt != EASYNMC_EVT_TIMEOUT)
228 fprintf(stderr,
"Application is in state running (not killable)\n");
229 fprintf(stderr,
"Killing it may cause userspace to misbehave\n");
230 fprintf(stderr,
"Use --force to kill it anyway\n");
236 printf(
"App on core %d terminated\n", h->
id);
242 printf(
"Failed to terminate app on core %d\n", h->
id);
243 printf(
"This will likely be only fixed by a reboot, sorry\n");
254 printf(
"Monitoring events on core %d (epoll), CTRL+C to terminate\n", h->
id);
259 struct epoll_event event;
260 struct epoll_event *events;
261 int efd = epoll_create(1);
264 perror (
"epoll_create");
269 event.data.fd = h->
memfd;
270 event.events = EPOLLNMI | EPOLLHP | EPOLLLP;
271 ret = epoll_ctl (efd, EPOLL_CTL_ADD, h->
memfd, &event);
274 perror (
"epoll_ctl");
279 events = calloc (
NUMEVENTS,
sizeof event);
283 n = epoll_wait(efd, events,
NUMEVENTS, -1);
284 for (i = 0; i < n; i++) {
285 if (events[i].events & EPOLLNMI)
286 printf(
"Event: NMI\n");
287 if (events[i].events & EPOLLLP)
288 printf(
"Event: LP\n");
289 if (events[i].events & EPOLLHP)
290 printf(
"Event: HP\n");
291 if (events[i].events & EPOLLERR)
292 printf(
"Event: ERROR\n");
300 static struct option long_options[] =
303 {
"list", no_argument, 0,
'l' },
304 {
"help", no_argument, 0,
'h' },
307 {
"core", required_argument, 0,
'c' },
308 {
"force", no_argument, &
g_force, 1 },
309 {
"nostdio", no_argument, &
g_nostdio, 1 },
312 {
"boot", optional_argument, 0,
'b' },
313 {
"reset-stats", no_argument, 0,
'r' },
314 {
"load", required_argument, 0,
'L' },
315 {
"start", required_argument, 0,
's' },
316 {
"irq", required_argument, 0,
'i' },
317 {
"mon", no_argument, 0,
'm' },
318 {
"mon-epoll", no_argument, 0,
'M' },
319 {
"kill", no_argument, 0,
'k' },
324 {
"debug", no_argument, &
g_debug, 1 },
325 {
"dump-ldr-regs", optional_argument, 0,
'D' },
333 "nmctl - The EasyNMC control utility\n"
334 "(c) 2014 RC Module | Andrew 'Necromant' Andrianov <andrew@ncrmnt.org>\n"
335 "This is free software; see the source for copying conditions. There is NO\n"
336 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
338 "Usage: %s [options] [actions] - operate on core 0 (default)\n"
339 " %s --core=n [options] - operate on selected core\n"
340 " %s --core=all [options] - operate all cores\n"
341 "Valid options are: \n"
342 " --core=id - Select a core to operate on (--core=all selects all cores)\n"
343 " --list - list available nmc cores in this system and their state\n"
344 " --help - Show this help\n"
345 " --force - Disable internal seatbelts (DANGEROUS!)\n"
346 " --nostdio - Do not auto-attach stdio\n"
347 " --debug - print lots of debugging info (nmctl)\n"
348 " --debug-lib - print lots of debugging info (libeasynmc)\n"
349 "Valid actions are: \n"
350 " --boot - Load initcode and boot a core (all cores)\n"
351 " --reset-stats - Reset driver statistics for core (all cores)\n"
352 " --load=file.abs - Load abs file to core internal memory\n"
353 " --start=file.abs - Load abs file to core internal memory and start it\n"
354 " --irq=[nmi,lp,hp] - Send an interrupt to NMC\n"
355 " --kill - Abort nmc program execution\n"
356 " --mon - Monitor IRQs from NMC\n"
357 " --dump-ldr-regs - Dump init code memory registers\n\n"
358 "ProTIP(tm): You can supply init code file to use via NMC_STARTUPCODE env var\n"
359 " When no env is set nmctl will search a set of predefined paths\n"
364 static int for_each_core_optarg(
int core,
int (*cb)(
struct easynmc_handle *h,
void *optarg),
char* optarg)
371 fprintf(stderr,
"Iterated over 0 cores, kernel driver problem?\n");
377 fprintf(stderr,
"easynmc_open_noboot() failed. Kernel driver problem or invalid core?\n");
384 int main (
int argc,
char **argv)
389 usage(argv[0]), exit(1);
394 int option_index = 0;
396 c = getopt_long (argc, argv,
"lhb:zr:",
397 long_options, &option_index);
406 if (strcmp(optarg,
"all") == 0)
412 return for_each_core_optarg(core,
do_mon, optarg);
414 return for_each_core_optarg(core,
do_mon, optarg);
418 return for_each_core_optarg(core,
do_kill, NULL);
420 return for_each_core_optarg(core,
do_irq, optarg);
425 ret = for_each_core_optarg(core,
do_load_abs, optarg);
428 fprintf(stderr,
"Failed to load abs file to nmc core(s)\n");
436 return for_each_core_optarg(core,
do_boot_core, optarg);