1 #include "userprog/addrspace.h"
7 #include "userprog/pagedir.h"
8 #include "userprog/tss.h"
9 #include "filesys/file.h"
10 #include "filesys/filesys.h"
11 #include "threads/init.h"
12 #include "threads/mmu.h"
13 #include "threads/palloc.h"
14 #include "threads/thread.h"
16 /* We load ELF binaries. The following definitions are taken
17 from the ELF specification, [ELF1], more-or-less verbatim. */
19 /* ELF types. See [ELF1] 1-2. */
20 typedef uint32_t Elf32_Word, Elf32_Addr, Elf32_Off;
21 typedef uint16_t Elf32_Half;
23 /* For use with ELF types in printf(). */
24 #define PE32Wx PRIx32 /* Print Elf32_Word in hexadecimal. */
25 #define PE32Ax PRIx32 /* Print Elf32_Addr in hexadecimal. */
26 #define PE32Ox PRIx32 /* Print Elf32_Off in hexadecimal. */
27 #define PE32Hx PRIx16 /* Print Elf32_Half in hexadecimal. */
29 /* Executable header. See [ELF1] 1-4 to 1-8.
30 This appears at the very beginning of an ELF binary. */
33 unsigned char e_ident[16];
42 Elf32_Half e_phentsize;
44 Elf32_Half e_shentsize;
46 Elf32_Half e_shstrndx;
49 /* Program header. See [ELF1] 2-2 to 2-4.
50 There are e_phnum of these, starting at file offset e_phoff
64 /* Values for p_type. See [ELF1] 2-3. */
65 #define PT_NULL 0 /* Ignore. */
66 #define PT_LOAD 1 /* Loadable segment. */
67 #define PT_DYNAMIC 2 /* Dynamic linking info. */
68 #define PT_INTERP 3 /* Name of dynamic loader. */
69 #define PT_NOTE 4 /* Auxiliary info. */
70 #define PT_SHLIB 5 /* Reserved. */
71 #define PT_PHDR 6 /* Program header table. */
72 #define PT_STACK 0x6474e551 /* Stack segment. */
74 /* Flags for p_flags. See [ELF3] 2-3 and 2-4. */
75 #define PF_X 1 /* Executable. */
76 #define PF_W 2 /* Writable. */
77 #define PF_R 4 /* Readable. */
79 static bool load_segment (struct thread *, struct file *,
80 const struct Elf32_Phdr *);
81 static bool setup_stack (struct thread *);
83 /* Aborts loading an executable, with an error message. */
84 #define LOAD_ERROR(MSG) \
86 printf ("addrspace_load: %s: ", filename); \
92 /* Loads an ELF executable from FILENAME into T,
93 and stores the executable's entry point into *START.
94 Returns true if successful, false otherwise. */
96 addrspace_load (struct thread *t, const char *filename, void (**start) (void))
98 struct Elf32_Ehdr ehdr;
99 struct file *file = NULL;
101 bool success = false;
104 /* Allocate page directory. */
105 t->pagedir = pagedir_create ();
106 if (t->pagedir == NULL)
107 LOAD_ERROR (("page directory allocation failed"));
109 /* Open executable file. */
110 file = filesys_open (filename);
112 LOAD_ERROR (("open failed"));
114 /* Read and verify executable header. */
115 if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr)
116 LOAD_ERROR (("error reading executable header"));
117 if (memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7) != 0)
118 LOAD_ERROR (("file is not ELF"));
119 if (ehdr.e_type != 2)
120 LOAD_ERROR (("ELF file is not an executable"));
121 if (ehdr.e_machine != 3)
122 LOAD_ERROR (("ELF executable is not x86"));
123 if (ehdr.e_version != 1)
124 LOAD_ERROR (("ELF executable hasunknown version %d",
125 (int) ehdr.e_version));
126 if (ehdr.e_phentsize != sizeof (struct Elf32_Phdr))
127 LOAD_ERROR (("bad ELF program header size"));
128 if (ehdr.e_phnum > 1024)
129 LOAD_ERROR (("too many ELF program headers"));
131 /* Read program headers. */
132 file_ofs = ehdr.e_phoff;
133 for (i = 0; i < ehdr.e_phnum; i++)
135 struct Elf32_Phdr phdr;
137 file_seek (file, file_ofs);
138 if (file_read (file, &phdr, sizeof phdr) != sizeof phdr)
139 LOAD_ERROR (("error reading program header"));
140 file_ofs += sizeof phdr;
147 /* Ignore this segment. */
152 /* Reject the executable. */
153 LOAD_ERROR (("unsupported ELF segment type %d\n", phdr.p_type));
156 printf ("unknown ELF segment type %08x\n", phdr.p_type);
159 if (!load_segment (t, file, &phdr))
166 if (!setup_stack (t))
170 *start = (void (*) (void)) ehdr.e_entry;
175 /* We arrive here whether the load is successful or not.
176 We can distinguish based on `success'. */
179 addrspace_destroy (t);
183 /* Destroys the user address space in T and frees all of its
186 addrspace_destroy (struct thread *t)
188 if (t->pagedir != NULL)
190 pagedir_destroy (t->pagedir);
195 /* Sets up the CPU for running user code in thread T, if any. */
197 addrspace_activate (struct thread *t)
201 /* Activate T's page tables. */
202 pagedir_activate (t->pagedir);
204 /* Set T's kernel stack for use in processing interrupts. */
205 tss_set_esp0 ((uint8_t *) t + PGSIZE);
208 /* addrspace_load() helpers. */
210 static bool install_page (struct thread *, void *upage, void *kpage);
212 /* Loads the segment described by PHDR from FILE into thread T's
213 user address space. Return true if successful, false
216 load_segment (struct thread *t, struct file *file,
217 const struct Elf32_Phdr *phdr)
219 void *start, *end; /* Page-rounded segment start and end. */
220 uint8_t *upage; /* Iterator from start to end. */
221 off_t filesz_left; /* Bytes left of file data (as opposed to
222 zero-initialized bytes). */
224 /* Is this a read-only segment? Not currently used, so it's
225 commented out. You'll want to use it when implementing VM
226 to decide whether to page the segment from its executable or
228 //bool read_only = (phdr->p_flags & PF_W) == 0;
231 ASSERT (file != NULL);
232 ASSERT (phdr != NULL);
233 ASSERT (phdr->p_type == PT_LOAD);
235 /* [ELF1] 2-2 says that p_offset and p_vaddr must be congruent
237 if (phdr->p_offset % PGSIZE != phdr->p_vaddr % PGSIZE)
239 printf ("%#08"PE32Ox" and %#08"PE32Ax" not congruent modulo %#x\n",
240 phdr->p_offset, phdr->p_vaddr, (unsigned) PGSIZE);
244 /* [ELF1] 2-3 says that p_memsz must be at least as big as
246 if (phdr->p_memsz < phdr->p_filesz)
248 printf ("p_memsz (%08"PE32Wx") < p_filesz (%08"PE32Wx")\n",
249 phdr->p_memsz, phdr->p_filesz);
253 /* Validate virtual memory region to be mapped.
254 The region must both start and end within the user address
255 space range starting at 0 and ending at PHYS_BASE (typically
256 3 GB == 0xc0000000). */
257 start = pg_round_down ((void *) phdr->p_vaddr);
258 end = pg_round_up ((void *) (phdr->p_vaddr + phdr->p_memsz));
259 if (start >= PHYS_BASE || end >= PHYS_BASE || end < start)
261 printf ("bad virtual region %08lx...%08lx\n",
262 (unsigned long) start, (unsigned long) end);
266 /* Load the segment page-by-page into memory. */
267 filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
268 file_seek (file, ROUND_DOWN (phdr->p_offset, PGSIZE));
269 for (upage = start; upage < (uint8_t *) end; upage += PGSIZE)
271 /* We want to read min(PGSIZE, filesz_left) bytes from the
272 file into the page and zero the rest. */
273 size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
274 size_t zero_bytes = PGSIZE - read_bytes;
275 uint8_t *kpage = palloc_get (PAL_USER);
279 /* Do the reading and zeroing. */
280 if (file_read (file, kpage, read_bytes) != (int) read_bytes)
285 memset (kpage + read_bytes, 0, zero_bytes);
286 filesz_left -= read_bytes;
288 /* Add the page to the process's address space. */
289 if (!install_page (t, upage, kpage))
299 /* Create a minimal stack for T by mapping a zeroed page at the
300 top of user virtual memory. */
302 setup_stack (struct thread *t)
305 bool success = false;
307 kpage = palloc_get (PAL_USER | PAL_ZERO);
310 success = install_page (t, ((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
315 printf ("failed to allocate process stack\n");
320 /* Adds a mapping from user virtual address UPAGE to kernel
321 virtual address KPAGE to T's page tables. Fails if UPAGE is
322 already mapped or if memory allocation fails. */
324 install_page (struct thread *t, void *upage, void *kpage)
326 /* Verify that there's not already a page at that virtual
327 address, then map our page there. */
328 return (pagedir_get_page (t->pagedir, upage) == NULL
329 && pagedir_set_page (t->pagedir, upage, kpage, true));