[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v2 08/13] xsplice: Implement payload loading (v2)



On 01/14/2016 09:47 PM, Konrad Rzeszutek Wilk wrote:
From: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>

Add support for loading xsplice payloads. This is somewhat similar to
the Linux kernel module loader, implementing the following steps:
- Verify the elf file.
- Parse the elf file.
- Allocate a region of memory mapped within a free area of
   [xen_virt_end, XEN_VIRT_END].
- Copy allocated sections into the new region.
- Resolve section symbols. All other symbols must be absolute addresses.
- Perform relocations.

Note that the structure 'xsplice_patch_func' differs a bit from the design
by usurping 8 bytes from the padding. We use that for our own uses.

Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
---
v2: - Change the 'xsplice_patch_func' structure layout/size.
     - Add more error checking. Fix memory leak.
     - Move elf_resolve and elf_perform relocs in elf file.
     - Print the payload address and pages in keyhandler.
v3:
     - Make it build under ARM
snip

+static void find_hole(ssize_t pages, unsigned long *hole_start,
+                      unsigned long *hole_end)
+{
+    struct payload *data, *data2;
+
+    spin_lock(&payload_list_lock);
+    list_for_each_entry ( data, &payload_list, list )
+    {
+        list_for_each_entry ( data2, &payload_list, list )
+        {
+            unsigned long start, end;
+
+            start = (unsigned long)data2->payload_address;
+            end = start + data2->payload_pages * PAGE_SIZE;
+            if ( *hole_end > start && *hole_start < end )
+            {
+                *hole_start = end;
+                *hole_end = *hole_start + pages * PAGE_SIZE;
+                break;
+            }
+        }
+        if ( &data2->list == &payload_list )
+            break;
+    }
+    spin_unlock(&payload_list_lock);
+}

This function above should go down into the CONFIG_X86 section below.

+
+/*
+ * The following functions prepare an xSplice payload to be executed by
+ * allocating space, loading the allocated sections, resolving symbols,
+ * performing relocations, etc.
+ */
+#ifdef CONFIG_X86
+static void *alloc_payload(size_t size)
+{
+    mfn_t *mfn, *mfn_ptr;
+    size_t pages, i;
+    struct page_info *pg;
+    unsigned long hole_start, hole_end, cur;
+
+    ASSERT(size);
+
+    /*
+     * Copied from vmalloc which allocates pages and then maps them to an
+     * arbitrary virtual address with PAGE_HYPERVISOR. We need specific
+     * virtual address with PAGE_HYPERVISOR_RWX.
+     */
+    pages = PFN_UP(size);
+    mfn = xmalloc_array(mfn_t, pages);
+    if ( mfn == NULL )
+        return NULL;
+
+    for ( i = 0; i < pages; i++ )
+    {
+        pg = alloc_domheap_page(NULL, 0);
+        if ( pg == NULL )
+            goto error;
+        mfn[i] = _mfn(page_to_mfn(pg));
snip
diff --git a/xen/common/xsplice_elf.c b/xen/common/xsplice_elf.c
index a5e9d63..ea7eb73 100644
--- a/xen/common/xsplice_elf.c
+++ b/xen/common/xsplice_elf.c
@@ -199,3 +199,87 @@ void xsplice_elf_free(struct xsplice_elf *elf)
      elf->name = NULL;
      elf->len = 0;
  }
+
+int xsplice_elf_resolve_symbols(struct xsplice_elf *elf)
+{
+    unsigned int i;
+
+    /*
+     * The first entry of an ELF symbol table is the "undefined symbol index".
+     * aka reserved so we skip it.
+     */
+    ASSERT( elf->sym );
+    for ( i = 1; i < elf->nsym; i++ )
+    {
+        switch ( elf->sym[i].sym->st_shndx )
+        {
+            case SHN_COMMON:
+                printk(XENLOG_ERR "%s: Unexpected common symbol: %s\n",
+                       elf->name, elf->sym[i].name);
+                return_(-EINVAL);
+                break;
+            case SHN_UNDEF:
+                printk(XENLOG_ERR "%s: Unknown symbol: %s\n", elf->name,
+                       elf->sym[i].name);
+                return_(-ENOENT);
+                break;
+            case SHN_ABS:
+                printk(XENLOG_DEBUG "%s: Absolute symbol: %s => 0x%p\n",
+                      elf->name, elf->sym[i].name,
+                      (void *)elf->sym[i].sym->st_value);
+                break;
+            default:
+                if ( elf->sec[elf->sym[i].sym->st_shndx].sec->sh_flags & 
SHF_ALLOC )
+                {
+                    elf->sym[i].sym->st_value +=
+                        (unsigned 
long)elf->sec[elf->sym[i].sym->st_shndx].load_addr;
+                    printk(XENLOG_DEBUG "%s: Symbol resolved: %s => 0x%p\n",
+                           elf->name, elf->sym[i].name,
+                           (void *)elf->sym[i].sym->st_value);
+                }
+        }
+    }
+
+    return 0;
+}
+
+int xsplice_elf_perform_relocs(struct xsplice_elf *elf)
+{
+    struct xsplice_elf_sec *rela, *base;
+    unsigned int i;
+    int rc;
+
+    /*
+     * The first entry of an ELF symbol table is the "undefined symbol index".
+     * aka reserved so we skip it.
+     */
+    ASSERT( elf->sym );
+    for ( i = 1; i < elf->hdr->e_shnum; i++ )
+    {
+        rela = &elf->sec[i];
+
+        if ( (rela->sec->sh_type != SHT_RELA ) &&
+             (rela->sec->sh_type != SHT_REL ) )
+            continue;
+
+         /* Is it a valid relocation section? */
+         if ( rela->sec->sh_info >= elf->hdr->e_shnum )
+            continue;
+
+         base = &elf->sec[rela->sec->sh_info];
+
+         /* Don't relocate non-allocated sections. */
+         if ( !(base->sec->sh_flags & SHF_ALLOC) )
+            continue;
+
+        if ( elf->sec[i].sec->sh_type == SHT_RELA )
+            rc = xsplice_perform_rela(elf, base, rela);
+        else /* SHT_REL */
+            rc = xsplice_perform_rel(elf, base, rela);
+
+        if ( rc )
+            return rc;
+    }
+
+    return 0;
+}

Is there a reason the above two functions weren't put in the previous patch?

diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index bd832df..4ea66bf 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -15,8 +15,10 @@

  #if defined(CONFIG_ARM_64)
  # define LONG_BYTEORDER 3
+# define ELFSIZE 64
  #else
  # define LONG_BYTEORDER 2
+# define ELFSIZE 32
  #endif

What does this do?

(And perhaps it should also be in the previous patch since it's mentioned in the previous patch's changelog?)

--
Ross Lagerwall

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.