user/vmm: add and use a load_elf function
authorRon Minnich <rminnich@xcpu.hot.corp.google.com>
Thu, 20 Apr 2017 15:39:07 +0000 (11:39 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 20 Apr 2017 19:03:35 +0000 (15:03 -0400)
load_elf loads an elf, not just a kernel.

I've tested vmrunkernel with this and it works fine.

Change-Id: Ib1d825746e0307565ecd44216bd739f9e6d30c54
Signed-off-by: Ron Minnich <rminnich@google.com>
[formatting]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/kfs/bin/m [changed mode: 0644->0755]
tests/dune/dune.c
tests/vmm/vmrunkernel.c
user/vmm/include/vmm/vmm.h
user/vmm/load_elf.c [new file with mode: 0644]
user/vmm/vmexit.c

old mode 100644 (file)
new mode 100755 (executable)
index 96ded4b..379266c 100644 (file)
@@ -38,103 +38,6 @@ static unsigned long long *p512, *p1, *p2m;
 
 static int debug = 0;
 
-/* load_kernel loads an ELF file as a kernel. */
-uintptr_t
-load_kernel(char *filename)
-{
-       Elf64_Ehdr *ehdr;
-       Elf *elf;
-       size_t phnum = 0;
-       Elf64_Phdr *hdrs;
-       int fd;
-
-       elf_version(EV_CURRENT);
-       fd = open(filename, O_RDONLY);
-       if (fd < 0) {
-               fprintf(stderr, "Can't open %s: %r\n", filename);
-               return 0;
-       }
-
-       elf = elf_begin(fd, ELF_C_READ, NULL);
-       if (elf == NULL) {
-               fprintf(stderr, "%s: cannot read %s ELF file.\n", __func__, filename);
-               close(fd);
-               return 0;
-       }
-
-       ehdr = elf64_getehdr(elf);
-       if (ehdr == NULL) {
-               fprintf(stderr, "%s: cannot get exec header of %s.\n",
-                       __func__, filename);
-               goto fail;
-       }
-       fprintf(stderr, "%s ELF entry point is %p\n", filename,
-               (void *)ehdr->e_entry);
-
-       if (elf_getphdrnum(elf, &phnum) < 0) {
-               fprintf(stderr, "%s: cannot get program header num of %s.\n",
-                       __func__, filename);
-               goto fail;
-       }
-       fprintf(stderr, "%s has %p program headers\n", filename, phnum);
-
-       hdrs = elf64_getphdr(elf);
-       if (hdrs == NULL) {
-               fprintf(stderr, "%s: cannot get program headers of %s.\n",
-                       __func__, filename);
-               goto fail;
-       }
-
-       for (int i = 0; i < phnum; i++) {
-               size_t tot;
-               Elf64_Phdr *h = &hdrs[i];
-               uintptr_t pa;
-
-               fprintf(stderr,
-                       "%d: type 0x%lx flags 0x%lx  offset 0x%lx vaddr 0x%lx paddr 0x%lx size 0x%lx  memsz 0x%lx align 0x%lx\n",
-                       i,
-                       h->p_type,              /* Segment type */
-                       h->p_flags,             /* Segment flags */
-                       h->p_offset,            /* Segment file offset */
-                       h->p_vaddr,             /* Segment virtual address */
-                       h->p_paddr,             /* Segment physical address */
-                       h->p_filesz,            /* Segment size in file */
-                       h->p_memsz,             /* Segment size in memory */
-                       h->p_align              /* Segment alignment */);
-               if (h->p_type != PT_LOAD)
-                       continue;
-               if ((h->p_flags & (PF_R | PF_W | PF_X)) == 0)
-                       continue;
-
-               pa = h->p_paddr;
-               fprintf(stderr,
-                       "Read header %d @offset %p to %p (elf PA is %p) %d bytes:",
-                       i, h->p_offset, pa, h->p_paddr, h->p_filesz);
-               tot = 0;
-               while (tot < h->p_filesz) {
-                       int amt = pread(fd, (void *)(pa + tot), h->p_filesz - tot,
-                                       h->p_offset + tot);
-                       if (amt < 1)
-                               break;
-                       tot += amt;
-               }
-               fprintf(stderr, "read a total of %d bytes\n", tot);
-               if (tot < h->p_filesz) {
-                       fprintf(stderr, "%s: got %d bytes, wanted %d bytes\n",
-                               filename, tot, h->p_filesz);
-                       goto fail;
-               }
-       }
-
-       close(fd);
-       elf_end(elf);
-       return ehdr->e_entry;
- fail:
-       close(fd);
-       elf_end(elf);
-       return 0;
-}
-
 int main(int argc, char **argv)
 {
        int vmmflags = VMM_VMCALL_PRINTF;
@@ -227,7 +130,7 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       entry = load_kernel(argv[0]);
+       entry = load_elf(argv[0]);
        if (entry == 0) {
                fprintf(stderr, "Unable to load kernel %s\n", argv[0]);
                exit(1);
index 9e5801b..4bcbf23 100644 (file)
@@ -329,103 +329,6 @@ static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
        return oldbit;
 }
 
-/* load_kernel loads an ELF file as a kernel. */
-uintptr_t
-load_kernel(char *filename)
-{
-       Elf64_Ehdr *ehdr;
-       Elf *elf;
-       size_t phnum = 0;
-       Elf64_Phdr *hdrs;
-       int fd;
-
-       elf_version(EV_CURRENT);
-       fd = open(filename, O_RDONLY);
-       if (fd < 0) {
-               fprintf(stderr, "Can't open %s: %r\n", filename);
-               return 0;
-       }
-
-       elf = elf_begin(fd, ELF_C_READ, NULL);
-       if (elf == NULL) {
-               fprintf(stderr, "%s: cannot read %s ELF file.\n", __func__, filename);
-               close(fd);
-               return 0;
-       }
-
-       ehdr = elf64_getehdr(elf);
-       if (ehdr == NULL) {
-               fprintf(stderr, "%s: cannot get exec header of %s.\n",
-                       __func__, filename);
-               goto fail;
-       }
-       fprintf(stderr, "%s ELF entry point is %p\n", filename,
-               (void *)ehdr->e_entry);
-
-       if (elf_getphdrnum(elf, &phnum) < 0) {
-               fprintf(stderr, "%s: cannot get program header num of %s.\n",
-                       __func__, filename);
-               goto fail;
-       }
-       fprintf(stderr, "%s has %p program headers\n", filename, phnum);
-
-       hdrs = elf64_getphdr(elf);
-       if (hdrs == NULL) {
-               fprintf(stderr, "%s: cannot get program headers of %s.\n",
-                       __func__, filename);
-               goto fail;
-       }
-
-       for (int i = 0; i < phnum; i++) {
-               size_t tot;
-               Elf64_Phdr *h = &hdrs[i];
-               uintptr_t pa;
-
-               fprintf(stderr,
-                       "%d: type 0x%lx flags 0x%lx  offset 0x%lx vaddr 0x%lx paddr 0x%lx size 0x%lx  memsz 0x%lx align 0x%lx\n",
-                       i,
-                       h->p_type,              /* Segment type */
-                       h->p_flags,             /* Segment flags */
-                       h->p_offset,            /* Segment file offset */
-                       h->p_vaddr,             /* Segment virtual address */
-                       h->p_paddr,             /* Segment physical address */
-                       h->p_filesz,            /* Segment size in file */
-                       h->p_memsz,             /* Segment size in memory */
-                       h->p_align              /* Segment alignment */);
-               if (h->p_type != PT_LOAD)
-                       continue;
-               if ((h->p_flags & (PF_R | PF_W | PF_X)) == 0)
-                       continue;
-
-               pa = h->p_paddr;
-               fprintf(stderr,
-                       "Read header %d @offset %p to %p (elf PA is %p) %d bytes:",
-                       i, h->p_offset, pa, h->p_paddr, h->p_filesz);
-               tot = 0;
-               while (tot < h->p_filesz) {
-                       int amt = pread(fd, (void *)(pa + tot), h->p_filesz - tot,
-                                       h->p_offset + tot);
-                       if (amt < 1)
-                               break;
-                       tot += amt;
-               }
-               fprintf(stderr, "read a total of %d bytes\n", tot);
-               if (tot < h->p_filesz) {
-                       fprintf(stderr, "%s: got %d bytes, wanted %d bytes\n",
-                               filename, tot, h->p_filesz);
-                       goto fail;
-               }
-       }
-
-       close(fd);
-       elf_end(elf);
-       return ehdr->e_entry;
-fail:
-       close(fd);
-       elf_end(elf);
-       return 0;
-}
-
 /* TODO: put this in a library somewhere */
 int cat(char *file, void *where)
 {
@@ -793,7 +696,7 @@ int main(int argc, char **argv)
 
        mmap_memory(memstart, memsize);
 
-       entry = load_kernel(argv[0]);
+       entry = load_elf(argv[0]);
        if (entry == 0) {
                fprintf(stderr, "Unable to load kernel %s\n", argv[0]);
                exit(1);
index 3694ace..d57daaa 100644 (file)
@@ -84,6 +84,7 @@ int __apic_access(struct guest_thread *vm_thread, uint64_t gpa, int destreg,
                   uint64_t *regp, int store);
 int vmm_interrupt_guest(struct virtual_machine *vm, unsigned int gpcoreid,
                         unsigned int vector);
+uintptr_t load_elf(char *filename);
 
 /* Lookup helpers */
 
diff --git a/user/vmm/load_elf.c b/user/vmm/load_elf.c
new file mode 100644 (file)
index 0000000..7ab92fd
--- /dev/null
@@ -0,0 +1,109 @@
+/* Copyright (c) 2017 Google Inc.
+ * See LICENSE for details.
+ *
+ * ELF loading. */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <libelf.h>
+
+/* load_elf loads and ELF file. This is almost always a kernel.
+ * We assume that memory is set up correctly, and it will go hard
+ * with you if it is not. */
+uintptr_t
+load_elf(char *filename)
+{
+       Elf64_Ehdr *ehdr;
+       Elf *elf;
+       size_t phnum = 0;
+       Elf64_Phdr *hdrs;
+       int fd;
+
+       elf_version(EV_CURRENT);
+       fd = open(filename, O_RDONLY);
+       if (fd < 0) {
+               fprintf(stderr, "Can't open %s: %r\n", filename);
+               return 0;
+       }
+
+       elf = elf_begin(fd, ELF_C_READ, NULL);
+       if (elf == NULL) {
+               fprintf(stderr, "%s: cannot read %s ELF file.\n", __func__, filename);
+               close(fd);
+               return 0;
+       }
+
+       ehdr = elf64_getehdr(elf);
+       if (ehdr == NULL) {
+               fprintf(stderr, "%s: cannot get exec header of %s.\n",
+                       __func__, filename);
+               goto fail;
+       }
+       fprintf(stderr, "%s ELF entry point is %p\n", filename,
+               (void *)ehdr->e_entry);
+
+       if (elf_getphdrnum(elf, &phnum) < 0) {
+               fprintf(stderr, "%s: cannot get program header num of %s.\n",
+                       __func__, filename);
+               goto fail;
+       }
+       fprintf(stderr, "%s has %p program headers\n", filename, phnum);
+
+       hdrs = elf64_getphdr(elf);
+       if (hdrs == NULL) {
+               fprintf(stderr, "%s: cannot get program headers of %s.\n",
+                       __func__, filename);
+               goto fail;
+       }
+
+       for (int i = 0; i < phnum; i++) {
+               size_t tot;
+               Elf64_Phdr *h = &hdrs[i];
+               uintptr_t pa;
+
+               fprintf(stderr,
+                       "%d: type 0x%lx flags 0x%lx  offset 0x%lx vaddr 0x%lx paddr 0x%lx size 0x%lx  memsz 0x%lx align 0x%lx\n",
+                       i,
+                       h->p_type,              /* Segment type */
+                       h->p_flags,             /* Segment flags */
+                       h->p_offset,            /* Segment file offset */
+                       h->p_vaddr,             /* Segment virtual address */
+                       h->p_paddr,             /* Segment physical address */
+                       h->p_filesz,            /* Segment size in file */
+                       h->p_memsz,             /* Segment size in memory */
+                       h->p_align              /* Segment alignment */);
+               if (h->p_type != PT_LOAD)
+                       continue;
+               if ((h->p_flags & (PF_R | PF_W | PF_X)) == 0)
+                       continue;
+
+               pa = h->p_paddr;
+               fprintf(stderr,
+                       "Read header %d @offset %p to %p (elf PA is %p) %d bytes:",
+                       i, h->p_offset, pa, h->p_paddr, h->p_filesz);
+               tot = 0;
+               while (tot < h->p_filesz) {
+                       int amt = pread(fd, (void *)(pa + tot), h->p_filesz - tot,
+                                       h->p_offset + tot);
+
+                       if (amt < 1)
+                               break;
+                       tot += amt;
+               }
+               fprintf(stderr, "read a total of %d bytes\n", tot);
+               if (tot < h->p_filesz) {
+                       fprintf(stderr, "%s: got %d bytes, wanted %d bytes\n",
+                               filename, tot, h->p_filesz);
+                       goto fail;
+               }
+       }
+
+       close(fd);
+       elf_end(elf);
+       return ehdr->e_entry;
+fail:
+       close(fd);
+       elf_end(elf);
+       return 0;
+}
index bf7a05b..fa61c80 100644 (file)
@@ -342,7 +342,7 @@ bool handle_vmexit(struct guest_thread *gth)
                /* TODO: just ignore these? */
                return TRUE;
        default:
-               fprintf(stderr, "Don't know how to handle exit %d\n",
+               fprintf(stderr, "VMM library: don't know how to handle exit %d\n",
                        vm_tf->tf_exit_reason);
                fprintf(stderr, "RIP %p, shutdown 0x%x\n", vm_tf->tf_rip,
                        vm_tf->tf_exit_reason);