1 #include "userprog/addrspace.h"
7 #include "userprog/tss.h"
8 #include "filesys/file.h"
9 #include "filesys/filesys.h"
10 #include "threads/init.h"
11 #include "threads/mmu.h"
12 #include "threads/paging.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;
100 bool file_open = false;
102 bool success = false;
105 /* Allocate page directory. */
106 t->pagedir = pagedir_create ();
107 if (t->pagedir == NULL)
108 LOAD_ERROR (("page directory allocation failed"));
110 /* Open executable file. */
111 file_open = filesys_open (filename, &file);
113 LOAD_ERROR (("open failed"));
115 /* Read and verify executable header. */
116 if (file_read (&file, &ehdr, sizeof ehdr) != sizeof ehdr)
117 LOAD_ERROR (("error reading executable header"));
118 if (memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7) != 0)
119 LOAD_ERROR (("file is not ELF"));
120 if (ehdr.e_type != 2)
121 LOAD_ERROR (("ELF file is not an executable"));
122 if (ehdr.e_machine != 3)
123 LOAD_ERROR (("ELF executable is not x86"));
124 if (ehdr.e_version != 1)
125 LOAD_ERROR (("ELF executable hasunknown version %d",
126 (int) ehdr.e_version));
127 if (ehdr.e_phentsize != sizeof (struct Elf32_Phdr))
128 LOAD_ERROR (("bad ELF program header size"));
129 if (ehdr.e_phnum > 1024)
130 LOAD_ERROR (("too many ELF program headers"));
132 /* Read program headers. */
133 file_ofs = ehdr.e_phoff;
134 for (i = 0; i < ehdr.e_phnum; i++)
136 struct Elf32_Phdr phdr;
138 file_seek (&file, file_ofs);
139 if (file_read (&file, &phdr, sizeof phdr) != sizeof phdr)
140 LOAD_ERROR (("error reading program header"));
141 file_ofs += sizeof phdr;
148 /* Ignore this segment. */
153 /* Reject the executable. */
154 LOAD_ERROR (("unsupported ELF segment type %d\n", phdr.p_type));
157 printf ("unknown ELF segment type %08x\n", phdr.p_type);
160 if (!load_segment (t, &file, &phdr))
167 if (!setup_stack (t))
171 *start = (void (*) (void)) ehdr.e_entry;
176 /* We arrive here whether the load is successful or not.
177 We can distinguish based on `success'. */
181 addrspace_destroy (t);
185 /* Destroys the user address space in T and frees all of its
188 addrspace_destroy (struct thread *t)
190 if (t->pagedir != NULL)
192 pagedir_destroy (t->pagedir);
197 /* Sets up the CPU for running user code in thread T, if any. */
199 addrspace_activate (struct thread *t)
203 /* Activate T's page tables. */
204 pagedir_activate (t->pagedir);
206 /* Set T's kernel stack for use in processing interrupts. */
207 tss_set_esp0 ((uint8_t *) t + PGSIZE);
210 /* addrspace_load() helpers. */
212 static bool install_page (struct thread *, void *upage, void *kpage);
214 /* Loads the segment described by PHDR from FILE into thread T's
215 user address space. Return true if successful, false
218 load_segment (struct thread *t, struct file *file,
219 const struct Elf32_Phdr *phdr)
221 void *start, *end; /* Page-rounded segment start and end. */
222 uint8_t *upage; /* Iterator from start to end. */
223 off_t filesz_left; /* Bytes left of file data (as opposed to
224 zero-initialized bytes). */
226 /* Is this a read-only segment? Not currently used, so it's
227 commented out. You'll want to use it when implementing VM
228 to decide whether to page the segment from its executable or
230 //bool read_only = (phdr->p_flags & PF_W) == 0;
233 ASSERT (file != NULL);
234 ASSERT (phdr != NULL);
235 ASSERT (phdr->p_type == PT_LOAD);
237 /* [ELF1] 2-2 says that p_offset and p_vaddr must be congruent
239 if (phdr->p_offset % PGSIZE != phdr->p_vaddr % PGSIZE)
241 printf ("%#08"PE32Ox" and %#08"PE32Ax" not congruent modulo %#x\n",
242 phdr->p_offset, phdr->p_vaddr, (unsigned) PGSIZE);
246 /* [ELF1] 2-3 says that p_memsz must be at least as big as
248 if (phdr->p_memsz < phdr->p_filesz)
250 printf ("p_memsz (%08"PE32Wx") < p_filesz (%08"PE32Wx")\n",
251 phdr->p_memsz, phdr->p_filesz);
255 /* Validate virtual memory region to be mapped.
256 The region must both start and end within the user address
257 space range starting at 0 and ending at PHYS_BASE (typically
258 3 GB == 0xc0000000). */
259 start = pg_round_down ((void *) phdr->p_vaddr);
260 end = pg_round_up ((void *) (phdr->p_vaddr + phdr->p_memsz));
261 if (start >= PHYS_BASE || end >= PHYS_BASE || end < start)
263 printf ("bad virtual region %08lx...%08lx\n",
264 (unsigned long) start, (unsigned long) end);
268 /* Load the segment page-by-page into memory. */
269 filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
270 file_seek (file, ROUND_DOWN (phdr->p_offset, PGSIZE));
271 for (upage = start; upage < (uint8_t *) end; upage += PGSIZE)
273 /* We want to read min(PGSIZE, filesz_left) bytes from the
274 file into the page and zero the rest. */
275 size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
276 size_t zero_bytes = PGSIZE - read_bytes;
277 uint8_t *kpage = palloc_get (0);
281 /* Do the reading and zeroing. */
282 if (file_read (file, kpage, read_bytes) != (int) read_bytes)
287 memset (kpage + read_bytes, 0, zero_bytes);
288 filesz_left -= read_bytes;
290 /* Add the page to the process's address space. */
291 if (!install_page (t, upage, kpage))
301 /* Create a minimal stack for T by mapping a zeroed page at the
302 top of user virtual memory. */
304 setup_stack (struct thread *t)
307 bool success = false;
309 kpage = palloc_get (PAL_ZERO);
312 success = install_page (t, ((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
317 printf ("failed to allocate process stack\n");
322 /* Adds a mapping from user virtual address UPAGE to kernel
323 virtual address KPAGE to T's page tables. Fails if UPAGE is
324 already mapped or if memory allocation fails. */
326 install_page (struct thread *t, void *upage, void *kpage)
328 /* Verify that there's not already a page at that virtual
329 address, then map our page there. */
330 return (pagedir_get_page (t->pagedir, upage) == NULL
331 && pagedir_set_page (t->pagedir, upage, kpage, true));