#include <stddef.h>
#include "debug.h"
#include "interrupt.h"
+#include "intr-stubs.h"
#include "lib.h"
#include "mmu.h"
#include "palloc.h"
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
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)
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;
/* 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;
case PT_NULL:
case PT_NOTE:
case PT_PHDR:
- case PT_STACK: /* Stack segment. */
+ case PT_STACK:
/* Ignore this segment. */
break;
case PT_DYNAMIC:
break;
}
}
+
+ /* Set up stack. */
+ if (!setup_stack (as))
+ goto error;
+
+ /* Start address. */
+ *start = (void (*) (void)) ehdr.e_entry;
+
success = true;
error: