Proc data structure management, env gutting
[akaros.git] / kern / src / monitor.c
index 42e4010..71855a7 100644 (file)
@@ -1,14 +1,13 @@
 // Simple command-line kernel monitor useful for
 // controlling the kernel and exploring the system interactively.
 
-#ifdef __DEPUTY__
-#pragma nodeputy
+#ifdef __SHARC__
+#pragma nosharc
 #endif
 
-#include <arch/x86.h>
-#include <arch/stab.h>
-#include <arch/apic.h>
-#include <arch/smp.h>
+#include <arch/arch.h>
+#include <stab.h>
+#include <smp.h>
 #include <arch/console.h>
 
 #include <stdio.h>
@@ -20,6 +19,9 @@
 #include <kdebug.h>
 #include <testing.h>
 #include <kfs.h>
+#include <manager.h>
+#include <schedule.h>
+#include <resource.h>
 
 #include <ros/memlayout.h>
 
@@ -32,7 +34,7 @@ typedef struct command {
        int (*func)(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 } command_t;
 
-static command_t commands[] = {
+static command_t (RO commands)[] = {
        { "help", "Display this list of commands", mon_help },
        { "kerninfo", "Display information about the kernel", mon_kerninfo },
        { "backtrace", "Dump a backtrace", mon_backtrace },
@@ -43,6 +45,8 @@ static command_t commands[] = {
        { "nanwan", "Meet Nanwan!!", mon_nanwan},
        { "kfs_ls", "List files in KFS", mon_kfs_ls},
        { "kfs_run", "Create and run a program from KFS", mon_kfs_run},
+       { "manager", "Run the manager", mon_manager},
+       { "procinfo", "Show information about processes", mon_procinfo},
 };
 #define NCOMMANDS (sizeof(commands)/sizeof(commands[0]))
 
@@ -59,7 +63,7 @@ int mon_help(int argc, char **argv, trapframe_t *tf)
 
 int mon_kerninfo(int argc, char **argv, trapframe_t *tf)
 {
-       extern char (SNT _start)[], (SNT etext)[], (SNT edata)[], (SNT end)[];
+       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));
@@ -71,19 +75,21 @@ int mon_kerninfo(int argc, char **argv, trapframe_t *tf)
        return 0;
 }
 
-static char* function_of(uint32_t address) 
+#if 0
+zra: not called
+static char RO* function_of(uint32_t address)
 {
-       extern stab_t stab[], estab[];
-       extern char stabstr[];
+       extern stab_t (RO stab)[], (RO estab)[];
+       extern char (RO stabstr)[];
        stab_t* symtab;
        stab_t* best_symtab = 0;
        uint32_t best_func = 0;
-       
+
        // ugly and unsorted
        for (symtab = stab; symtab < estab; symtab++) {
                // only consider functions, type = N_FUN
-               if ((symtab->n_type == N_FUN) && 
-                   (symtab->n_value <= address) && 
+               if ((symtab->n_type == N_FUN) &&
+                   (symtab->n_value <= address) &&
                        (symtab->n_value > best_func)) {
                        best_func = symtab->n_value;
                        best_symtab = symtab;
@@ -94,50 +100,19 @@ static char* function_of(uint32_t address)
                return "Function not found!";
        return stabstr + best_symtab->n_strx;
 }
+#endif
 
 int mon_backtrace(int argc, char **argv, trapframe_t *tf)
 {
-       uint32_t* ebp, eip;
-       eipdebuginfo_t debuginfo;
-       char buf[256];
-       int j, i = 1;
-       ebp = (uint32_t*)read_ebp();    
-       // this is part of the way back into the call() instruction's bytes
-       // eagle-eyed readers should be able to explain why this is good enough,
-       // and retaddr (just *(ebp + 1) is not)
-       eip = *(ebp + 1) - 1;
-       // jump back a frame (out of mon_backtrace)
-       ebp = (uint32_t*)(*ebp);
-       cprintf("Stack Backtrace:\n");
-       // on each iteration, ebp holds the stack frame and eip an addr in that func
-       while (ebp != 0) {
-               debuginfo_eip(eip, &debuginfo);
-               memset(buf, 0, 256);
-               strncpy(buf, debuginfo.eip_fn_name, MIN(debuginfo.eip_fn_namelen, 256));
-               buf[MIN(debuginfo.eip_fn_namelen, 255)] = 0;
-               cprintf("#%02d [<%x>] in %s+%x(%p) from %s:%d\n", i++,  eip, buf, 
-                       debuginfo.eip_fn_addr - (uint32_t)_start, debuginfo.eip_fn_addr, 
-                       debuginfo.eip_file, debuginfo.eip_line);
-               cprintf("    ebp: %x   Args:", ebp);
-               for (j = 0; j < MIN(debuginfo.eip_fn_narg, 5); j++)
-                       cprintf(" %08x", *(ebp + 2 + j));
-               cprintf("\n");
-               eip = *(ebp + 1) - 1;
-               ebp = (uint32_t*)(*ebp);
-       }
+       backtrace();
        return 0;
 }
 
 int mon_reboot(int argc, char **argv, trapframe_t *tf)
 {
        cprintf("[Irish Accent]: She's goin' down, Cap'n!\n");
-       outb(0x92, 0x3);
-       // KVM doesn't reboot yet, but this next bit will make it
-       // if you're in kernel mode and you can't do a push, when an interrupt
-       // comes in, the system just resets.  if esp = 0, there's no room left.
-       // somewhat curious about what happens in an SMP....
-       cprintf("[Irish Accent]: I'm givin' you all she's got!\n");
-       asm volatile ("movl $0, %esp; int $0");
+       reboot();
+
        // really, should never see this
        cprintf("Sigh....\n");
        return 0;
@@ -147,7 +122,7 @@ int mon_showmapping(int argc, char **argv, trapframe_t *tf)
 {
        if (argc < 2) {
                cprintf("Shows virtual -> physical mappings for a virtual address range.\n");
-               cprintf("Usage: showmappings START_ADDR [END_ADDR]\n");
+               cprintf("Usage: showmapping START_ADDR [END_ADDR]\n");
                return 1;
        }
        pde_t* pgdir = (pde_t*)vpd;
@@ -161,26 +136,17 @@ int mon_showmapping(int argc, char **argv, trapframe_t *tf)
                cprintf("Not going to do this for more than 512 items\n");
                return 1;
        }
-       cprintf("   Virtual    Physical  Ps Dr Ac CD WT U W\n");
-       cprintf("------------------------------------------\n");
-       for(i = 0; i < size; i += PGSIZE, start += PGSIZE) {
-               page = page_lookup(pgdir, (void*)start, &pte);
-               cprintf("%08p  ", start);
-               if (page) {
-                       pde = &pgdir[PDX(start)];
-                       // for a jumbo, pde = pte and PTE_PS (better be) = 1
-                       cprintf("%08p  %1d  %1d  %1d  %1d  %1d  %1d %1d\n", page2pa(page), 
-                              (*pte & PTE_PS) >> 7, (*pte & PTE_D) >> 6, (*pte & PTE_A) >> 5,
-                              (*pte & PTE_PCD) >> 4, (*pte & PTE_PWT) >> 3, 
-                              (*pte & *pde & PTE_U) >> 2, (*pte & *pde & PTE_W) >> 1);
-               } else
-                       cprintf("%08p\n", 0);
-       }
+
+       show_mapping(start,size);
        return 0;
 }
 
 int mon_setmapperm(int argc, char **argv, trapframe_t *tf)
 {
+#ifndef __i386__
+       cprintf("I don't support this call yet!\n");
+       return 1;
+#else
        if (argc < 3) {
                cprintf("Sets VIRT_ADDR's mapping's permissions to PERMS (in hex)\n");
                cprintf("Only affects the lowest level PTE.  To adjust the PDE, do the math.\n");
@@ -188,12 +154,12 @@ int mon_setmapperm(int argc, char **argv, trapframe_t *tf)
                cprintf("Usage: setmapperm VIRT_ADDR PERMS\n");
                return 1;
        }
-       pde_t* pgdir = (pde_t*)vpd;
+       pde_t*COUNT(PTSIZE) pgdir = (pde_t*COUNT(PTSIZE))vpd;
        pte_t *pte, *pde;
        page_t* page;
        uintptr_t va;
        va = ROUNDDOWN(strtol(argv[1], 0, 16), PGSIZE);
-       page = page_lookup(pgdir, (void*)va, &pte);
+       page = page_lookup(pgdir, (void*SNT)va, &pte);
        if (!page) {
                cprintf("No such mapping\n");
                return 1;
@@ -201,30 +167,39 @@ int mon_setmapperm(int argc, char **argv, trapframe_t *tf)
        pde = &pgdir[PDX(va)];
        cprintf("   Virtual    Physical  Ps Dr Ac CD WT U W\n");
        cprintf("------------------------------------------\n");
-       cprintf("%08p  %08p  %1d  %1d  %1d  %1d  %1d  %1d %1d\n", va, page2pa(page), 
-              (*pte & PTE_PS) >> 7, (*pte & PTE_D) >> 6, (*pte & PTE_A) >> 5, 
-              (*pte & PTE_PCD) >> 4, (*pte & PTE_PWT) >> 3, (*pte & *pde & PTE_U) >> 2, 
+       cprintf("%08p  %08p  %1d  %1d  %1d  %1d  %1d  %1d %1d\n", va, page2pa(page),
+              (*pte & PTE_PS) >> 7, (*pte & PTE_D) >> 6, (*pte & PTE_A) >> 5,
+              (*pte & PTE_PCD) >> 4, (*pte & PTE_PWT) >> 3, (*pte & *pde & PTE_U) >> 2,
               (*pte & *pde & PTE_W) >> 1);
        *pte = PTE_ADDR(*pte) | (*pte & PTE_PS) |
               (PGOFF(strtol(argv[2], 0, 16)) & ~PTE_PS ) | PTE_P;
-       cprintf("%08p  %08p  %1d  %1d  %1d  %1d  %1d  %1d %1d\n", va, page2pa(page), 
-              (*pte & PTE_PS) >> 7, (*pte & PTE_D) >> 6, (*pte & PTE_A) >> 5, 
-              (*pte & PTE_PCD) >> 4, (*pte & PTE_PWT) >> 3, (*pte & *pde & PTE_U) >> 2, 
+       cprintf("%08p  %08p  %1d  %1d  %1d  %1d  %1d  %1d %1d\n", va, page2pa(page),
+              (*pte & PTE_PS) >> 7, (*pte & PTE_D) >> 6, (*pte & PTE_A) >> 5,
+              (*pte & PTE_PCD) >> 4, (*pte & PTE_PWT) >> 3, (*pte & *pde & PTE_U) >> 2,
               (*pte & *pde & PTE_W) >> 1);
        return 0;
+#endif
 }
 
 int mon_cpuinfo(int argc, char **argv, trapframe_t *tf)
 {
-       extern uint8_t num_cpus;
+       cprintf("Number of CPUs detected: %d\n", num_cpus);
+       cprintf("Calling CPU's ID: 0x%08x\n", core_id());
 
-       cprintf("Number of CPUs detected: %d\n", num_cpus);     
-       cprintf("Calling CPU's LAPIC ID: 0x%08x\n", lapic_get_id());
+#ifdef __i386__
        if (argc < 2)
-               smp_call_function_self(test_print_info_handler, 0, 0);
+               smp_call_function_self(test_print_info_handler, NULL, 0);
        else
                smp_call_function_single(strtol(argv[1], 0, 16),
-                                        test_print_info_handler, 0, 0);
+                                        test_print_info_handler, NULL, 0);
+#endif
+       return 0;
+}
+
+int mon_manager(int argc, char** argv, trapframe_t *tf)
+{
+       manager();
+       panic("should never get here");
        return 0;
 }
 
@@ -280,8 +255,12 @@ int mon_kfs_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                printk("Bad filename!\n");
                return 1;
        }
-       env_t *new_e = kfs_proc_create(kfs_inode);
-       new_e->env_status = ENV_RUNNABLE;
+       struct proc *p = kfs_proc_create(kfs_inode);
+       // go from PROC_CREATED->PROC_RUNNABLE_S
+       spin_lock_irqsave(&p->proc_lock); // might not be necessary for a mon function
+       __proc_set_state(p, PROC_RUNNABLE_S);
+       schedule_proc(p);
+       spin_unlock_irqsave(&p->proc_lock);
        // 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 around that are runnable
@@ -289,13 +268,69 @@ int mon_kfs_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
        return 0;
 }
 
+int mon_procinfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
+{
+       if (argc < 2) {
+               printk("Usage: procinfo OPTION\n");
+               printk("\tidlecores: show idle core map\n");
+               printk("\tall: show all active pids\n");
+               printk("\trunnable: show proc_runnablelist\n");
+               printk("\tresources: show resources wanted/granted for all procs\n");
+               printk("\tpid NUM: show a lot of info for proc NUM\n");
+               printk("\tunlock NUM: unlock the lock for proc NUM (OMG!!!)\n");
+               printk("\tkill NUM: destroy proc NUM\n");
+               return 1;
+       }
+       if (!strcmp(argv[1], "idlecores")) {
+               print_idlecoremap();
+       } else if (!strcmp(argv[1], "all")) {
+               print_allpids();
+       } else if (!strcmp(argv[1], "runnable")) {
+               dump_proclist(&proc_runnablelist);
+       } else if (!strcmp(argv[1], "resources")) {
+               print_all_resources();
+       } else if (!strcmp(argv[1], "pid")) {
+               if (argc != 3) {
+                       printk("Give me a pid number.\n");
+                       return 1;
+               }
+               print_proc_info(strtol(argv[2], 0, 0));
+       } else if (!strcmp(argv[1], "unlock")) {
+               if (argc != 3) {
+                       printk("Give me a pid number.\n");
+                       return 1;
+               }
+               struct proc *p = pid2proc(strtol(argv[2], 0, 0));
+               if (!p) {
+                       printk("No such proc\n");
+                       return 1;
+               }
+               spin_unlock_irqsave(&p->proc_lock);
+       } else if (!strcmp(argv[1], "kill")) {
+               if (argc != 3) {
+                       printk("Give me a pid number.\n");
+                       return 1;
+               }
+               struct proc *p = pid2proc(strtol(argv[2], 0, 0));
+               if (!p) {
+                       printk("No such proc\n");
+                       return 1;
+               }
+               proc_destroy(p);
+       } else {
+               printk("Bad option\n");
+               return 1;
+       }
+       return 0;
+}
+
 /***** Kernel monitor command interpreter *****/
 
 #define WHITESPACE "\t\r\n "
 #define MAXARGS 16
 
-static int runcmd(char *COUNT(CMDBUF_SIZE) real_buf, trapframe_t *tf) {
-       char *BND(real_buf, real_buf+CMDBUF_SIZE) buf = real_buf;
+static int runcmd(char *NTS real_buf, trapframe_t *tf) {
+       char * buf = NTEXPAND(real_buf);
        int argc;
        char *NTS argv[MAXARGS];
        int i;
@@ -316,7 +351,7 @@ static int runcmd(char *COUNT(CMDBUF_SIZE) real_buf, trapframe_t *tf) {
                        return 0;
                }
                //This will get fucked at runtime..... in the ASS
-               argv[argc++] = (char *NTS) TC(buf);
+               argv[argc++] = buf;
                while (*buf && !strchr(WHITESPACE, *buf))
                        buf++;
        }
@@ -336,8 +371,8 @@ static int runcmd(char *COUNT(CMDBUF_SIZE) real_buf, trapframe_t *tf) {
 void monitor(trapframe_t *tf) {
        char *buf;
 
-       cprintf("Welcome to the ROS kernel monitor!\n");
-       cprintf("Type 'help' for a list of commands.\n");
+       printk("Welcome to the ROS kernel monitor on core %d!\n", core_id());
+       printk("Type 'help' for a list of commands.\n");
 
        if (tf != NULL)
                print_trapframe(tf);