···11+/*22+ * tools/testing/selftests/kvm/lib/elf.c33+ *44+ * Copyright (C) 2018, Google LLC.55+ *66+ * This work is licensed under the terms of the GNU GPL, version 2.77+ */88+99+#include "test_util.h"1010+1111+#include <bits/endian.h>1212+#include <linux/elf.h>1313+1414+#include "kvm_util.h"1515+#include "kvm_util_internal.h"1616+1717+static void elfhdr_get(const char *filename, Elf64_Ehdr *hdrp)1818+{1919+ off_t offset_rv;2020+2121+ /* Open the ELF file. */2222+ int fd;2323+ fd = open(filename, O_RDONLY);2424+ TEST_ASSERT(fd >= 0, "Failed to open ELF file,\n"2525+ " filename: %s\n"2626+ " rv: %i errno: %i", filename, fd, errno);2727+2828+ /* Read in and validate ELF Identification Record.2929+ * The ELF Identification record is the first 16 (EI_NIDENT) bytes3030+ * of the ELF header, which is at the beginning of the ELF file.3131+ * For now it is only safe to read the first EI_NIDENT bytes. Once3232+ * read and validated, the value of e_ehsize can be used to determine3333+ * the real size of the ELF header.3434+ */3535+ unsigned char ident[EI_NIDENT];3636+ test_read(fd, ident, sizeof(ident));3737+ TEST_ASSERT((ident[EI_MAG0] == ELFMAG0) && (ident[EI_MAG1] == ELFMAG1)3838+ && (ident[EI_MAG2] == ELFMAG2) && (ident[EI_MAG3] == ELFMAG3),3939+ "ELF MAGIC Mismatch,\n"4040+ " filename: %s\n"4141+ " ident[EI_MAG0 - EI_MAG3]: %02x %02x %02x %02x\n"4242+ " Expected: %02x %02x %02x %02x",4343+ filename,4444+ ident[EI_MAG0], ident[EI_MAG1], ident[EI_MAG2], ident[EI_MAG3],4545+ ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3);4646+ TEST_ASSERT(ident[EI_CLASS] == ELFCLASS64,4747+ "Current implementation only able to handle ELFCLASS64,\n"4848+ " filename: %s\n"4949+ " ident[EI_CLASS]: %02x\n"5050+ " expected: %02x",5151+ filename,5252+ ident[EI_CLASS], ELFCLASS64);5353+ TEST_ASSERT(((BYTE_ORDER == LITTLE_ENDIAN)5454+ && (ident[EI_DATA] == ELFDATA2LSB))5555+ || ((BYTE_ORDER == BIG_ENDIAN)5656+ && (ident[EI_DATA] == ELFDATA2MSB)), "Current "5757+ "implementation only able to handle\n"5858+ "cases where the host and ELF file endianness\n"5959+ "is the same:\n"6060+ " host BYTE_ORDER: %u\n"6161+ " host LITTLE_ENDIAN: %u\n"6262+ " host BIG_ENDIAN: %u\n"6363+ " ident[EI_DATA]: %u\n"6464+ " ELFDATA2LSB: %u\n"6565+ " ELFDATA2MSB: %u",6666+ BYTE_ORDER, LITTLE_ENDIAN, BIG_ENDIAN,6767+ ident[EI_DATA], ELFDATA2LSB, ELFDATA2MSB);6868+ TEST_ASSERT(ident[EI_VERSION] == EV_CURRENT,6969+ "Current implementation only able to handle current "7070+ "ELF version,\n"7171+ " filename: %s\n"7272+ " ident[EI_VERSION]: %02x\n"7373+ " expected: %02x",7474+ filename, ident[EI_VERSION], EV_CURRENT);7575+7676+ /* Read in the ELF header.7777+ * With the ELF Identification portion of the ELF header7878+ * validated, especially that the value at EI_VERSION is7979+ * as expected, it is now safe to read the entire ELF header.8080+ */8181+ offset_rv = lseek(fd, 0, SEEK_SET);8282+ TEST_ASSERT(offset_rv == 0, "Seek to ELF header failed,\n"8383+ " rv: %zi expected: %i", offset_rv, 0);8484+ test_read(fd, hdrp, sizeof(*hdrp));8585+ TEST_ASSERT(hdrp->e_phentsize == sizeof(Elf64_Phdr),8686+ "Unexpected physical header size,\n"8787+ " hdrp->e_phentsize: %x\n"8888+ " expected: %zx",8989+ hdrp->e_phentsize, sizeof(Elf64_Phdr));9090+ TEST_ASSERT(hdrp->e_shentsize == sizeof(Elf64_Shdr),9191+ "Unexpected section header size,\n"9292+ " hdrp->e_shentsize: %x\n"9393+ " expected: %zx",9494+ hdrp->e_shentsize, sizeof(Elf64_Shdr));9595+}9696+9797+/* VM ELF Load9898+ *9999+ * Input Args:100100+ * filename - Path to ELF file101101+ *102102+ * Output Args: None103103+ *104104+ * Input/Output Args:105105+ * vm - Pointer to opaque type that describes the VM.106106+ *107107+ * Return: None, TEST_ASSERT failures for all error conditions108108+ *109109+ * Loads the program image of the ELF file specified by filename,110110+ * into the virtual address space of the VM pointed to by vm. On entry111111+ * the VM needs to not be using any of the virtual address space used112112+ * by the image and it needs to have sufficient available physical pages, to113113+ * back the virtual pages used to load the image.114114+ */115115+void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename,116116+ uint32_t data_memslot, uint32_t pgd_memslot)117117+{118118+ off_t offset, offset_rv;119119+ Elf64_Ehdr hdr;120120+121121+ /* Open the ELF file. */122122+ int fd;123123+ fd = open(filename, O_RDONLY);124124+ TEST_ASSERT(fd >= 0, "Failed to open ELF file,\n"125125+ " filename: %s\n"126126+ " rv: %i errno: %i", filename, fd, errno);127127+128128+ /* Read in the ELF header. */129129+ elfhdr_get(filename, &hdr);130130+131131+ /* For each program header.132132+ * The following ELF header members specify the location133133+ * and size of the program headers:134134+ *135135+ * e_phoff - File offset to start of program headers136136+ * e_phentsize - Size of each program header137137+ * e_phnum - Number of program header entries138138+ */139139+ for (unsigned int n1 = 0; n1 < hdr.e_phnum; n1++) {140140+ /* Seek to the beginning of the program header. */141141+ offset = hdr.e_phoff + (n1 * hdr.e_phentsize);142142+ offset_rv = lseek(fd, offset, SEEK_SET);143143+ TEST_ASSERT(offset_rv == offset,144144+ "Failed to seek to begining of program header %u,\n"145145+ " filename: %s\n"146146+ " rv: %jd errno: %i",147147+ n1, filename, (intmax_t) offset_rv, errno);148148+149149+ /* Read in the program header. */150150+ Elf64_Phdr phdr;151151+ test_read(fd, &phdr, sizeof(phdr));152152+153153+ /* Skip if this header doesn't describe a loadable segment. */154154+ if (phdr.p_type != PT_LOAD)155155+ continue;156156+157157+ /* Allocate memory for this segment within the VM. */158158+ TEST_ASSERT(phdr.p_memsz > 0, "Unexpected loadable segment "159159+ "memsize of 0,\n"160160+ " phdr index: %u p_memsz: 0x%" PRIx64,161161+ n1, (uint64_t) phdr.p_memsz);162162+ vm_vaddr_t seg_vstart = phdr.p_vaddr;163163+ seg_vstart &= ~(vm_vaddr_t)(vm->page_size - 1);164164+ vm_vaddr_t seg_vend = phdr.p_vaddr + phdr.p_memsz - 1;165165+ seg_vend |= vm->page_size - 1;166166+ size_t seg_size = seg_vend - seg_vstart + 1;167167+168168+ vm_vaddr_t vaddr = vm_vaddr_alloc(vm, seg_size, seg_vstart,169169+ data_memslot, pgd_memslot);170170+ TEST_ASSERT(vaddr == seg_vstart, "Unable to allocate "171171+ "virtual memory for segment at requested min addr,\n"172172+ " segment idx: %u\n"173173+ " seg_vstart: 0x%lx\n"174174+ " vaddr: 0x%lx",175175+ n1, seg_vstart, vaddr);176176+ memset(addr_gva2hva(vm, vaddr), 0, seg_size);177177+ /* TODO(lhuemill): Set permissions of each memory segment178178+ * based on the least-significant 3 bits of phdr.p_flags.179179+ */180180+181181+ /* Load portion of initial state that is contained within182182+ * the ELF file.183183+ */184184+ if (phdr.p_filesz) {185185+ offset_rv = lseek(fd, phdr.p_offset, SEEK_SET);186186+ TEST_ASSERT(offset_rv == phdr.p_offset,187187+ "Seek to program segment offset failed,\n"188188+ " program header idx: %u errno: %i\n"189189+ " offset_rv: 0x%jx\n"190190+ " expected: 0x%jx\n",191191+ n1, errno, (intmax_t) offset_rv,192192+ (intmax_t) phdr.p_offset);193193+ test_read(fd, addr_gva2hva(vm, phdr.p_vaddr),194194+ phdr.p_filesz);195195+ }196196+ }197197+}
+158
tools/testing/selftests/kvm/lib/io.c
···11+/*22+ * tools/testing/selftests/kvm/lib/io.c33+ *44+ * Copyright (C) 2018, Google LLC.55+ *66+ * This work is licensed under the terms of the GNU GPL, version 2.77+ */88+99+#include "test_util.h"1010+1111+/* Test Write1212+ *1313+ * A wrapper for write(2), that automatically handles the following1414+ * special conditions:1515+ *1616+ * + Interrupted system call (EINTR)1717+ * + Write of less than requested amount1818+ * + Non-block return (EAGAIN)1919+ *2020+ * For each of the above, an additional write is performed to automatically2121+ * continue writing the requested data.2222+ * There are also many cases where write(2) can return an unexpected2323+ * error (e.g. EIO). Such errors cause a TEST_ASSERT failure.2424+ *2525+ * Note, for function signature compatibility with write(2), this function2626+ * returns the number of bytes written, but that value will always be equal2727+ * to the number of requested bytes. All other conditions in this and2828+ * future enhancements to this function either automatically issue another2929+ * write(2) or cause a TEST_ASSERT failure.3030+ *3131+ * Args:3232+ * fd - Opened file descriptor to file to be written.3333+ * count - Number of bytes to write.3434+ *3535+ * Output:3636+ * buf - Starting address of data to be written.3737+ *3838+ * Return:3939+ * On success, number of bytes written.4040+ * On failure, a TEST_ASSERT failure is caused.4141+ */4242+ssize_t test_write(int fd, const void *buf, size_t count)4343+{4444+ ssize_t rc;4545+ ssize_t num_written = 0;4646+ size_t num_left = count;4747+ const char *ptr = buf;4848+4949+ /* Note: Count of zero is allowed (see "RETURN VALUE" portion of5050+ * write(2) manpage for details.5151+ */5252+ TEST_ASSERT(count >= 0, "Unexpected count, count: %li", count);5353+5454+ do {5555+ rc = write(fd, ptr, num_left);5656+5757+ switch (rc) {5858+ case -1:5959+ TEST_ASSERT(errno == EAGAIN || errno == EINTR,6060+ "Unexpected write failure,\n"6161+ " rc: %zi errno: %i", rc, errno);6262+ continue;6363+6464+ case 0:6565+ TEST_ASSERT(false, "Unexpected EOF,\n"6666+ " rc: %zi num_written: %zi num_left: %zu",6767+ rc, num_written, num_left);6868+ break;6969+7070+ default:7171+ TEST_ASSERT(rc >= 0, "Unexpected ret from write,\n"7272+ " rc: %zi errno: %i", rc, errno);7373+ num_written += rc;7474+ num_left -= rc;7575+ ptr += rc;7676+ break;7777+ }7878+ } while (num_written < count);7979+8080+ return num_written;8181+}8282+8383+/* Test Read8484+ *8585+ * A wrapper for read(2), that automatically handles the following8686+ * special conditions:8787+ *8888+ * + Interrupted system call (EINTR)8989+ * + Read of less than requested amount9090+ * + Non-block return (EAGAIN)9191+ *9292+ * For each of the above, an additional read is performed to automatically9393+ * continue reading the requested data.9494+ * There are also many cases where read(2) can return an unexpected9595+ * error (e.g. EIO). Such errors cause a TEST_ASSERT failure. Note,9696+ * it is expected that the file opened by fd at the current file position9797+ * contains at least the number of requested bytes to be read. A TEST_ASSERT9898+ * failure is produced if an End-Of-File condition occurs, before all the9999+ * data is read. It is the callers responsibility to assure that sufficient100100+ * data exists.101101+ *102102+ * Note, for function signature compatibility with read(2), this function103103+ * returns the number of bytes read, but that value will always be equal104104+ * to the number of requested bytes. All other conditions in this and105105+ * future enhancements to this function either automatically issue another106106+ * read(2) or cause a TEST_ASSERT failure.107107+ *108108+ * Args:109109+ * fd - Opened file descriptor to file to be read.110110+ * count - Number of bytes to read.111111+ *112112+ * Output:113113+ * buf - Starting address of where to write the bytes read.114114+ *115115+ * Return:116116+ * On success, number of bytes read.117117+ * On failure, a TEST_ASSERT failure is caused.118118+ */119119+ssize_t test_read(int fd, void *buf, size_t count)120120+{121121+ ssize_t rc;122122+ ssize_t num_read = 0;123123+ size_t num_left = count;124124+ char *ptr = buf;125125+126126+ /* Note: Count of zero is allowed (see "If count is zero" portion of127127+ * read(2) manpage for details.128128+ */129129+ TEST_ASSERT(count >= 0, "Unexpected count, count: %li", count);130130+131131+ do {132132+ rc = read(fd, ptr, num_left);133133+134134+ switch (rc) {135135+ case -1:136136+ TEST_ASSERT(errno == EAGAIN || errno == EINTR,137137+ "Unexpected read failure,\n"138138+ " rc: %zi errno: %i", rc, errno);139139+ break;140140+141141+ case 0:142142+ TEST_ASSERT(false, "Unexpected EOF,\n"143143+ " rc: %zi num_read: %zi num_left: %zu",144144+ rc, num_read, num_left);145145+ break;146146+147147+ default:148148+ TEST_ASSERT(rc > 0, "Unexpected ret from read,\n"149149+ " rc: %zi errno: %i", rc, errno);150150+ num_read += rc;151151+ num_left -= rc;152152+ ptr += rc;153153+ break;154154+ }155155+ } while (num_read < count);156156+157157+ return num_read;158158+}