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 %%esp, %0; jmp intr_exit" :: "g" (&if_));
82 /* Free the current process's resources. */
86 struct thread *cur = thread_current ();
89 /* Destroy the current process's page directory and switch back
90 to the kernel-only page directory. We have to set
91 cur->pagedir to NULL before switching page directories, or a
92 timer interrupt might switch back to the process page
98 pagedir_activate (NULL);
103 /* Sets up the CPU for running user code in the current
106 process_activate (void)
108 struct thread *t = thread_current ();
110 /* Activate thread's page tables. */
111 pagedir_activate (t->pagedir);
113 /* Set thread's kernel stack for use in processing
115 tss_set_esp0 ((uint8_t *) t + PGSIZE);
118 /* We load ELF binaries. The following definitions are taken
119 from the ELF specification, [ELF1], more-or-less verbatim. */
121 /* ELF types. See [ELF1] 1-2. */
122 typedef uint32_t Elf32_Word, Elf32_Addr, Elf32_Off;
123 typedef uint16_t Elf32_Half;
125 /* For use with ELF types in printf(). */
126 #define PE32Wx PRIx32 /* Print Elf32_Word in hexadecimal. */
127 #define PE32Ax PRIx32 /* Print Elf32_Addr in hexadecimal. */
128 #define PE32Ox PRIx32 /* Print Elf32_Off in hexadecimal. */
129 #define PE32Hx PRIx16 /* Print Elf32_Half in hexadecimal. */
131 /* Executable header. See [ELF1] 1-4 to 1-8.
132 This appears at the very beginning of an ELF binary. */
135 unsigned char e_ident[16];
137 Elf32_Half e_machine;
138 Elf32_Word e_version;
144 Elf32_Half e_phentsize;
146 Elf32_Half e_shentsize;
148 Elf32_Half e_shstrndx;
151 /* Program header. See [ELF1] 2-2 to 2-4.
152 There are e_phnum of these, starting at file offset e_phoff
166 /* Values for p_type. See [ELF1] 2-3. */
167 #define PT_NULL 0 /* Ignore. */
168 #define PT_LOAD 1 /* Loadable segment. */
169 #define PT_DYNAMIC 2 /* Dynamic linking info. */
170 #define PT_INTERP 3 /* Name of dynamic loader. */
171 #define PT_NOTE 4 /* Auxiliary info. */
172 #define PT_SHLIB 5 /* Reserved. */
173 #define PT_PHDR 6 /* Program header table. */
174 #define PT_STACK 0x6474e551 /* Stack segment. */
176 /* Flags for p_flags. See [ELF3] 2-3 and 2-4. */
177 #define PF_X 1 /* Executable. */
178 #define PF_W 2 /* Writable. */
179 #define PF_R 4 /* Readable. */
181 static bool load_segment (struct file *, const struct Elf32_Phdr *);
182 static bool setup_stack (void **esp);
184 /* Aborts loading an executable, with an error message. */
185 #define LOAD_ERROR(MSG) \
187 printf ("load: %s: ", filename); \
193 /* Loads an ELF executable from FILENAME into the current thread.
194 Stores the executable's entry point into *EIP
195 and its initial stack pointer into *ESP.
196 Returns true if successful, false otherwise. */
198 load (const char *filename, void (**eip) (void), void **esp)
200 struct thread *t = thread_current ();
201 struct Elf32_Ehdr ehdr;
202 struct file *file = NULL;
204 bool success = false;
207 /* Allocate page directory. */
208 t->pagedir = pagedir_create ();
209 if (t->pagedir == NULL)
210 LOAD_ERROR (("page directory allocation failed"));
212 /* Open executable file. */
213 file = filesys_open (filename);
215 LOAD_ERROR (("open failed"));
217 /* Read and verify executable header. */
218 if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr)
219 LOAD_ERROR (("error reading executable header"));
220 if (memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7) != 0)
221 LOAD_ERROR (("file is not ELF"));
222 if (ehdr.e_type != 2)
223 LOAD_ERROR (("ELF file is not an executable"));
224 if (ehdr.e_machine != 3)
225 LOAD_ERROR (("ELF executable is not x86"));
226 if (ehdr.e_version != 1)
227 LOAD_ERROR (("ELF executable has unknown version %d",
228 (int) ehdr.e_version));
229 if (ehdr.e_phentsize != sizeof (struct Elf32_Phdr))
230 LOAD_ERROR (("bad ELF program header size"));
231 if (ehdr.e_phnum > 1024)
232 LOAD_ERROR (("too many ELF program headers"));
234 /* Read program headers. */
235 file_ofs = ehdr.e_phoff;
236 for (i = 0; i < ehdr.e_phnum; i++)
238 struct Elf32_Phdr phdr;
240 if (file_ofs < 0 || file_ofs > file_length (file))
241 LOAD_ERROR (("bad file offset %ld", (long) file_ofs));
242 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 /* p_offset must point within file. */
320 if (phdr->p_offset > (Elf32_Off) file_length (file))
322 printf ("bad p_offset %"PE32Ox, phdr->p_offset);
326 /* [ELF1] 2-3 says that p_memsz must be at least as big as
328 if (phdr->p_memsz < phdr->p_filesz)
330 printf ("p_memsz (%08"PE32Wx") < p_filesz (%08"PE32Wx")\n",
331 phdr->p_memsz, phdr->p_filesz);
335 /* Validate virtual memory region to be mapped.
336 The region must both start and end within the user address
337 space range starting at 0 and ending at PHYS_BASE (typically
338 3 GB == 0xc0000000). */
339 start = pg_round_down ((void *) phdr->p_vaddr);
340 end = pg_round_up ((void *) (phdr->p_vaddr + phdr->p_memsz));
341 if (start >= PHYS_BASE || end >= PHYS_BASE || end < start)
343 printf ("bad virtual region %08lx...%08lx\n",
344 (unsigned long) start, (unsigned long) end);
348 /* Load the segment page-by-page into memory. */
349 filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
350 file_seek (file, ROUND_DOWN (phdr->p_offset, PGSIZE));
351 for (upage = start; upage < (uint8_t *) end; upage += PGSIZE)
353 /* We want to read min(PGSIZE, filesz_left) bytes from the
354 file into the page and zero the rest. */
355 size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
356 size_t zero_bytes = PGSIZE - read_bytes;
357 uint8_t *kpage = palloc_get_page (PAL_USER);
361 /* Do the reading and zeroing. */
362 if (file_read (file, kpage, read_bytes) != (int) read_bytes)
364 palloc_free_page (kpage);
367 memset (kpage + read_bytes, 0, zero_bytes);
368 filesz_left -= read_bytes;
370 /* Add the page to the process's address space. */
371 if (!install_page (upage, kpage))
373 palloc_free_page (kpage);
381 /* Create a minimal stack by mapping a zeroed page at the top of
382 user virtual memory. */
384 setup_stack (void **esp)
387 bool success = false;
389 kpage = palloc_get_page (PAL_USER | PAL_ZERO);
392 success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
396 palloc_free_page (kpage);
399 printf ("failed to allocate process stack\n");
404 /* Adds a mapping from user virtual address UPAGE to kernel
405 virtual address KPAGE to the page table. Fails if UPAGE is
406 already mapped or if memory allocation fails. */
408 install_page (void *upage, void *kpage)
410 struct thread *t = thread_current ();
412 /* Verify that there's not already a page at that virtual
413 address, then map our page there. */
414 return (pagedir_get_page (t->pagedir, upage) == NULL
415 && pagedir_set_page (t->pagedir, upage, kpage, true));