Rewrite page allocator to support multi-page allocations.
[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 hasunknown 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       file_seek (file, file_ofs);
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   /* [ELF1] 2-3 says that p_memsz must be at least as big as
320      p_filesz. */
321   if (phdr->p_memsz < phdr->p_filesz) 
322     {
323       printf ("p_memsz (%08"PE32Wx") < p_filesz (%08"PE32Wx")\n",
324               phdr->p_memsz, phdr->p_filesz);
325       return false; 
326     }
327
328   /* Validate virtual memory region to be mapped.
329      The region must both start and end within the user address
330      space range starting at 0 and ending at PHYS_BASE (typically
331      3 GB == 0xc0000000). */
332   start = pg_round_down ((void *) phdr->p_vaddr);
333   end = pg_round_up ((void *) (phdr->p_vaddr + phdr->p_memsz));
334   if (start >= PHYS_BASE || end >= PHYS_BASE || end < start) 
335     {
336       printf ("bad virtual region %08lx...%08lx\n",
337               (unsigned long) start, (unsigned long) end);
338       return false; 
339     }
340
341   /* Load the segment page-by-page into memory. */
342   filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
343   file_seek (file, ROUND_DOWN (phdr->p_offset, PGSIZE));
344   for (upage = start; upage < (uint8_t *) end; upage += PGSIZE) 
345     {
346       /* We want to read min(PGSIZE, filesz_left) bytes from the
347          file into the page and zero the rest. */
348       size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
349       size_t zero_bytes = PGSIZE - read_bytes;
350       uint8_t *kpage = palloc_get_page (PAL_USER);
351       if (kpage == NULL)
352         return false;
353
354       /* Do the reading and zeroing. */
355       if (file_read (file, kpage, read_bytes) != (int) read_bytes) 
356         {
357           palloc_free_page (kpage);
358           return false; 
359         }
360       memset (kpage + read_bytes, 0, zero_bytes);
361       filesz_left -= read_bytes;
362
363       /* Add the page to the process's address space. */
364       if (!install_page (upage, kpage)) 
365         {
366           palloc_free_page (kpage);
367           return false; 
368         }
369     }
370
371   return true;
372 }
373
374 /* Create a minimal stack by mapping a zeroed page at the top of
375    user virtual memory. */
376 static bool
377 setup_stack (void **esp) 
378 {
379   uint8_t *kpage;
380   bool success = false;
381
382   kpage = palloc_get_page (PAL_USER | PAL_ZERO);
383   if (kpage != NULL) 
384     {
385       success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
386       if (success)
387         *esp = PHYS_BASE;
388       else
389         palloc_free_page (kpage);
390     }
391   else
392     printf ("failed to allocate process stack\n");
393
394   return success;
395 }
396
397 /* Adds a mapping from user virtual address UPAGE to kernel
398    virtual address KPAGE to the page table.  Fails if UPAGE is
399    already mapped or if memory allocation fails. */
400 static bool
401 install_page (void *upage, void *kpage)
402 {
403   struct thread *t = thread_current ();
404
405   /* Verify that there's not already a page at that virtual
406      address, then map our page there. */
407   return (pagedir_get_page (t->pagedir, upage) == NULL
408           && pagedir_set_page (t->pagedir, upage, kpage, true));
409 }