90ff18b14ddaae54563ee7d53d6c0cef538fe5aa
[pintos-anon] / src / userprog / process.c
1 #include "userprog/process.h"
2 #include <debug.h>
3 #include <inttypes.h>
4 #include <round.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include "userprog/gdt.h"
8 #include "userprog/pagedir.h"
9 #include "userprog/tss.h"
10 #include "filesys/directory.h"
11 #include "filesys/file.h"
12 #include "filesys/filesys.h"
13 #include "threads/flags.h"
14 #include "threads/init.h"
15 #include "threads/interrupt.h"
16 #include "threads/mmu.h"
17 #include "threads/palloc.h"
18 #include "threads/thread.h"
19
20 static thread_func execute_thread NO_RETURN;
21 static bool load (const char *cmdline, void (**eip) (void), void **esp);
22
23 /* Starts a new thread running a user program loaded from
24    FILENAME.  The new thread may be scheduled before
25    process_execute() returns.*/
26 tid_t
27 process_execute (const char *filename) 
28 {
29   char *fn_copy;
30   tid_t tid;
31
32   /* Make a copy of FILENAME.
33      Otherwise there's a race between the caller and load(). */
34   fn_copy = palloc_get_page (0);
35   if (fn_copy == NULL)
36     return TID_ERROR;
37   strlcpy (fn_copy, filename, PGSIZE);
38
39   /* Create a new thread to execute FILENAME. */
40   tid = thread_create (filename, PRI_DEFAULT, execute_thread, fn_copy);
41   if (tid == TID_ERROR)
42     palloc_free_page (fn_copy); 
43   return tid;
44 }
45
46 /* A thread function that loads a user process and starts it
47    running. */
48 static void
49 execute_thread (void *filename_)
50 {
51   char *filename = filename_;
52   struct intr_frame if_;
53   bool success;
54
55   /* Initialize interrupt frame and load executable. */
56   memset (&if_, 0, sizeof if_);
57   if_.es = SEL_UDSEG;
58   if_.ds = SEL_UDSEG;
59   if_.cs = SEL_UCSEG;
60   if_.eflags = FLAG_IF | FLAG_MBS;
61   if_.ss = SEL_UDSEG;
62   success = load (filename, &if_.eip, &if_.esp);
63
64   /* If load failed, quit. */
65   palloc_free_page (filename);
66   if (!success) 
67     thread_exit ();
68
69   /* Switch page tables. */
70   process_activate ();
71
72   /* Start the user process by simulating a return from an
73      interrupt, implemented by intr_exit (in
74      threads/intr-stubs.pl).  Because intr_exit takes all of its
75      arguments on the stack in the form of a `struct intr_frame',
76      we just point the stack pointer (%esp) to our stack frame
77      and jump to it. */
78   asm ("mov %0, %%esp\n"
79        "jmp intr_exit\n"
80        : /* no outputs */
81        : "g" (&if_));
82   NOT_REACHED ();
83 }
84
85 /* Free the current process's resources. */
86 void
87 process_exit (void)
88 {
89   struct thread *cur = thread_current ();
90   uint32_t *pd;
91
92   /* Destroy the current process's page directory and switch back
93      to the kernel-only page directory.  We have to set
94      cur->pagedir to NULL before switching page directories, or a
95      timer interrupt might switch back to the process page
96      directory. */
97   pd = cur->pagedir;
98   if (pd != NULL) 
99     {
100       cur->pagedir = NULL;
101       pagedir_activate (NULL);
102       pagedir_destroy (pd);
103     }
104 }
105
106 /* Sets up the CPU for running user code in the current
107    thread. */
108 void
109 process_activate (void)
110 {
111   struct thread *t = thread_current ();
112
113   /* Activate thread's page tables. */
114   pagedir_activate (t->pagedir);
115
116   /* Set thread's kernel stack for use in processing
117      interrupts. */
118   tss_set_esp0 ((uint8_t *) t + PGSIZE);
119 }
120 \f
121 /* We load ELF binaries.  The following definitions are taken
122    from the ELF specification, [ELF1], more-or-less verbatim.  */
123
124 /* ELF types.  See [ELF1] 1-2. */
125 typedef uint32_t Elf32_Word, Elf32_Addr, Elf32_Off;
126 typedef uint16_t Elf32_Half;
127
128 /* For use with ELF types in printf(). */
129 #define PE32Wx PRIx32   /* Print Elf32_Word in hexadecimal. */
130 #define PE32Ax PRIx32   /* Print Elf32_Addr in hexadecimal. */
131 #define PE32Ox PRIx32   /* Print Elf32_Off in hexadecimal. */
132 #define PE32Hx PRIx16   /* Print Elf32_Half in hexadecimal. */
133
134 /* Executable header.  See [ELF1] 1-4 to 1-8.
135    This appears at the very beginning of an ELF binary. */
136 struct Elf32_Ehdr
137   {
138     unsigned char e_ident[16];
139     Elf32_Half    e_type;
140     Elf32_Half    e_machine;
141     Elf32_Word    e_version;
142     Elf32_Addr    e_entry;
143     Elf32_Off     e_phoff;
144     Elf32_Off     e_shoff;
145     Elf32_Word    e_flags;
146     Elf32_Half    e_ehsize;
147     Elf32_Half    e_phentsize;
148     Elf32_Half    e_phnum;
149     Elf32_Half    e_shentsize;
150     Elf32_Half    e_shnum;
151     Elf32_Half    e_shstrndx;
152   };
153
154 /* Program header.  See [ELF1] 2-2 to 2-4.
155    There are e_phnum of these, starting at file offset e_phoff
156    (see [ELF1] 1-6). */
157 struct Elf32_Phdr
158   {
159     Elf32_Word p_type;
160     Elf32_Off  p_offset;
161     Elf32_Addr p_vaddr;
162     Elf32_Addr p_paddr;
163     Elf32_Word p_filesz;
164     Elf32_Word p_memsz;
165     Elf32_Word p_flags;
166     Elf32_Word p_align;
167   };
168
169 /* Values for p_type.  See [ELF1] 2-3. */
170 #define PT_NULL    0            /* Ignore. */
171 #define PT_LOAD    1            /* Loadable segment. */
172 #define PT_DYNAMIC 2            /* Dynamic linking info. */
173 #define PT_INTERP  3            /* Name of dynamic loader. */
174 #define PT_NOTE    4            /* Auxiliary info. */
175 #define PT_SHLIB   5            /* Reserved. */
176 #define PT_PHDR    6            /* Program header table. */
177 #define PT_STACK   0x6474e551   /* Stack segment. */
178
179 /* Flags for p_flags.  See [ELF3] 2-3 and 2-4. */
180 #define PF_X 1          /* Executable. */
181 #define PF_W 2          /* Writable. */
182 #define PF_R 4          /* Readable. */
183
184 static bool load_segment (struct file *, const struct Elf32_Phdr *);
185 static bool setup_stack (void **esp);
186
187 /* Aborts loading an executable, with an error message. */
188 #define LOAD_ERROR(MSG)                                         \
189         do {                                                    \
190                 printf ("load: %s: ", filename);      \
191                 printf MSG;                                     \
192                 printf ("\n");                                  \
193                 goto done;                                     \
194         } while (0)
195
196 /* Loads an ELF executable from FILENAME into the current thread.
197    Stores the executable's entry point into *EIP
198    and its initial stack pointer into *ESP.
199    Returns true if successful, false otherwise. */
200 bool
201 load (const char *filename, void (**eip) (void), void **esp) 
202 {
203   struct thread *t = thread_current ();
204   struct Elf32_Ehdr ehdr;
205   struct file *file = NULL;
206   off_t file_ofs;
207   bool success = false;
208   int i;
209
210   /* Allocate page directory. */
211   t->pagedir = pagedir_create ();
212   if (t->pagedir == NULL)
213     LOAD_ERROR (("page directory allocation failed"));
214
215   /* Open executable file. */
216   file = filesys_open (filename);
217   if (file == NULL)
218     LOAD_ERROR (("open failed"));
219
220   /* Read and verify executable header. */
221   if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr) 
222     LOAD_ERROR (("error reading executable header"));
223   if (memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7) != 0)
224     LOAD_ERROR (("file is not ELF"));
225   if (ehdr.e_type != 2)
226     LOAD_ERROR (("ELF file is not an executable"));
227   if (ehdr.e_machine != 3)
228     LOAD_ERROR (("ELF executable is not x86"));
229   if (ehdr.e_version != 1)
230     LOAD_ERROR (("ELF executable has unknown version %d",
231                  (int) ehdr.e_version));
232   if (ehdr.e_phentsize != sizeof (struct Elf32_Phdr))
233     LOAD_ERROR (("bad ELF program header size"));
234   if (ehdr.e_phnum > 1024)
235     LOAD_ERROR (("too many ELF program headers"));
236
237   /* Read program headers. */
238   file_ofs = ehdr.e_phoff;
239   for (i = 0; i < ehdr.e_phnum; i++) 
240     {
241       struct Elf32_Phdr phdr;
242
243       if (file_ofs < 0 || file_ofs > file_length (file))
244         LOAD_ERROR (("bad file offset %ld", (long) file_ofs));
245       file_seek (file, file_ofs);
246
247       if (file_read (file, &phdr, sizeof phdr) != sizeof phdr)
248         LOAD_ERROR (("error reading program header"));
249       file_ofs += sizeof phdr;
250       switch (phdr.p_type) 
251         {
252         case PT_NULL:
253         case PT_NOTE:
254         case PT_PHDR:
255         case PT_STACK:
256           /* Ignore this segment. */
257           break;
258         case PT_DYNAMIC:
259         case PT_INTERP:
260         case PT_SHLIB:
261           /* Reject the executable. */
262           LOAD_ERROR (("unsupported ELF segment type %d\n", phdr.p_type));
263           break;
264         default:
265           printf ("unknown ELF segment type %08x\n", phdr.p_type);
266           break;
267         case PT_LOAD:
268           if (!load_segment (file, &phdr))
269             goto done;
270           break;
271         }
272     }
273
274   /* Set up stack. */
275   if (!setup_stack (esp))
276     goto done;
277
278   /* Start address. */
279   *eip = (void (*) (void)) ehdr.e_entry;
280
281   success = true;
282
283  done:
284   /* We arrive here whether the load is successful or not. */
285   file_close (file);
286   return success;
287 }
288 \f
289 /* load() helpers. */
290
291 static bool install_page (void *upage, void *kpage);
292
293 /* Loads the segment described by PHDR from FILE into user
294    address space.  Return true if successful, false otherwise. */
295 static bool
296 load_segment (struct file *file, const struct Elf32_Phdr *phdr) 
297 {
298   void *start, *end;  /* Page-rounded segment start and end. */
299   uint8_t *upage;     /* Iterator from start to end. */
300   off_t filesz_left;  /* Bytes left of file data (as opposed to
301                          zero-initialized bytes). */
302
303   /* Is this a read-only segment?  Not currently used, so it's
304      commented out.  You'll want to use it when implementing VM
305      to decide whether to page the segment from its executable or
306      from swap. */
307   //bool read_only = (phdr->p_flags & PF_W) == 0;
308
309   ASSERT (file != NULL);
310   ASSERT (phdr != NULL);
311   ASSERT (phdr->p_type == PT_LOAD);
312
313   /* [ELF1] 2-2 says that p_offset and p_vaddr must be congruent
314      modulo PGSIZE. */
315   if (phdr->p_offset % PGSIZE != phdr->p_vaddr % PGSIZE) 
316     {
317       printf ("%#08"PE32Ox" and %#08"PE32Ax" not congruent modulo %#x\n",
318               phdr->p_offset, phdr->p_vaddr, (unsigned) PGSIZE);
319       return false; 
320     }
321
322   /* p_offset must point within file. */
323   if (phdr->p_offset > (Elf32_Off) file_length (file)) 
324     {
325       printf ("bad p_offset %"PE32Ox, phdr->p_offset);
326       return false;
327     }
328
329   /* [ELF1] 2-3 says that p_memsz must be at least as big as
330      p_filesz. */
331   if (phdr->p_memsz < phdr->p_filesz) 
332     {
333       printf ("p_memsz (%08"PE32Wx") < p_filesz (%08"PE32Wx")\n",
334               phdr->p_memsz, phdr->p_filesz);
335       return false; 
336     }
337
338   /* Validate virtual memory region to be mapped.
339      The region must both start and end within the user address
340      space range starting at 0 and ending at PHYS_BASE (typically
341      3 GB == 0xc0000000). */
342   start = pg_round_down ((void *) phdr->p_vaddr);
343   end = pg_round_up ((void *) (phdr->p_vaddr + phdr->p_memsz));
344   if (start >= PHYS_BASE || end >= PHYS_BASE || end < start) 
345     {
346       printf ("bad virtual region %08lx...%08lx\n",
347               (unsigned long) start, (unsigned long) end);
348       return false; 
349     }
350
351   /* Load the segment page-by-page into memory. */
352   filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
353   file_seek (file, ROUND_DOWN (phdr->p_offset, PGSIZE));
354   for (upage = start; upage < (uint8_t *) end; upage += PGSIZE) 
355     {
356       /* We want to read min(PGSIZE, filesz_left) bytes from the
357          file into the page and zero the rest. */
358       size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
359       size_t zero_bytes = PGSIZE - read_bytes;
360       uint8_t *kpage = palloc_get_page (PAL_USER);
361       if (kpage == NULL)
362         return false;
363
364       /* Do the reading and zeroing. */
365       if (file_read (file, kpage, read_bytes) != (int) read_bytes) 
366         {
367           palloc_free_page (kpage);
368           return false; 
369         }
370       memset (kpage + read_bytes, 0, zero_bytes);
371       filesz_left -= read_bytes;
372
373       /* Add the page to the process's address space. */
374       if (!install_page (upage, kpage)) 
375         {
376           palloc_free_page (kpage);
377           return false; 
378         }
379     }
380
381   return true;
382 }
383
384 /* Create a minimal stack by mapping a zeroed page at the top of
385    user virtual memory. */
386 static bool
387 setup_stack (void **esp) 
388 {
389   uint8_t *kpage;
390   bool success = false;
391
392   kpage = palloc_get_page (PAL_USER | PAL_ZERO);
393   if (kpage != NULL) 
394     {
395       success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
396       if (success)
397         *esp = PHYS_BASE;
398       else
399         palloc_free_page (kpage);
400     }
401   else
402     printf ("failed to allocate process stack\n");
403
404   return success;
405 }
406
407 /* Adds a mapping from user virtual address UPAGE to kernel
408    virtual address KPAGE to the page table.  Fails if UPAGE is
409    already mapped or if memory allocation fails. */
410 static bool
411 install_page (void *upage, void *kpage)
412 {
413   struct thread *t = thread_current ();
414
415   /* Verify that there's not already a page at that virtual
416      address, then map our page there. */
417   return (pagedir_get_page (t->pagedir, upage) == NULL
418           && pagedir_set_page (t->pagedir, upage, kpage, true));
419 }