From: Ben Pfaff Date: Fri, 27 Aug 2004 00:05:55 +0000 (+0000) Subject: Userspace almost (?) working. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b9d1a06a2bcc6de5251e12be91ad687d3b291244;p=pintos-anon Userspace almost (?) working. --- diff --git a/src/threads/thread.c b/src/threads/thread.c index 04b446f..82858df 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -2,6 +2,7 @@ #include #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 diff --git a/src/userprog/addrspace.c b/src/userprog/addrspace.c index 28e89f7..eb0de49 100644 --- a/src/userprog/addrspace.c +++ b/src/userprog/addrspace.c @@ -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: diff --git a/src/userprog/addrspace.h b/src/userprog/addrspace.h index 8de4dfe..46ff745 100644 --- a/src/userprog/addrspace.h +++ b/src/userprog/addrspace.h @@ -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 *);