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 (and may even exit)
25 before process_execute() returns. Returns the new process's
26 thread id, or TID_ERROR if the thread cannot be created. */
28 process_execute (const char *filename)
33 /* Make a copy of FILENAME.
34 Otherwise there's a race between the caller and load(). */
35 fn_copy = palloc_get_page (0);
38 strlcpy (fn_copy, filename, PGSIZE);
40 /* Create a new thread to execute FILENAME. */
41 tid = thread_create (filename, PRI_DEFAULT, execute_thread, fn_copy);
43 palloc_free_page (fn_copy);
47 /* A thread function that loads a user process and starts it
50 execute_thread (void *filename_)
52 char *filename = filename_;
53 struct intr_frame if_;
56 /* Initialize interrupt frame and load executable. */
57 memset (&if_, 0, sizeof if_);
58 if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG;
60 if_.eflags = FLAG_IF | FLAG_MBS;
61 success = load (filename, &if_.eip, &if_.esp);
63 /* If load failed, quit. */
64 palloc_free_page (filename);
68 /* Start the user process by simulating a return from an
69 interrupt, implemented by intr_exit (in
70 threads/intr-stubs.S). Because intr_exit takes all of its
71 arguments on the stack in the form of a `struct intr_frame',
72 we just point the stack pointer (%esp) to our stack frame
74 asm ("mov %%esp, %0; jmp intr_exit" :: "g" (&if_));
78 /* Waits for thread TID to die and returns its exit status. If
79 it was terminated by the kernel (i.e. killed due to an
80 exception), returns -1. If TID is invalid or if it was not a
81 child of the calling process, or if process_wait() has already
82 been successfully called for the given TID, returns -1
83 immediately, without waiting.
85 This function will be implemented in problem 2-2. For now, it
88 process_wait (tid_t child_tid UNUSED)
93 /* Free the current process's resources. */
97 struct thread *cur = thread_current ();
100 /* Destroy the current process's page directory and switch back
101 to the kernel-only page directory. */
105 /* Correct ordering here is crucial. We must set
106 cur->pagedir to NULL before switching page directories,
107 so that a timer interrupt can't switch back to the
108 process page directory. We must activate the base page
109 directory before destroying the process's page
110 directory, or our active page directory will be one
111 that's been freed (and cleared). */
113 pagedir_activate (NULL);
114 pagedir_destroy (pd);
118 /* Sets up the CPU for running user code in the current
121 process_activate (void)
123 struct thread *t = thread_current ();
125 /* Activate thread's page tables. */
126 pagedir_activate (t->pagedir);
128 /* Set thread's kernel stack for use in processing
130 tss_set_esp0 ((uint8_t *) t + PGSIZE);
133 /* We load ELF binaries. The following definitions are taken
134 from the ELF specification, [ELF1], more-or-less verbatim. */
136 /* ELF types. See [ELF1] 1-2. */
137 typedef uint32_t Elf32_Word, Elf32_Addr, Elf32_Off;
138 typedef uint16_t Elf32_Half;
140 /* For use with ELF types in printf(). */
141 #define PE32Wx PRIx32 /* Print Elf32_Word in hexadecimal. */
142 #define PE32Ax PRIx32 /* Print Elf32_Addr in hexadecimal. */
143 #define PE32Ox PRIx32 /* Print Elf32_Off in hexadecimal. */
144 #define PE32Hx PRIx16 /* Print Elf32_Half in hexadecimal. */
146 /* Executable header. See [ELF1] 1-4 to 1-8.
147 This appears at the very beginning of an ELF binary. */
150 unsigned char e_ident[16];
152 Elf32_Half e_machine;
153 Elf32_Word e_version;
159 Elf32_Half e_phentsize;
161 Elf32_Half e_shentsize;
163 Elf32_Half e_shstrndx;
166 /* Program header. See [ELF1] 2-2 to 2-4.
167 There are e_phnum of these, starting at file offset e_phoff
181 /* Values for p_type. See [ELF1] 2-3. */
182 #define PT_NULL 0 /* Ignore. */
183 #define PT_LOAD 1 /* Loadable segment. */
184 #define PT_DYNAMIC 2 /* Dynamic linking info. */
185 #define PT_INTERP 3 /* Name of dynamic loader. */
186 #define PT_NOTE 4 /* Auxiliary info. */
187 #define PT_SHLIB 5 /* Reserved. */
188 #define PT_PHDR 6 /* Program header table. */
189 #define PT_STACK 0x6474e551 /* Stack segment. */
191 /* Flags for p_flags. See [ELF3] 2-3 and 2-4. */
192 #define PF_X 1 /* Executable. */
193 #define PF_W 2 /* Writable. */
194 #define PF_R 4 /* Readable. */
196 static bool load_segment (struct file *, const struct Elf32_Phdr *);
197 static bool setup_stack (void **esp);
199 /* Loads an ELF executable from FILENAME into the current thread.
200 Stores the executable's entry point into *EIP
201 and its initial stack pointer into *ESP.
202 Returns true if successful, false otherwise. */
204 load (const char *filename, void (**eip) (void), void **esp)
206 struct thread *t = thread_current ();
207 struct Elf32_Ehdr ehdr;
208 struct file *file = NULL;
210 bool success = false;
213 /* Allocate and activate page directory. */
214 t->pagedir = pagedir_create ();
215 if (t->pagedir == NULL)
219 /* Open executable file. */
220 file = filesys_open (filename);
223 printf ("load: %s: open failed\n", filename);
227 /* Read and verify executable header. */
228 if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr
229 || memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7)
231 || ehdr.e_machine != 3
232 || ehdr.e_version != 1
233 || ehdr.e_phentsize != sizeof (struct Elf32_Phdr)
234 || ehdr.e_phnum > 1024)
236 printf ("load: %s: error loading executable\n", filename);
240 /* Read program headers. */
241 file_ofs = ehdr.e_phoff;
242 for (i = 0; i < ehdr.e_phnum; i++)
244 struct Elf32_Phdr phdr;
246 if (file_ofs < 0 || file_ofs > file_length (file))
248 file_seek (file, file_ofs);
250 if (file_read (file, &phdr, sizeof phdr) != sizeof phdr)
252 file_ofs += sizeof phdr;
260 /* Ignore this segment. */
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)
317 /* p_offset must point within file. */
318 if (phdr->p_offset > (Elf32_Off) file_length (file))
321 /* [ELF1] 2-3 says that p_memsz must be at least as big as
323 if (phdr->p_memsz < phdr->p_filesz)
326 /* Validate virtual memory region to be mapped.
327 The region must both start and end within the user address
328 space range. We don't allow mapping page 0.*/
329 start = pg_round_down ((void *) phdr->p_vaddr);
330 end = pg_round_up ((void *) (phdr->p_vaddr + phdr->p_memsz));
331 if (!is_user_vaddr (start) || !is_user_vaddr (end) || end < start
335 /* Load the segment page-by-page into memory. */
336 filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
337 file_seek (file, ROUND_DOWN (phdr->p_offset, PGSIZE));
338 for (upage = start; upage < (uint8_t *) end; upage += PGSIZE)
340 /* We want to read min(PGSIZE, filesz_left) bytes from the
341 file into the page and zero the rest. */
342 size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
343 size_t zero_bytes = PGSIZE - read_bytes;
344 uint8_t *kpage = palloc_get_page (PAL_USER);
348 /* Do the reading and zeroing. */
349 if (file_read (file, kpage, read_bytes) != (int) read_bytes)
351 palloc_free_page (kpage);
354 memset (kpage + read_bytes, 0, zero_bytes);
355 filesz_left -= read_bytes;
357 /* Add the page to the process's address space. */
358 if (!install_page (upage, kpage))
360 palloc_free_page (kpage);
368 /* Create a minimal stack by mapping a zeroed page at the top of
369 user virtual memory. */
371 setup_stack (void **esp)
374 bool success = false;
376 kpage = palloc_get_page (PAL_USER | PAL_ZERO);
379 success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
383 palloc_free_page (kpage);
388 /* Adds a mapping from user virtual address UPAGE to kernel
389 virtual address KPAGE to the page table. Fails if UPAGE is
390 already mapped or if memory allocation fails. */
392 install_page (void *upage, void *kpage)
394 struct thread *t = thread_current ();
396 /* Verify that there's not already a page at that virtual
397 address, then map our page there. */
398 return (pagedir_get_page (t->pagedir, upage) == NULL
399 && pagedir_set_page (t->pagedir, upage, kpage, true));