1 #include "userprog/process.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"
20 static thread_func execute_thread NO_RETURN;
21 static bool load (const char *cmdline, void (**eip) (void), void **esp);
23 /* Starts a new thread running a user program loaded from
24 FILENAME. The new thread may be scheduled before
25 process_execute() returns.*/
27 process_execute (const char *filename)
32 /* Make a copy of FILENAME.
33 Otherwise there's a race between the caller and load(). */
34 fn_copy = palloc_get (0);
37 strlcpy (fn_copy, filename, PGSIZE);
39 /* Create a new thread to execute FILENAME. */
40 tid = thread_create (filename, PRI_DEFAULT, execute_thread, fn_copy);
42 palloc_free (fn_copy);
46 /* A thread function that loads a user process and starts it
49 execute_thread (void *filename_)
51 char *filename = filename_;
52 struct intr_frame if_;
55 /* Initialize interrupt frame and load executable. */
56 memset (&if_, 0, sizeof if_);
60 if_.eflags = FLAG_IF | FLAG_MBS;
62 success = load (filename, &if_.eip, &if_.esp);
64 /* If load failed, quit. */
65 palloc_free (filename);
69 /* Switch page tables. */
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
78 asm ("mov %0, %%esp\n"
85 /* Destroys the user address space in T and frees all of its
88 process_destroy (struct thread *t)
90 ASSERT (t != thread_current ());
92 if (t->pagedir != NULL)
94 pagedir_destroy (t->pagedir);
99 /* Sets up the CPU for running user code in the current
102 process_activate (void)
104 struct thread *t = thread_current ();
106 /* Activate T's page tables. */
107 pagedir_activate (t->pagedir);
109 /* Set T's kernel stack for use in processing interrupts. */
110 tss_set_esp0 ((uint8_t *) t + PGSIZE);
113 /* We load ELF binaries. The following definitions are taken
114 from the ELF specification, [ELF1], more-or-less verbatim. */
116 /* ELF types. See [ELF1] 1-2. */
117 typedef uint32_t Elf32_Word, Elf32_Addr, Elf32_Off;
118 typedef uint16_t Elf32_Half;
120 /* For use with ELF types in printf(). */
121 #define PE32Wx PRIx32 /* Print Elf32_Word in hexadecimal. */
122 #define PE32Ax PRIx32 /* Print Elf32_Addr in hexadecimal. */
123 #define PE32Ox PRIx32 /* Print Elf32_Off in hexadecimal. */
124 #define PE32Hx PRIx16 /* Print Elf32_Half in hexadecimal. */
126 /* Executable header. See [ELF1] 1-4 to 1-8.
127 This appears at the very beginning of an ELF binary. */
130 unsigned char e_ident[16];
132 Elf32_Half e_machine;
133 Elf32_Word e_version;
139 Elf32_Half e_phentsize;
141 Elf32_Half e_shentsize;
143 Elf32_Half e_shstrndx;
146 /* Program header. See [ELF1] 2-2 to 2-4.
147 There are e_phnum of these, starting at file offset e_phoff
161 /* Values for p_type. See [ELF1] 2-3. */
162 #define PT_NULL 0 /* Ignore. */
163 #define PT_LOAD 1 /* Loadable segment. */
164 #define PT_DYNAMIC 2 /* Dynamic linking info. */
165 #define PT_INTERP 3 /* Name of dynamic loader. */
166 #define PT_NOTE 4 /* Auxiliary info. */
167 #define PT_SHLIB 5 /* Reserved. */
168 #define PT_PHDR 6 /* Program header table. */
169 #define PT_STACK 0x6474e551 /* Stack segment. */
171 /* Flags for p_flags. See [ELF3] 2-3 and 2-4. */
172 #define PF_X 1 /* Executable. */
173 #define PF_W 2 /* Writable. */
174 #define PF_R 4 /* Readable. */
176 static bool load_segment (struct file *, const struct Elf32_Phdr *);
177 static bool setup_stack (void **esp);
179 /* Aborts loading an executable, with an error message. */
180 #define LOAD_ERROR(MSG) \
182 printf ("load: %s: ", filename); \
188 /* Loads an ELF executable from FILENAME into the current thread.
189 Stores the executable's entry point into *EIP
190 and its initial stack pointer into *ESP.
191 Returns true if successful, false otherwise. */
193 load (const char *filename, void (**eip) (void), void **esp)
195 struct thread *t = thread_current ();
196 struct Elf32_Ehdr ehdr;
197 struct file *file = NULL;
199 bool success = false;
202 /* Allocate page directory. */
203 t->pagedir = pagedir_create ();
204 if (t->pagedir == NULL)
205 LOAD_ERROR (("page directory allocation failed"));
207 /* Open executable file. */
208 file = filesys_open (filename);
210 LOAD_ERROR (("open failed"));
212 /* Read and verify executable header. */
213 if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr)
214 LOAD_ERROR (("error reading executable header"));
215 if (memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7) != 0)
216 LOAD_ERROR (("file is not ELF"));
217 if (ehdr.e_type != 2)
218 LOAD_ERROR (("ELF file is not an executable"));
219 if (ehdr.e_machine != 3)
220 LOAD_ERROR (("ELF executable is not x86"));
221 if (ehdr.e_version != 1)
222 LOAD_ERROR (("ELF executable hasunknown version %d",
223 (int) ehdr.e_version));
224 if (ehdr.e_phentsize != sizeof (struct Elf32_Phdr))
225 LOAD_ERROR (("bad ELF program header size"));
226 if (ehdr.e_phnum > 1024)
227 LOAD_ERROR (("too many ELF program headers"));
229 /* Read program headers. */
230 file_ofs = ehdr.e_phoff;
231 for (i = 0; i < ehdr.e_phnum; i++)
233 struct Elf32_Phdr phdr;
235 file_seek (file, file_ofs);
236 if (file_read (file, &phdr, sizeof phdr) != sizeof phdr)
237 LOAD_ERROR (("error reading program header"));
238 file_ofs += sizeof phdr;
245 /* Ignore this segment. */
250 /* Reject the executable. */
251 LOAD_ERROR (("unsupported ELF segment type %d\n", phdr.p_type));
254 printf ("unknown ELF segment type %08x\n", phdr.p_type);
257 if (!load_segment (file, &phdr))
264 if (!setup_stack (esp))
268 *eip = (void (*) (void)) ehdr.e_entry;
273 /* We arrive here whether the load is successful or not. */
278 /* load() helpers. */
280 static bool install_page (void *upage, void *kpage);
282 /* Loads the segment described by PHDR from FILE into user
283 address space. Return true if successful, false otherwise. */
285 load_segment (struct file *file, const struct Elf32_Phdr *phdr)
287 void *start, *end; /* Page-rounded segment start and end. */
288 uint8_t *upage; /* Iterator from start to end. */
289 off_t filesz_left; /* Bytes left of file data (as opposed to
290 zero-initialized bytes). */
292 /* Is this a read-only segment? Not currently used, so it's
293 commented out. You'll want to use it when implementing VM
294 to decide whether to page the segment from its executable or
296 //bool read_only = (phdr->p_flags & PF_W) == 0;
298 ASSERT (file != NULL);
299 ASSERT (phdr != NULL);
300 ASSERT (phdr->p_type == PT_LOAD);
302 /* [ELF1] 2-2 says that p_offset and p_vaddr must be congruent
304 if (phdr->p_offset % PGSIZE != phdr->p_vaddr % PGSIZE)
306 printf ("%#08"PE32Ox" and %#08"PE32Ax" not congruent modulo %#x\n",
307 phdr->p_offset, phdr->p_vaddr, (unsigned) PGSIZE);
311 /* [ELF1] 2-3 says that p_memsz must be at least as big as
313 if (phdr->p_memsz < phdr->p_filesz)
315 printf ("p_memsz (%08"PE32Wx") < p_filesz (%08"PE32Wx")\n",
316 phdr->p_memsz, phdr->p_filesz);
320 /* Validate virtual memory region to be mapped.
321 The region must both start and end within the user address
322 space range starting at 0 and ending at PHYS_BASE (typically
323 3 GB == 0xc0000000). */
324 start = pg_round_down ((void *) phdr->p_vaddr);
325 end = pg_round_up ((void *) (phdr->p_vaddr + phdr->p_memsz));
326 if (start >= PHYS_BASE || end >= PHYS_BASE || end < start)
328 printf ("bad virtual region %08lx...%08lx\n",
329 (unsigned long) start, (unsigned long) end);
333 /* Load the segment page-by-page into memory. */
334 filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
335 file_seek (file, ROUND_DOWN (phdr->p_offset, PGSIZE));
336 for (upage = start; upage < (uint8_t *) end; upage += PGSIZE)
338 /* We want to read min(PGSIZE, filesz_left) bytes from the
339 file into the page and zero the rest. */
340 size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
341 size_t zero_bytes = PGSIZE - read_bytes;
342 uint8_t *kpage = palloc_get (PAL_USER);
346 /* Do the reading and zeroing. */
347 if (file_read (file, kpage, read_bytes) != (int) read_bytes)
352 memset (kpage + read_bytes, 0, zero_bytes);
353 filesz_left -= read_bytes;
355 /* Add the page to the process's address space. */
356 if (!install_page (upage, kpage))
366 /* Create a minimal stack by mapping a zeroed page at the top of
367 user virtual memory. */
369 setup_stack (void **esp)
372 bool success = false;
374 kpage = palloc_get (PAL_USER | PAL_ZERO);
377 success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
384 printf ("failed to allocate process stack\n");
389 /* Adds a mapping from user virtual address UPAGE to kernel
390 virtual address KPAGE to the page table. Fails if UPAGE is
391 already mapped or if memory allocation fails. */
393 install_page (void *upage, void *kpage)
395 struct thread *t = thread_current ();
397 /* Verify that there's not already a page at that virtual
398 address, then map our page there. */
399 return (pagedir_get_page (t->pagedir, upage) == NULL
400 && pagedir_set_page (t->pagedir, upage, kpage, true));