Userspace almost (?) working.
authorBen Pfaff <blp@cs.stanford.edu>
Fri, 27 Aug 2004 00:05:55 +0000 (00:05 +0000)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 27 Aug 2004 00:05:55 +0000 (00:05 +0000)
src/threads/thread.c
src/userprog/addrspace.c
src/userprog/addrspace.h

index 04b446f9f475d0225b45b4f6e6d797a12defbd87..82858dfca059874717e0f01c77db979634f9000e 100644 (file)
@@ -2,6 +2,7 @@
 #include <stddef.h>
 #include "debug.h"
 #include "interrupt.h"
+#include "intr-stubs.h"
 #include "lib.h"
 #include "mmu.h"
 #include "palloc.h"
@@ -105,13 +106,42 @@ thread_current (void)
 bool
 thread_execute (const char *filename) 
 {
-  struct thread *t = new_thread (filename);
+  struct thread *t;
+  struct intr_frame *if_;
+  struct switch_thunk_frame *tf;
+  struct switch_frame *sf;
+  void (*start) (void);
+
+  ASSERT (filename != NULL);
+
+  t = new_thread (filename);
   if (t == NULL)
     return false;
   
-  if (!addrspace_load (&t->addrspace, filename)) 
+  if (!addrspace_load (&t->addrspace, filename, &start)) 
     panic ("%s: program load failed", filename);
-  printk ("%s: loaded\n", filename);
+
+  /* Interrupt frame. */
+  if_ = alloc_frame (t, sizeof *if_);
+  if_->es = SEL_UDSEG;
+  if_->ds = SEL_UDSEG;
+  if_->eip = start;
+  if_->cs = SEL_UCSEG;
+  if_->eflags = FLAG_IF | 2;
+  if_->esp = PHYS_BASE;
+  if_->ss = SEL_UDSEG;
+  
+  /* Stack frame for switch_thunk(). */
+  tf = alloc_frame (t, sizeof *tf);
+  tf->eip = (void (*) (void)) intr_exit;
+
+  /* Stack frame for thread_switch(). */
+  sf = alloc_frame (t, sizeof *sf);
+  sf->eip = (void (*) (void)) switch_thunk;
+
+  /* Add to run queue. */
+  thread_ready (t);
+
   return true;
 }
 #endif
index 28e89f7884ec2d5245ded6c056bddfe3b9fa885d..eb0de496851a5a340270e8d1cdd38074d677d88e 100644 (file)
@@ -78,6 +78,21 @@ struct Elf32_Phdr
                 goto error;                                     \
         } while (0)
 
+static bool
+install_page (struct addrspace *as, void *upage, void *kpage)
+{
+  /* Verify that there's not already a page at that virtual
+     address, then map our page there. */
+  if (pagedir_get_page (as->pagedir, upage) == NULL
+      && pagedir_set_page (as->pagedir, upage, kpage, true))
+    return true;
+  else
+    {
+      palloc_free (kpage);
+      return false;
+    }
+}
+
 static bool
 load_segment (struct addrspace *as, struct file *file,
               const struct Elf32_Phdr *phdr) 
@@ -132,19 +147,29 @@ load_segment (struct addrspace *as, struct file *file,
       memset (kpage + read_bytes, 0, zero_bytes);
       filesz_left -= read_bytes;
 
-      if (pagedir_get_page (as->pagedir, upage))
-        {
-          palloc_free (kpage);
-          return false;
-        }
-      pagedir_set_page (as->pagedir, upage, kpage, true);
+      if (!install_page (as, upage, kpage))
+        return false;
     }
 
   return true;
 }
 
+static bool
+setup_stack (struct addrspace *as) 
+{
+  uint8_t *kpage = palloc_get (PAL_ZERO);
+  if (kpage == NULL)
+    {
+      printk ("failed to allocate process stack\n");
+      return false;
+    }
+
+  return install_page (as, ((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
+}
+
 bool
-addrspace_load (struct addrspace *as, const char *filename) 
+addrspace_load (struct addrspace *as, const char *filename,
+                void (**start) (void)) 
 {
   struct Elf32_Ehdr ehdr;
   struct file *file = NULL;
@@ -177,7 +202,6 @@ addrspace_load (struct addrspace *as, const char *filename)
 
   /* Read program headers. */
   file_ofs = ehdr.e_phoff;
-  printk ("e_phnum=%d\n", ehdr.e_phnum);
   for (i = 0; i < ehdr.e_phnum; i++) 
     {
       struct Elf32_Phdr phdr;
@@ -196,7 +220,7 @@ addrspace_load (struct addrspace *as, const char *filename)
         case PT_NULL:
         case PT_NOTE:
         case PT_PHDR:
-        case PT_STACK: /* Stack segment. */
+        case PT_STACK:
           /* Ignore this segment. */
           break;
         case PT_DYNAMIC:
@@ -214,6 +238,14 @@ addrspace_load (struct addrspace *as, const char *filename)
           break;
         }
     }
+
+  /* Set up stack. */
+  if (!setup_stack (as))
+    goto error;
+
+  /* Start address. */
+  *start = (void (*) (void)) ehdr.e_entry;
+
   success = true;
 
  error:
index 8de4dfeca5f05de7fbe402b61a0f316ea55a7d8d..46ff74517963af4ebb725ef4178600bbdc1ae366 100644 (file)
@@ -9,7 +9,7 @@ struct addrspace
     uint32_t *pagedir;
   };
 
-bool addrspace_load (struct addrspace *, const char *);
+bool addrspace_load (struct addrspace *, const char *, void (**start) (void));
 void addrspace_destroy (struct addrspace *);
 
 void addrspace_activate (struct addrspace *);