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 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"));
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 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;
253 /* Ignore this segment. */
258 /* Reject the executable. */
259 LOAD_ERROR (("unsupported ELF segment type %d\n", phdr.p_type));
262 printf ("unknown ELF segment type %08x\n", phdr.p_type);
265 if (!load_segment (file, &phdr))
272 if (!setup_stack (esp))
276 *eip = (void (*) (void)) ehdr.e_entry;
281 /* We arrive here whether the load is successful or not. */
286 /* load() helpers. */
288 static bool install_page (void *upage, void *kpage);
290 /* Loads the segment described by PHDR from FILE into user
291 address space. Return true if successful, false otherwise. */
293 load_segment (struct file *file, const struct Elf32_Phdr *phdr)
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). */
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
304 //bool read_only = (phdr->p_flags & PF_W) == 0;
306 ASSERT (file != NULL);
307 ASSERT (phdr != NULL);
308 ASSERT (phdr->p_type == PT_LOAD);
310 /* [ELF1] 2-2 says that p_offset and p_vaddr must be congruent
312 if (phdr->p_offset % PGSIZE != phdr->p_vaddr % PGSIZE)
314 printf ("%#08"PE32Ox" and %#08"PE32Ax" not congruent modulo %#x\n",
315 phdr->p_offset, phdr->p_vaddr, (unsigned) PGSIZE);
319 /* [ELF1] 2-3 says that p_memsz must be at least as big as
321 if (phdr->p_memsz < phdr->p_filesz)
323 printf ("p_memsz (%08"PE32Wx") < p_filesz (%08"PE32Wx")\n",
324 phdr->p_memsz, phdr->p_filesz);
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)
336 printf ("bad virtual region %08lx...%08lx\n",
337 (unsigned long) start, (unsigned long) end);
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)
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);
354 /* Do the reading and zeroing. */
355 if (file_read (file, kpage, read_bytes) != (int) read_bytes)
357 palloc_free_page (kpage);
360 memset (kpage + read_bytes, 0, zero_bytes);
361 filesz_left -= read_bytes;
363 /* Add the page to the process's address space. */
364 if (!install_page (upage, kpage))
366 palloc_free_page (kpage);
374 /* Create a minimal stack by mapping a zeroed page at the top of
375 user virtual memory. */
377 setup_stack (void **esp)
380 bool success = false;
382 kpage = palloc_get_page (PAL_USER | PAL_ZERO);
385 success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
389 palloc_free_page (kpage);
392 printf ("failed to allocate process stack\n");
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. */
401 install_page (void *upage, void *kpage)
403 struct thread *t = thread_current ();
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));