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