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