BCQ touch-ups (XCC)
[akaros.git] / kern / src / elf.c
index 663f56b..8db3e45 100644 (file)
@@ -200,11 +200,23 @@ static int load_one_elf(struct proc *p, struct file *f, uintptr_t pgoffset,
                                                goto fail;
                                        }
 
-                                       /* Zero the end of it. */
+                                       /* Zero the end of it.  This is a huge pain in the ass.  The
+                                        * filesystems should zero out the last bits of a page if
+                                        * the file doesn't fill the last page.  But we're dealing
+                                        * with windows into otherwise complete files. */
                                        pte_t *pte = pgdir_walk(p->env_pgdir, (void*)last_page, 0);
-                                       assert(pte);
-                                       void* last_page_kva = ppn2kva(PTE2PPN(*pte));
-                                       memset(last_page_kva + partial, 0, PGSIZE - partial);
+                                       /* if we were able to get a PTE, then there is a real page
+                                        * backing the VMR, and we need to zero the excess.  if
+                                        * there isn't, then the page fault code should handle it.
+                                        * since we set populate above, we should have a PTE, except
+                                        * in cases where the offset + len window exceeded the file
+                                        * size.  in this case, we let them mmap it, but didn't
+                                        * populate it.  there will be a PF right away if someone
+                                        * tries to use this.  check out do_mmap for more info. */
+                                       if (pte) {
+                                               void* last_page_kva = ppn2kva(PTE2PPN(*pte));
+                                               memset(last_page_kva + partial, 0, PGSIZE - partial);
+                                       }
 
                                        filesz = ROUNDUP(filesz, PGSIZE);
                                }
@@ -254,8 +266,13 @@ int load_elf(struct proc* p, struct file* f)
                struct file *interp = do_file_open(ei.interp, 0, 0);
                if (!interp)
                        return -1;
-               /* Load dynamic linker one page into the address space */
-               int error = load_one_elf(p, interp, 1, &interp_ei, TRUE);
+               /* Load dynamic linker at 1M. Obvious MIB joke avoided.
+                * It used to be loaded at page 1, but the existence of valid addresses
+                * that low masked bad derefs through NULL pointer structs. This in turn
+                * helped us waste a full day debugging a bug in the Go runtime. True!
+                * Note that MMAP_LOWEST_VA also has this value but we want to make this
+                * explicit. */
+               int error = load_one_elf(p, interp, MiB>>12, &interp_ei, TRUE);
                kref_put(&interp->f_kref);
                if (error)
                        return -1;