Fixes gcc 4.6.1 incompatibility with old x86 asm
[akaros.git] / kern / src / monitor.c
index 4ede378..ea6fd8b 100644 (file)
 #include <kmalloc.h>
 #include <elf.h>
 #include <event.h>
+#include <trap.h>
 
-#include <ros/timer.h>
+#include <ros/time.h>
 #include <ros/memlayout.h>
+#include <ros/event.h>
 
 #define CMDBUF_SIZE    80      // enough for one VGA text line
 
@@ -57,10 +59,11 @@ static command_t (RO commands)[] = {
        { "kfunc", "Run a kernel function directly (!!!)", mon_kfunc},
        { "notify", "Notify a process.  Vcoreid will skip their prefs", mon_notify},
        { "measure", "Run a specific measurement", mon_measure},
-       { "trace", "Run a specific measurement", mon_trace},
+       { "trace", "Run some tracing functions", mon_trace},
        { "monitor", "Run the monitor on another core", mon_monitor},
        { "fs", "Filesystem Diagnostics", mon_fs},
        { "bb", "Try to run busybox (ash)", mon_bb},
+       { "alarm", "Alarm Diagnostics", mon_alarm},
 };
 #define NCOMMANDS (sizeof(commands)/sizeof(commands[0]))
 
@@ -86,10 +89,10 @@ int mon_kerninfo(int argc, char **argv, trapframe_t *tf)
        extern char (RO SNT _start)[], (RO SNT etext)[], (RO SNT edata)[], (RO SNT end)[];
 
        cprintf("Special kernel symbols:\n");
-       cprintf("  _start %08x (virt)  %08x (phys)\n", _start, (uint32_t)(_start - KERNBASE));
-       cprintf("  etext  %08x (virt)  %08x (phys)\n", etext, (uint32_t)(etext - KERNBASE));
-       cprintf("  edata  %08x (virt)  %08x (phys)\n", edata, (uint32_t)(edata - KERNBASE));
-       cprintf("  end    %08x (virt)  %08x (phys)\n", end, (uint32_t)(end - KERNBASE));
+       cprintf("  _start %016x (virt)  %016x (phys)\n", _start, (uintptr_t)(_start - KERNBASE));
+       cprintf("  etext  %016x (virt)  %016x (phys)\n", etext, (uintptr_t)(etext - KERNBASE));
+       cprintf("  edata  %016x (virt)  %016x (phys)\n", edata, (uintptr_t)(edata - KERNBASE));
+       cprintf("  end    %016x (virt)  %016x (phys)\n", end, (uintptr_t)(end - KERNBASE));
        cprintf("Kernel executable memory footprint: %dKB\n",
                (uint32_t)(end-_start+1023)/1024);
        return 0;
@@ -300,7 +303,7 @@ int mon_bin_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
        __proc_set_state(p, PROC_RUNNABLE_S);
        schedule_proc(p);
        spin_unlock(&p->proc_lock);
-       kref_put(&p->kref); /* let go of the reference created in proc_create() */
+       proc_decref(p); /* let go of the reference created in proc_create() */
        kref_put(&program->f_kref);
        /* Should never return from schedule (env_pop in there) also note you may
         * not get the process you created, in the event there are others floating
@@ -358,7 +361,7 @@ int mon_procinfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                        return 1;
                }
                proc_destroy(p);
-               kref_put(&p->kref);
+               proc_decref(p);
        } else {
                printk("Bad option\n");
                return 1;
@@ -461,7 +464,7 @@ int mon_notify(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                /* o/w, try and do what they want */
                send_kernel_event(p, &msg, 0);
        }
-       kref_put(&p->kref);
+       proc_decref(p);
        return 0;
 }
 
@@ -470,7 +473,6 @@ int mon_notify(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
 int mon_measure(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
 {
        uint64_t begin = 0, diff = 0;
-       bool self_ipi_pending = FALSE;
        uint32_t end_refcnt = 0;
 
        if (argc < 2) {
@@ -497,14 +499,14 @@ int mon_measure(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                begin = start_timing();
 #ifdef __CONFIG_APPSERVER__
                printk("Warning: this will be inaccurate due to the appserver.\n");
-               end_refcnt = kref_refcnt(&p->kref) - p->procinfo->num_vcores - 1;
+               end_refcnt = kref_refcnt(&p->p_kref) - p->procinfo->num_vcores - 1;
 #endif /* __CONFIG_APPSERVER__ */
                proc_destroy(p);
-               kref_put(&p->kref);
+               proc_decref(p);
 #ifdef __CONFIG_APPSERVER__
                /* Won't be that accurate, since it's not actually going through the
                 * __proc_free() path. */
-               spin_on(kref_refcnt(&p->kref) != end_refcnt);   
+               spin_on(kref_refcnt(&p->p_kref) != end_refcnt); 
 #else
                /* this is a little ghetto. it's not fully free yet, but we are also
                 * slowing it down by messing with it, esp with the busy waiting on a
@@ -531,14 +533,14 @@ int mon_measure(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                        spin_on(p->procinfo->pcoremap[pcoreid].valid);
                        diff = stop_timing(begin);
                } else { /* preempt all cores, warned but no delay */
-                       end_refcnt = kref_refcnt(&p->kref) - p->procinfo->num_vcores;
+                       end_refcnt = kref_refcnt(&p->p_kref) - p->procinfo->num_vcores;
                        begin = start_timing();
                        proc_preempt_all(p, 1000000);
                        /* a little ghetto, implies no one is using p */
-                       spin_on(kref_refcnt(&p->kref) != end_refcnt);
+                       spin_on(kref_refcnt(&p->p_kref) != end_refcnt);
                        diff = stop_timing(begin);
                }
-               kref_put(&p->kref);
+               proc_decref(p);
        } else if (!strcmp(argv[1], "preempt-warn")) {
                if (argc < 3) {
                        printk("Give me a pid number.\n");
@@ -549,6 +551,7 @@ int mon_measure(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                        printk("No such proc\n");
                        return 1;
                }
+               printk("Careful: if this hangs, then the process isn't responding.\n");
                if (argc == 4) { /* single core being preempted-warned */
                        uint32_t pcoreid = strtol(argv[3], 0, 0);
                        spin_lock(&p->proc_lock);
@@ -575,7 +578,7 @@ int mon_measure(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                        spin_on(p->procinfo->num_vcores > 1);
                        diff = stop_timing(begin);
                }
-               kref_put(&p->kref);
+               proc_decref(p);
        } else if (!strcmp(argv[1], "preempt-raw")) {
                if (argc < 3) {
                        printk("Give me a pid number.\n");
@@ -595,42 +598,41 @@ int mon_measure(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                                return 1;
                        }
                        begin = start_timing();
-                       self_ipi_pending = __proc_preempt_core(p, pcoreid);
+                       __proc_preempt_core(p, pcoreid);
                        spin_unlock(&p->proc_lock);
-                       __proc_kmsg_pending(p, self_ipi_pending);
                        /* done when unmapped (right before abandoning) */
                        spin_on(p->procinfo->pcoremap[pcoreid].valid);
                        diff = stop_timing(begin);
                        /* TODO: (RMS), if num_vcores == 0, RUNNABLE_M, schedule */
                } else { /* preempt all cores, no warning or waiting */
                        spin_lock(&p->proc_lock);
-                       end_refcnt = kref_refcnt(&p->kref) - p->procinfo->num_vcores;
+                       end_refcnt = kref_refcnt(&p->p_kref) - p->procinfo->num_vcores;
                        begin = start_timing();
-                       self_ipi_pending = __proc_preempt_all(p);
+                       __proc_preempt_all(p);
                        /* TODO: (RMS), RUNNABLE_M, schedule */
                        spin_unlock(&p->proc_lock);
-                       __proc_kmsg_pending(p, self_ipi_pending);
                        /* a little ghetto, implies no one else is using p */
-                       spin_on(kref_refcnt(&p->kref) != end_refcnt);
+                       spin_on(kref_refcnt(&p->p_kref) != end_refcnt);
                        diff = stop_timing(begin);
                }
-               kref_put(&p->kref);
+               proc_decref(p);
        } else {
                printk("Bad option\n");
                return 1;
        }
        printk("[Tired Giraffe Accent] Took %llu usec (%llu nsec) to finish.\n",
-              diff * 1000000 / system_timing.tsc_freq,
-              diff * 1000000000 / system_timing.tsc_freq);
+              tsc2usec(diff), tsc2nsec(diff));
        return 0;
 }
 
 int mon_trace(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
 {
+       uint32_t core;
        if (argc < 2) {
                printk("Usage: trace OPTION\n");
                printk("\tsyscall start [silent] [pid]: starts tracing\n");
                printk("\tsyscall stop: stops tracing, prints if it was silent\n");
+               printk("\tcoretf COREID: cause the other core to print its TF (NMI)\n");
                return 1;
        }
        if (!strcmp(argv[1], "syscall")) {
@@ -662,6 +664,18 @@ int mon_trace(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                        systrace_print(TRUE, 0);
                        systrace_clear_buffer();
                }
+       } else if (!strcmp(argv[1], "coretf")) {
+               if (argc != 3) {
+                       printk("Need a coreid, fool.\n");
+                       return 1;
+               }
+               core = strtol(argv[2], 0, 0);
+               if (core >= num_cpus) {
+                       printk("No such core!  Maybe it's in another cell...\n");
+                       return 1;
+               }
+               send_nmi(core);
+               udelay(1000000);
        } else if (!strcmp(argv[1], "opt2")) {
                if (argc != 3) {
                        printk("ERRRRRRRRRR.\n");
@@ -686,10 +700,10 @@ int mon_monitor(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                printk("No such core!  Maybe it's in another cell...\n");
                return 1;
        }
-       void run_mon(struct trapframe *tf, uint32_t srcid, void *a0, void *a1,
-                    void *a2)
+       void run_mon(struct trapframe *tf, uint32_t srcid, long a0, long a1,
+                    long a2)
        {
-               monitor(0); // TODO consider passing the tf
+               monitor(0);
        }
        send_kernel_message(core, run_mon, 0, 0, 0, KMSG_ROUTINE);
        return 0;
@@ -809,16 +823,16 @@ int mon_fs(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                printk("Dentry Cache:\n----------------------------\n");
                TAILQ_FOREACH(sb, &super_blocks, s_list) {
                        printk("Superblock for %s\n", sb->s_name);
-                       if (hashtable_count(sb->s_dcache)) {
-                               hashtable_itr_t *dcache_i = hashtable_iterator(sb->s_dcache);
-                               printk("DENTRY     FLAGS      REFCNT NAME\n");
-                               printk("--------------------------------\n");
-                               do {
-                                       struct dentry *d_i = hashtable_iterator_value(dcache_i);
-                                       printk("%08p %08p %02d     %s\n", d_i, d_i->d_flags,
-                                              kref_refcnt(&d_i->d_kref), d_i->d_name.name);
-                               } while (hashtable_iterator_advance(dcache_i));
+                       printk("DENTRY     FLAGS      REFCNT NAME\n");
+                       printk("--------------------------------\n");
+                       /* Hash helper */
+                       void print_dcache_entry(void *item)
+                       {
+                               struct dentry *d_i = (struct dentry*)item;
+                               printk("%08p %08p %02d     %s\n", d_i, d_i->d_flags,
+                                      kref_refcnt(&d_i->d_kref), d_i->d_name.name);
                        }
+                       hash_for_each(sb->s_dcache, print_dcache_entry);
                }
                if (argc < 3)
                        return 0;
@@ -864,3 +878,19 @@ int mon_bb(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
        char *l_argv[3] = {"", "busybox", "ash"};
        return mon_bin_run(3, l_argv, tf);
 }
+
+int mon_alarm(int argc, char **argv, struct trapframe *tf)
+{
+       if (argc < 2) {
+               printk("Usage: alarm OPTION\n");
+               printk("\tpcpu: print full alarm tchains from every core\n");
+               return 1;
+       }
+       if (!strcmp(argv[1], "pcpu")) {
+               print_pcpu_chains();
+       } else {
+               printk("Bad option\n");
+               return 1;
+       }
+       return 0;
+}