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_page (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_page (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_);
62 if_.eflags = FLAG_IF | FLAG_MBS;
64 success = load (filename, &if_.eip, &if_.esp);
66 /* If load failed, quit. */
67 palloc_free_page (filename);
71 /* Switch page tables. */
74 /* Start the user process by simulating a return from an
75 interrupt, implemented by intr_exit (in
76 threads/intr-stubs.S). 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
80 asm ("mov %%esp, %0; jmp intr_exit" :: "g" (&if_));
84 /* Free the current process's resources. */
88 struct thread *cur = thread_current ();
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
100 pagedir_activate (NULL);
101 pagedir_destroy (pd);
105 /* Sets up the CPU for running user code in the current
108 process_activate (void)
110 struct thread *t = thread_current ();
112 /* Activate thread's page tables. */
113 pagedir_activate (t->pagedir);
115 /* Set thread's kernel stack for use in processing
117 tss_set_esp0 ((uint8_t *) t + PGSIZE);
120 /* We load ELF binaries. The following definitions are taken
121 from the ELF specification, [ELF1], more-or-less verbatim. */
123 /* ELF types. See [ELF1] 1-2. */
124 typedef uint32_t Elf32_Word, Elf32_Addr, Elf32_Off;
125 typedef uint16_t Elf32_Half;
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. */
133 /* Executable header. See [ELF1] 1-4 to 1-8.
134 This appears at the very beginning of an ELF binary. */
137 unsigned char e_ident[16];
139 Elf32_Half e_machine;
140 Elf32_Word e_version;
146 Elf32_Half e_phentsize;
148 Elf32_Half e_shentsize;
150 Elf32_Half e_shstrndx;
153 /* Program header. See [ELF1] 2-2 to 2-4.
154 There are e_phnum of these, starting at file offset e_phoff
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. */
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. */
183 static bool load_segment (struct file *, const struct Elf32_Phdr *);
184 static bool setup_stack (void **esp);
186 /* Aborts loading an executable, with an error message. */
187 #define LOAD_ERROR(MSG) \
189 printf ("load: %s: ", filename); \
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. */
200 load (const char *filename, void (**eip) (void), void **esp)
202 struct thread *t = thread_current ();
203 struct Elf32_Ehdr ehdr;
204 struct file *file = NULL;
206 bool success = false;
209 /* Allocate page directory. */
210 t->pagedir = pagedir_create ();
211 if (t->pagedir == NULL)
212 LOAD_ERROR (("page directory allocation failed"));
214 /* Open executable file. */
215 file = filesys_open (filename);
217 LOAD_ERROR (("open failed"));
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"));
236 /* Read program headers. */
237 file_ofs = ehdr.e_phoff;
238 for (i = 0; i < ehdr.e_phnum; i++)
240 struct Elf32_Phdr phdr;
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);
246 if (file_read (file, &phdr, sizeof phdr) != sizeof phdr)
247 LOAD_ERROR (("error reading program header"));
248 file_ofs += sizeof phdr;
255 /* Ignore this segment. */
260 /* Reject the executable. */
261 LOAD_ERROR (("unsupported ELF segment type %d\n", phdr.p_type));
264 printf ("unknown ELF segment type %08x\n", phdr.p_type);
267 if (!load_segment (file, &phdr))
274 if (!setup_stack (esp))
278 *eip = (void (*) (void)) ehdr.e_entry;
283 /* We arrive here whether the load is successful or not. */
288 /* load() helpers. */
290 static bool install_page (void *upage, void *kpage);
292 /* Loads the segment described by PHDR from FILE into user
293 address space. Return true if successful, false otherwise. */
295 load_segment (struct file *file, const struct Elf32_Phdr *phdr)
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). */
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
306 //bool read_only = (phdr->p_flags & PF_W) == 0;
308 ASSERT (file != NULL);
309 ASSERT (phdr != NULL);
310 ASSERT (phdr->p_type == PT_LOAD);
312 /* [ELF1] 2-2 says that p_offset and p_vaddr must be congruent
314 if (phdr->p_offset % PGSIZE != phdr->p_vaddr % PGSIZE)
316 printf ("%#08"PE32Ox" and %#08"PE32Ax" not congruent modulo %#x\n",
317 phdr->p_offset, phdr->p_vaddr, (unsigned) PGSIZE);
321 /* p_offset must point within file. */
322 if (phdr->p_offset > (Elf32_Off) file_length (file))
324 printf ("bad p_offset %"PE32Ox, phdr->p_offset);
328 /* [ELF1] 2-3 says that p_memsz must be at least as big as
330 if (phdr->p_memsz < phdr->p_filesz)
332 printf ("p_memsz (%08"PE32Wx") < p_filesz (%08"PE32Wx")\n",
333 phdr->p_memsz, phdr->p_filesz);
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)
345 printf ("bad virtual region %08lx...%08lx\n",
346 (unsigned long) start, (unsigned long) end);
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)
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);
363 /* Do the reading and zeroing. */
364 if (file_read (file, kpage, read_bytes) != (int) read_bytes)
366 palloc_free_page (kpage);
369 memset (kpage + read_bytes, 0, zero_bytes);
370 filesz_left -= read_bytes;
372 /* Add the page to the process's address space. */
373 if (!install_page (upage, kpage))
375 palloc_free_page (kpage);
383 /* Create a minimal stack by mapping a zeroed page at the top of
384 user virtual memory. */
386 setup_stack (void **esp)
389 bool success = false;
391 kpage = palloc_get_page (PAL_USER | PAL_ZERO);
394 success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
398 palloc_free_page (kpage);
401 printf ("failed to allocate process stack\n");
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. */
410 install_page (void *upage, void *kpage)
412 struct thread *t = thread_current ();
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));