Proc data structure management, env gutting
[akaros.git] / kern / src / env.c
index 3a76a8d..5e232b5 100644 (file)
 #include <ros/syscall.h>
 #include <ros/error.h>
 
-env_t *envs = NULL;            // All environments
 atomic_t num_envs;
 
 #define ENVGENSHIFT    12              // >= LOGNENV
 
 //
-// Converts an envid to an env pointer.
-//
-// RETURNS
-//   0 on success, -EBADENV on error.
-//   On success, sets *env_store to the environment.
-//   On error, sets *env_store to NULL.
-//
-int
-envid2env(envid_t envid, env_t **env_store, bool checkperm)
-{
-       env_t *e;
-
-       // If envid is zero, return the current environment.
-       if (envid == 0) {
-               *env_store = current;
-               return 0;
-       }
-
-       // Look up the Env structure via the index part of the envid,
-       // then check the env_id field in that env_t
-       // to ensure that the envid is not stale
-       // (i.e., does not refer to a _previous_ environment
-       // that used the same slot in the envs[] array).
-       e = &envs[ENVX(envid)];
-       if (e->state == ENV_FREE || e->env_id != envid) {
-               *env_store = 0;
-               return -EBADENV;
-       }
-
-       // Check that the calling environment has legitimate permission
-       // to manipulate the specified environment.
-       // If checkperm is set, the specified environment
-       // must be either the current environment
-       // or an immediate child of the current environment.
-       // TODO: should check for current being null
-       if (checkperm && e != current && e->env_parent_id != current->env_id) {
-               *env_store = 0;
-               return -EBADENV;
-       }
-
-       *env_store = e;
-       return 0;
-}
-
-//
-// Mark all environments in 'envs' as free, set their env_ids to 0,
-// and insert them into the proc_freelist.
-// Insert in reverse order, so that the first call to env_alloc()
-// returns envs[0].
-// TODO: get rid of this whole array bullshit
-//
-void
-env_init(void)
-{
-       int i;
-
-       schedule_init();
-       // core 0 is not idle, all others are (for now)
-       spin_lock(&idle_lock);
-       num_idlecores = num_cpus - 1;
-       for (i = 0; i < num_idlecores; i++)
-               idlecoremap[i] = i + 1;
-       spin_unlock(&idle_lock);
-       atomic_init(&num_envs, 0);
-       TAILQ_INIT(&proc_freelist);
-       assert(envs != NULL);
-       for (i = NENV-1; i >= 0; i--) {
-               // these should already be set from when i memset'd the array to 0
-               envs[i].state = ENV_FREE;
-               envs[i].env_id = 0;
-               TAILQ_INSERT_HEAD(&proc_freelist, &envs[i], proc_link);
-       }
-
-}
-
-//
 // Initialize the kernel virtual memory layout for environment e.
 // Allocate a page directory, set e->env_pgdir and e->env_cr3 accordingly,
 // and initialize the kernel portion of the new environment's address space.
@@ -114,8 +37,7 @@ env_init(void)
 // Returns 0 on success, < 0 on error.  Errors include:
 //     -ENOMEM if page directory or table could not be allocated.
 //
-static int
-env_setup_vm(env_t *e)
+int env_setup_vm(env_t *e)
 WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_procdata)
 {
        int i, r;
@@ -226,95 +148,6 @@ env_setup_vm_error:
 }
 
 //
-// Allocates and initializes a new environment.
-// On success, the new environment is stored in *newenv_store.
-//
-// Returns 0 on success, < 0 on failure.  Errors include:
-//     -ENOFREEENV if all NENVS environments are allocated
-//     -ENOMEM on memory exhaustion
-//
-int
-env_alloc(env_t **newenv_store, envid_t parent_id)
-{
-       int32_t generation;
-       int r;
-       env_t *e;
-
-       spin_lock(&freelist_lock);
-       e = TAILQ_FIRST(&proc_freelist);
-       if (e) {
-               TAILQ_REMOVE(&proc_freelist, e, proc_link);
-               spin_unlock(&freelist_lock);
-       } else {
-               spin_unlock(&freelist_lock);
-               return -ENOFREEENV;
-       }
-
-    { INITSTRUCT(*e)
-
-       // Allocate and set up the page directory for this environment.
-       if ((r = env_setup_vm(e)) < 0) {
-               spin_lock(&freelist_lock);
-               TAILQ_INSERT_HEAD(&proc_freelist, e, proc_link);
-               spin_unlock(&freelist_lock);
-               return r;
-       }
-
-       // Generate an env_id for this environment.
-       generation = (e->env_id + (1 << ENVGENSHIFT)) & ~(NENV - 1);
-       if (generation <= 0)    // Don't create a negative env_id.
-               generation = 1 << ENVGENSHIFT;
-       e->env_id = generation | (e - envs);
-
-       // Set the basic status variables.
-    spinlock_init(&e->proc_lock);
-       e->env_parent_id = parent_id;
-       __proc_set_state(e, PROC_CREATED);
-       e->env_runs = 0;
-       e->env_refcnt = 1;
-       e->env_flags = 0;
-       e->env_entry = 0; // cheating.  this really gets set in load_icode
-       e->num_vcores = 0;
-       memset(&e->vcoremap, -1, sizeof(e->vcoremap));
-       //for (int i = 0; i < MAX_NUM_CPUS; i++)
-               //e->vcoremap[i] = -1;
-       memset(&e->resources, 0, sizeof(e->resources));
-
-       memset(&e->env_ancillary_state, 0, sizeof(e->env_ancillary_state));
-       memset(&e->env_tf, 0, sizeof(e->env_tf));
-       proc_init_trapframe(&e->env_tf);
-
-       /*
-        * Initialize the contents of the e->env_procinfo structure
-        */
-        e->env_procinfo->id = (e->env_id & 0x3FF);
-
-       /*
-        * Initialize the contents of the e->env_procdata structure
-        */
-       // Initialize the generic syscall ring buffer
-       SHARED_RING_INIT(&e->env_procdata->syscallring);
-       // Initialize the backend of the syscall ring buffer
-       BACK_RING_INIT(&e->syscallbackring,
-                      &e->env_procdata->syscallring,
-                      SYSCALLRINGSIZE);
-
-       // Initialize the generic sysevent ring buffer
-       SHARED_RING_INIT(&e->env_procdata->syseventring);
-       // Initialize the frontend of the sysevent ring buffer
-       FRONT_RING_INIT(&e->syseventfrontring,
-                       &e->env_procdata->syseventring,
-                       SYSEVENTRINGSIZE);
-
-       *newenv_store = e;
-       atomic_inc(&num_envs);
-
-       printk("[%08x] new env %08x\n", current ? current->env_id : 0, e->env_id);
-       } // INIT_STRUCT
-       return 0;
-}
-
-//
 // Allocate len bytes of physical memory for environment env,
 // and map it at virtual address va in the environment's address space.
 // Does not zero or otherwise initialize the mapped pages in any way.
@@ -367,8 +200,7 @@ segment_alloc(env_t *e, void *SNT va, size_t len)
 // but not actually present in the ELF file - i.e., the program's bss section.
 //
 // Finally, this function maps one page for the program's initial stack.
-static void
-load_icode(env_t *SAFE e, uint8_t *COUNT(size) binary, size_t size)
+void load_icode(env_t *SAFE e, uint8_t *COUNT(size) binary, size_t size)
 {
        // asw: copy the headers because they might not be aligned.
        elf_t elfhdr;
@@ -426,52 +258,6 @@ load_icode(env_t *SAFE e, uint8_t *COUNT(size) binary, size_t size)
        proc_decref(e);
 }
 
-//
-// Allocates a new env and loads the named elf binary into it.
-//
-env_t* env_create(uint8_t *binary, size_t size)
-{
-       env_t *e;
-       int r;
-       envid_t curid;
-
-       curid = (current ? current->env_id : 0);
-       if ((r = env_alloc(&e, curid)) < 0)
-               panic("env_create: %e", r);
-       load_icode(e, binary, size);
-       return e;
-}
-
-//
-// Frees env e and all memory it uses.
-//
-void
-env_free(env_t *e)
-{
-       physaddr_t pa;
-
-       // Note the environment's demise.
-       printk("[%08x] free env %08x\n", current ? current->env_id : 0, e->env_id);
-       // All parts of the kernel should have decref'd before env_free was called.
-       assert(e->env_refcnt == 0);
-
-       // Flush all mapped pages in the user portion of the address space
-       env_user_mem_free(e);
-
-       // free the page directory
-       pa = e->env_cr3;
-       e->env_pgdir = 0;
-       e->env_cr3 = 0;
-       page_decref(pa2page(pa));
-
-       // return the environment to the free list
-       e->state = ENV_FREE;
-       spin_lock(&freelist_lock);
-       TAILQ_INSERT_HEAD(&proc_freelist, e, proc_link);
-       spin_unlock(&freelist_lock);
-}
-
-
 #define PER_CPU_THING(type,name)\
 type SLOCKED(name##_lock) * RWPROTECT name;\
 type SLOCKED(name##_lock) *\
@@ -482,7 +268,6 @@ type SLOCKED(name##_lock) *\
        }\
 }
 
-
 /* This is the top-half of an interrupt handler, where the bottom half is
  * proc_run (which never returns).  Just add it to the delayed work queue,
  * which (incidentally) can only hold one item at this point.