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_);
60 if_.eflags = FLAG_IF | FLAG_MBS;
62 success = load (filename, &if_.eip, &if_.esp);
64 /* If load failed, quit. */
65 palloc_free_page (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 /* Free the current process's resources. */
89 struct thread *cur = thread_current ();
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
101 pagedir_activate (NULL);
102 pagedir_destroy (pd);
106 /* Sets up the CPU for running user code in the current
109 process_activate (void)
111 struct thread *t = thread_current ();
113 /* Activate thread's page tables. */
114 pagedir_activate (t->pagedir);
116 /* Set thread's kernel stack for use in processing
118 tss_set_esp0 ((uint8_t *) t + PGSIZE);
121 /* We load ELF binaries. The following definitions are taken
122 from the ELF specification, [ELF1], more-or-less verbatim. */
124 /* ELF types. See [ELF1] 1-2. */
125 typedef uint32_t Elf32_Word, Elf32_Addr, Elf32_Off;
126 typedef uint16_t Elf32_Half;
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. */
134 /* Executable header. See [ELF1] 1-4 to 1-8.
135 This appears at the very beginning of an ELF binary. */
138 unsigned char e_ident[16];
140 Elf32_Half e_machine;
141 Elf32_Word e_version;
147 Elf32_Half e_phentsize;
149 Elf32_Half e_shentsize;
151 Elf32_Half e_shstrndx;
154 /* Program header. See [ELF1] 2-2 to 2-4.
155 There are e_phnum of these, starting at file offset e_phoff
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. */
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. */
184 static bool load_segment (struct file *, const struct Elf32_Phdr *);
185 static bool setup_stack (void **esp);
187 /* Aborts loading an executable, with an error message. */
188 #define LOAD_ERROR(MSG) \
190 printf ("load: %s: ", filename); \
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. */
201 load (const char *filename, void (**eip) (void), void **esp)
203 struct thread *t = thread_current ();
204 struct Elf32_Ehdr ehdr;
205 struct file *file = NULL;
207 bool success = false;
210 /* Allocate page directory. */
211 t->pagedir = pagedir_create ();
212 if (t->pagedir == NULL)
213 LOAD_ERROR (("page directory allocation failed"));
215 /* Open executable file. */
216 file = filesys_open (filename);
218 LOAD_ERROR (("open failed"));
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 has unknown 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"));
237 /* Read program headers. */
238 file_ofs = ehdr.e_phoff;
239 for (i = 0; i < ehdr.e_phnum; i++)
241 struct Elf32_Phdr phdr;
243 if (file_ofs < 0 || file_ofs > file_length (file))
244 LOAD_ERROR (("bad file offset %ld", (long) file_ofs));
245 file_seek (file, file_ofs);
247 if (file_read (file, &phdr, sizeof phdr) != sizeof phdr)
248 LOAD_ERROR (("error reading program header"));
249 file_ofs += sizeof phdr;
256 /* Ignore this segment. */
261 /* Reject the executable. */
262 LOAD_ERROR (("unsupported ELF segment type %d\n", phdr.p_type));
265 printf ("unknown ELF segment type %08x\n", phdr.p_type);
268 if (!load_segment (file, &phdr))
275 if (!setup_stack (esp))
279 *eip = (void (*) (void)) ehdr.e_entry;
284 /* We arrive here whether the load is successful or not. */
289 /* load() helpers. */
291 static bool install_page (void *upage, void *kpage);
293 /* Loads the segment described by PHDR from FILE into user
294 address space. Return true if successful, false otherwise. */
296 load_segment (struct file *file, const struct Elf32_Phdr *phdr)
298 void *start, *end; /* Page-rounded segment start and end. */
299 uint8_t *upage; /* Iterator from start to end. */
300 off_t filesz_left; /* Bytes left of file data (as opposed to
301 zero-initialized bytes). */
303 /* Is this a read-only segment? Not currently used, so it's
304 commented out. You'll want to use it when implementing VM
305 to decide whether to page the segment from its executable or
307 //bool read_only = (phdr->p_flags & PF_W) == 0;
309 ASSERT (file != NULL);
310 ASSERT (phdr != NULL);
311 ASSERT (phdr->p_type == PT_LOAD);
313 /* [ELF1] 2-2 says that p_offset and p_vaddr must be congruent
315 if (phdr->p_offset % PGSIZE != phdr->p_vaddr % PGSIZE)
317 printf ("%#08"PE32Ox" and %#08"PE32Ax" not congruent modulo %#x\n",
318 phdr->p_offset, phdr->p_vaddr, (unsigned) PGSIZE);
322 /* p_offset must point within file. */
323 if (phdr->p_offset > (Elf32_Off) file_length (file))
325 printf ("bad p_offset %"PE32Ox, phdr->p_offset);
329 /* [ELF1] 2-3 says that p_memsz must be at least as big as
331 if (phdr->p_memsz < phdr->p_filesz)
333 printf ("p_memsz (%08"PE32Wx") < p_filesz (%08"PE32Wx")\n",
334 phdr->p_memsz, phdr->p_filesz);
338 /* Validate virtual memory region to be mapped.
339 The region must both start and end within the user address
340 space range starting at 0 and ending at PHYS_BASE (typically
341 3 GB == 0xc0000000). */
342 start = pg_round_down ((void *) phdr->p_vaddr);
343 end = pg_round_up ((void *) (phdr->p_vaddr + phdr->p_memsz));
344 if (start >= PHYS_BASE || end >= PHYS_BASE || end < start)
346 printf ("bad virtual region %08lx...%08lx\n",
347 (unsigned long) start, (unsigned long) end);
351 /* Load the segment page-by-page into memory. */
352 filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
353 file_seek (file, ROUND_DOWN (phdr->p_offset, PGSIZE));
354 for (upage = start; upage < (uint8_t *) end; upage += PGSIZE)
356 /* We want to read min(PGSIZE, filesz_left) bytes from the
357 file into the page and zero the rest. */
358 size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
359 size_t zero_bytes = PGSIZE - read_bytes;
360 uint8_t *kpage = palloc_get_page (PAL_USER);
364 /* Do the reading and zeroing. */
365 if (file_read (file, kpage, read_bytes) != (int) read_bytes)
367 palloc_free_page (kpage);
370 memset (kpage + read_bytes, 0, zero_bytes);
371 filesz_left -= read_bytes;
373 /* Add the page to the process's address space. */
374 if (!install_page (upage, kpage))
376 palloc_free_page (kpage);
384 /* Create a minimal stack by mapping a zeroed page at the top of
385 user virtual memory. */
387 setup_stack (void **esp)
390 bool success = false;
392 kpage = palloc_get_page (PAL_USER | PAL_ZERO);
395 success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
399 palloc_free_page (kpage);
402 printf ("failed to allocate process stack\n");
407 /* Adds a mapping from user virtual address UPAGE to kernel
408 virtual address KPAGE to the page table. Fails if UPAGE is
409 already mapped or if memory allocation fails. */
411 install_page (void *upage, void *kpage)
413 struct thread *t = thread_current ();
415 /* Verify that there's not already a page at that virtual
416 address, then map our page there. */
417 return (pagedir_get_page (t->pagedir, upage) == NULL
418 && pagedir_set_page (t->pagedir, upage, kpage, true));