From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: xen-devel@lists.xenproject.org, ross.lagerwall@citrix.com,
konrad@kernel.org, andrew.cooper3@citrix.com, mpohlack@amazon.de,
sasha.levin@oracle.com
Cc: Keir Fraser <keir@xen.org>, Julien Grall <julien.grall@arm.com>,
Stefano Stabellini <stefano.stabellini@citrix.com>,
Jan Beulich <jbeulich@suse.com>,
Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Subject: [PATCH v5 10/28] xsplice: Implement payload loading
Date: Thu, 24 Mar 2016 16:00:22 -0400 [thread overview]
Message-ID: <1458849640-22588-11-git-send-email-konrad.wilk@oracle.com> (raw)
In-Reply-To: <1458849640-22588-1-git-send-email-konrad.wilk@oracle.com>
From: Ross Lagerwall <ross.lagerwall@citrix.com>
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. Split them in three
regions - .text, .data, and .rodata. MUST have at least .text.
- Resolve section symbols. All other symbols must be absolute addresses.
(Note that patch titled "xsplice,symbols: Implement symbol name resolution
on address" implements that)
- Perform relocations.
- Secure the the regions (.text,.data,.rodata) with proper permissions.
We capitalize on the vmalloc callback API (see patch titled:
"vmap: Add vmalloc_cb and vfree_cb") to allocate a region
of memory within the [xen_virt_end, XEN_VIRT_END] for the code.
Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Stefano Stabellini <stefano.stabellini@citrix.com>
Cc: Julien Grall <julien.grall@arm.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
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
- Build it without using the return_ macro.
- Add fixes from Ross.
- Add the _return macro back - but only use it during debug builds.
- Remove the macro, prefix arch_ on arch specific calls.
v4:
- Move alloc_payload to arch specific file.
- Use void* instead of uint8_t, use const
- Add copyrights
- Unroll the vmap code to add ASSERT. Change while to not incur
potential long error loop
- Use vmalloc/vfree cb APIs
- Secure .text pages to be RX instead of RWX.
v5:
- Fix allocation of virtual addresses only allowing one page to be allocated.
- Create .text, .data, and .rodata regions with different permissions.
- Make the find_space_t not a typedef to pointer to a function.
- Allocate memory in here.
---
---
xen/arch/arm/Makefile | 1 +
xen/arch/arm/xsplice.c | 55 ++++++++
xen/arch/x86/Makefile | 1 +
xen/arch/x86/setup.c | 7 +
xen/arch/x86/xsplice.c | 258 +++++++++++++++++++++++++++++++++++++
xen/common/xsplice.c | 262 +++++++++++++++++++++++++++++++++++++-
xen/common/xsplice_elf.c | 91 +++++++++++++
xen/include/asm-x86/x86_64/page.h | 2 +
xen/include/xen/xsplice.h | 46 +++++++
xen/include/xen/xsplice_elf.h | 5 +
10 files changed, 725 insertions(+), 3 deletions(-)
create mode 100644 xen/arch/arm/xsplice.c
create mode 100644 xen/arch/x86/xsplice.c
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 0328b50..eae5cb3 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -40,6 +40,7 @@ obj-y += device.o
obj-y += decode.o
obj-y += processor.o
obj-y += smc.o
+obj-$(CONFIG_XSPLICE) += xsplice.o
#obj-bin-y += ....o
diff --git a/xen/arch/arm/xsplice.c b/xen/arch/arm/xsplice.c
new file mode 100644
index 0000000..e9c49ab
--- /dev/null
+++ b/xen/arch/arm/xsplice.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 Citrix Systems R&D Ltd.
+ */
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/xsplice_elf.h>
+#include <xen/xsplice.h>
+
+int arch_xsplice_verify_elf(const struct xsplice_elf *elf, void *data)
+{
+ return -ENOSYS;
+}
+
+int arch_xsplice_perform_rel(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela)
+{
+ return -ENOSYS;
+}
+
+int arch_xsplice_perform_rela(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela)
+{
+ return -ENOSYS;
+}
+
+void *arch_xsplice_alloc_payload(unsigned int pages, mfn_t **mfn)
+{
+ return NULL;
+}
+
+int arch_xsplice_secure(void *va, unsigned int pages, enum va_type type,
+ const mfn_t *mfn)
+{
+ return -ENOSYS;
+}
+
+void arch_xsplice_register_find_space(find_space_t *cb)
+{
+}
+
+void arch_xsplice_free_payload(void *va, unsigned int pages)
+{
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 729065b..8a6a7d5 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -64,6 +64,7 @@ obj-y += vm_event.o
obj-y += xstate.o
obj-$(crash_debug) += gdbstub.o
+obj-$(CONFIG_XSPLICE) += xsplice.o
x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index c8a5adb..b306da8 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -100,6 +100,9 @@ unsigned long __read_mostly xen_phys_start;
unsigned long __read_mostly xen_virt_end;
+unsigned long __read_mostly avail_virt_start;
+unsigned long __read_mostly avail_virt_end;
+
DEFINE_PER_CPU(struct tss_struct, init_tss);
char __section(".bss.stack_aligned") cpu0_stack[STACK_SIZE];
@@ -1211,6 +1214,10 @@ void __init noreturn __start_xen(unsigned long mbi_p)
~((1UL << L2_PAGETABLE_SHIFT) - 1);
destroy_xen_mappings(xen_virt_end, XEN_VIRT_START + BOOTSTRAP_MAP_BASE);
+ avail_virt_start = xen_virt_end;
+ avail_virt_end = XEN_VIRT_END - NR_CPUS * PAGE_SIZE;
+ BUG_ON(avail_virt_end <= avail_virt_start);
+
/*
* If not using 2M mappings to gain suitable pagetable permissions
* directly from the relocation above, remap the code/data
diff --git a/xen/arch/x86/xsplice.c b/xen/arch/x86/xsplice.c
new file mode 100644
index 0000000..7149540
--- /dev/null
+++ b/xen/arch/x86/xsplice.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2016 Citrix Systems R&D Ltd.
+ */
+
+#include <xen/errno.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/pfn.h>
+#include <xen/vmap.h>
+#include <xen/xsplice_elf.h>
+#include <xen/xsplice.h>
+
+int arch_xsplice_verify_elf(const struct xsplice_elf *elf, void *data)
+{
+
+ Elf_Ehdr *hdr = data;
+
+ if ( !IS_ELF(*hdr) )
+ {
+ printk(XENLOG_ERR "%s%s: Not an ELF payload!\n", XSPLICE, elf->name);
+ return -EINVAL;
+ }
+
+ if ( elf->len < (sizeof *hdr) ||
+ !IS_ELF(*hdr) ||
+ hdr->e_ident[EI_CLASS] != ELFCLASS64 ||
+ hdr->e_ident[EI_DATA] != ELFDATA2LSB ||
+ hdr->e_ident[EI_OSABI] != ELFOSABI_SYSV ||
+ hdr->e_machine != EM_X86_64 ||
+ hdr->e_type != ET_REL ||
+ hdr->e_phnum != 0 )
+ {
+ printk(XENLOG_ERR "%s%s: Invalid ELF payload!\n", XSPLICE, elf->name);
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+int arch_xsplice_perform_rel(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela)
+{
+ dprintk(XENLOG_ERR, "%s%s: SHR_REL relocation unsupported\n",
+ XSPLICE, elf->name);
+ return -ENOSYS;
+}
+
+int arch_xsplice_perform_rela(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela)
+{
+ Elf_RelA *r;
+ unsigned int symndx, i;
+ uint64_t val;
+ uint8_t *dest;
+
+ if ( !rela->sec->sh_entsize || !rela->sec->sh_size ||
+ rela->sec->sh_entsize != sizeof(Elf_RelA) )
+ {
+ dprintk(XENLOG_DEBUG, "%s%s: Section relative header is corrupted!\n",
+ XSPLICE, elf->name);
+ return -EINVAL;
+ }
+
+ for ( i = 0; i < (rela->sec->sh_size / rela->sec->sh_entsize); i++ )
+ {
+ r = (Elf_RelA *)(rela->data + i * rela->sec->sh_entsize);
+ if ( (unsigned long)r > (unsigned long)(elf->hdr + elf->len) )
+ {
+ dprintk(XENLOG_DEBUG, "%s%s: Relative entry %u in %s is past end!\n",
+ XSPLICE, elf->name, i, rela->name);
+ return -EINVAL;
+ }
+
+ symndx = ELF64_R_SYM(r->r_info);
+ if ( symndx > elf->nsym )
+ {
+ dprintk(XENLOG_DEBUG, "%s%s: Relative symbol wants symbol@%u which is past end!\n",
+ XSPLICE, elf->name, symndx);
+ return -EINVAL;
+ }
+
+ dest = base->load_addr + r->r_offset;
+ val = r->r_addend + elf->sym[symndx].sym->st_value;
+
+ switch ( ELF64_R_TYPE(r->r_info) )
+ {
+ case R_X86_64_NONE:
+ break;
+
+ case R_X86_64_64:
+ *(uint64_t *)dest = val;
+ break;
+
+ case R_X86_64_PLT32:
+ /*
+ * Xen uses -fpic which normally uses PLT relocations
+ * except that it sets visibility to hidden which means
+ * that they are not used. However, when gcc cannot
+ * inline memcpy it emits memcpy with default visibility
+ * which then creates a PLT relocation. It can just be
+ * treated the same as R_X86_64_PC32.
+ */
+ /* Fall through */
+
+ case R_X86_64_PC32:
+ *(uint32_t *)dest = val - (uint64_t)dest;
+ break;
+
+ default:
+ printk(XENLOG_ERR "%s%s: Unhandled relocation %lu\n",
+ XSPLICE, elf->name, ELF64_R_TYPE(r->r_info));
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static find_space_t *find_space_fnc = NULL;
+
+void arch_xsplice_register_find_space(find_space_t *cb)
+{
+ ASSERT(!find_space_fnc);
+
+ find_space_fnc = cb;
+}
+
+static void* xsplice_map_rwx(const mfn_t *mfn, unsigned int pages)
+{
+ unsigned long cur;
+ unsigned long start, end;
+
+ start = (unsigned long)avail_virt_start;
+ end = start + pages * PAGE_SIZE;
+
+ ASSERT(find_space_fnc);
+
+ if ( find_space_fnc(pages, &start, &end) )
+ return NULL;
+
+ if ( end >= avail_virt_end )
+ return NULL;
+
+ for ( cur = start; pages--; ++mfn, cur += PAGE_SIZE )
+ {
+ /*
+ * We would like to to RX, but we need to copy data in it first.
+ * See arch_xsplice_secure for how we lockdown.
+ */
+ if ( map_pages_to_xen(cur, mfn_x(*mfn), 1, PAGE_HYPERVISOR_RWX) )
+ {
+ if ( cur != start )
+ destroy_xen_mappings(start, cur);
+ return NULL;
+ }
+ }
+
+ return (void*)start;
+}
+
+/*
+ * The function prepares an xSplice payload by allocating space which
+ * then can be used for loading the allocated sections, resolving symbols,
+ * performing relocations, etc.
+ */
+void *arch_xsplice_alloc_payload(unsigned int pages, mfn_t **mfn)
+{
+ unsigned int i;
+ void *p;
+
+ ASSERT(pages);
+ ASSERT(mfn && !*mfn);
+
+ *mfn = NULL;
+ /*
+ * We let the vmalloc allocate the pages we need, and use
+ * our callback. The callback must set the pages W otherwise we can't
+ * put anything in them.
+ */
+ p = vmalloc_cb(pages * PAGE_SIZE, xsplice_map_rwx, mfn);
+ WARN_ON(!p);
+ if ( !p )
+ return NULL;
+
+ for ( i = 0; i < pages; i++ )
+ clear_page(p + (i * PAGE_SIZE) );
+
+ /* Note that we do not free mfn. The caller is responsible for that. */
+ return p;
+}
+
+static void arch_xsplice_vfree_cb(void *va, unsigned int pages)
+{
+ unsigned long addr = (unsigned long)va;
+
+ destroy_xen_mappings(addr, addr + pages * PAGE_SIZE);
+}
+
+/*
+ * Once the resolving symbols, performing relocations, etc is complete
+ * we secure the memory by putting in the proper page table attributes
+ * for the desired type.
+ */
+int arch_xsplice_secure(void *va, unsigned int pages, enum va_type type,
+ const mfn_t *mfn)
+{
+ unsigned long cur;
+ unsigned long start = (unsigned long)va;
+ int flag;
+
+ ASSERT(va);
+ ASSERT(pages);
+
+ if ( type == XSPLICE_VA_RX )
+ flag = PAGE_HYPERVISOR_RX;
+ else if ( type == XSPLICE_VA_RW )
+ flag = PAGE_HYPERVISOR_RW;
+ else
+ flag = PAGE_HYPERVISOR_RO;
+
+ /*
+ * We could walk the pagetable and do the pagetable manipulations
+ * (strip the _PAGE_RW), which would mean also not needing the mfn
+ * array, but there are no generic code for this yet (TODO).
+ *
+ * For right now tear down the pagetables and recreate them.
+ */
+ arch_xsplice_vfree_cb(va, pages);
+
+ for ( cur = start; pages--; ++mfn, cur += PAGE_SIZE )
+ {
+ if ( map_pages_to_xen(cur, mfn_x(*mfn), 1, flag) )
+ {
+ if ( cur != start )
+ destroy_xen_mappings(start, cur);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+void arch_xsplice_free_payload(void *va, unsigned int pages)
+{
+ vfree_cb(va, pages, arch_xsplice_vfree_cb);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c
index 0047032..4d24898 100644
--- a/xen/common/xsplice.c
+++ b/xen/common/xsplice.c
@@ -13,6 +13,7 @@
#include <xen/smp.h>
#include <xen/spinlock.h>
#include <xen/vmap.h>
+#include <xen/xsplice_elf.h>
#include <xen/xsplice.h>
#include <asm/event.h>
@@ -28,6 +29,15 @@ struct payload {
uint32_t state; /* One of the XSPLICE_STATE_*. */
int32_t rc; /* 0 or -XEN_EXX. */
struct list_head list; /* Linked to 'payload_list'. */
+ void *text_addr; /* Virtual address of .text. */
+ size_t text_size; /* .. and its size. */
+ void *rw_addr; /* Virtual address of .data. */
+ size_t rw_size; /* .. and its size (if any). */
+ void *ro_addr; /* Virtual address of .rodata. */
+ size_t ro_size; /* .. and its size (if any). */
+ size_t payload_pages; /* Nr of the pages for the text_addr;
+ rw_addr, and ro_addr (if any) */
+ mfn_t *mfn; /* Array of MFNs of the pages. */
char name[XEN_XSPLICE_NAME_SIZE]; /* Name of it. */
};
@@ -99,6 +109,193 @@ static struct payload *find_payload(const xen_xsplice_name_t *name)
return found;
}
+/*
+ * Functions related to XEN_SYSCTL_XSPLICE_UPLOAD (see xsplice_upload), and
+ * freeing payload (XEN_SYSCTL_XSPLICE_ACTION:XSPLICE_ACTION_UNLOAD).
+ */
+
+static void free_payload_data(struct payload *payload)
+{
+ /* Set to zero until "move_payload". */
+ if ( !payload->text_addr )
+ return;
+
+ xfree(payload->mfn);
+ payload->mfn = NULL;
+
+ arch_xsplice_free_payload(payload->text_addr,
+ payload->payload_pages);
+
+ payload->text_addr = NULL;
+ payload->ro_addr = NULL;
+ payload->rw_addr = NULL;
+ payload->payload_pages = 0;
+}
+
+/*
+* calc_section computes the size (taking into account section alignment).
+*
+* It also modifies sh_entsize with the offset of from the start of
+* virtual address space. This is used in move_payload to figure out the
+* destination location.
+*/
+static void calc_section(struct xsplice_elf_sec *sec, size_t *size)
+{
+ size_t align_size = ROUNDUP(*size, sec->sec->sh_addralign);
+
+ sec->sec->sh_entsize = align_size;
+ *size = sec->sec->sh_size + align_size;
+}
+
+static int find_hole(size_t pages, unsigned long *hole_start,
+ unsigned long *hole_end)
+{
+ struct payload *data, *data2;
+
+ spin_lock_recursive(&payload_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->text_addr;
+ end = start + data2->payload_pages * PAGE_SIZE;
+ if ( *hole_end > start && *hole_start < end )
+ {
+ *hole_start = end;
+ *hole_end = end + pages * PAGE_SIZE;
+ break;
+ }
+ }
+ if ( &data2->list == &payload_list )
+ break;
+ }
+ spin_unlock_recursive(&payload_lock);
+
+ return 0;
+}
+
+static int move_payload(struct payload *payload, struct xsplice_elf *elf)
+{
+ uint8_t *buf;
+ unsigned int i;
+ size_t size = 0;
+
+ /* Compute text regions. */
+ for ( i = 0; i < elf->hdr->e_shnum; i++ )
+ {
+ if ( (elf->sec[i].sec->sh_flags & (SHF_ALLOC|SHF_EXECINSTR)) ==
+ (SHF_ALLOC|SHF_EXECINSTR) )
+ calc_section(&elf->sec[i], &payload->text_size);
+ }
+
+ /* Compute rw data. */
+ for ( i = 0; i < elf->hdr->e_shnum; i++ )
+ {
+ if ( (elf->sec[i].sec->sh_flags & SHF_ALLOC) &&
+ !(elf->sec[i].sec->sh_flags & SHF_EXECINSTR) &&
+ (elf->sec[i].sec->sh_flags & SHF_WRITE) )
+ calc_section(&elf->sec[i], &payload->rw_size);
+ }
+
+ /* Compute ro data. */
+ for ( i = 0; i < elf->hdr->e_shnum; i++ )
+ {
+ if ( (elf->sec[i].sec->sh_flags & SHF_ALLOC) &&
+ !(elf->sec[i].sec->sh_flags & SHF_EXECINSTR) &&
+ !(elf->sec[i].sec->sh_flags & SHF_WRITE) )
+ calc_section(&elf->sec[i], &payload->ro_size);
+ }
+
+ /*
+ * Total of all three regions - RX, RW, and RO. We have to have
+ * keep them in seperate pages so we PAGE_ALIGN the RX and RW to have
+ * them on seperate pages. The last one will by default fall on its
+ * own page.
+ */
+ size = PAGE_ALIGN(payload->text_size) + PAGE_ALIGN(payload->rw_size) +
+ payload->ro_size;
+
+ size = PFN_UP(size);
+ buf = arch_xsplice_alloc_payload(size, &payload->mfn);
+ if ( !buf ) {
+ printk(XENLOG_ERR "%s%s: Could not allocate memory for payload!\n",
+ XSPLICE, elf->name);
+ return -ENOMEM;
+ }
+
+ payload->payload_pages = size;
+ payload->text_addr = buf;
+ payload->rw_addr = payload->text_addr + PAGE_ALIGN(payload->text_size);
+ payload->ro_addr = payload->rw_addr + PAGE_ALIGN(payload->rw_size);
+
+ for ( i = 0; i < elf->hdr->e_shnum; i++ )
+ {
+ if ( elf->sec[i].sec->sh_flags & SHF_ALLOC )
+ {
+ if ( (elf->sec[i].sec->sh_flags & SHF_EXECINSTR) )
+ buf = payload->text_addr;
+ else if ( (elf->sec[i].sec->sh_flags & SHF_WRITE) )
+ buf = payload->rw_addr;
+ else
+ buf = payload->ro_addr;
+
+ elf->sec[i].load_addr = buf + elf->sec[i].sec->sh_entsize;
+
+ /* Don't copy NOBITS - such as BSS. */
+ if ( elf->sec[i].sec->sh_type != SHT_NOBITS )
+ {
+ memcpy(elf->sec[i].load_addr, elf->sec[i].data,
+ elf->sec[i].sec->sh_size);
+ dprintk(XENLOG_DEBUG, "%s%s: Loaded %s at 0x%p\n", XSPLICE,
+ elf->name, elf->sec[i].name, elf->sec[i].load_addr);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int secure_payload(struct payload *payload, struct xsplice_elf *elf)
+{
+ int rc;
+ unsigned int text_pages, rw_pages, ro_pages;
+
+ ASSERT(payload->mfn);
+
+ text_pages = PFN_UP(payload->text_size);
+ ASSERT(text_pages);
+
+ rc = arch_xsplice_secure(payload->text_addr, text_pages, XSPLICE_VA_RX,
+ payload->mfn);
+ if ( rc )
+ return rc;
+
+ rw_pages = PFN_UP(payload->rw_size);
+ if ( rw_pages )
+ {
+ rc = arch_xsplice_secure(payload->rw_addr, rw_pages, XSPLICE_VA_RW,
+ payload->mfn + text_pages);
+ if ( rc )
+ return rc;
+ }
+
+ ro_pages = PFN_UP(payload->ro_size);
+ if ( ro_pages )
+ {
+ rc = arch_xsplice_secure(payload->ro_addr, ro_pages, XSPLICE_VA_RO,
+ payload->mfn + text_pages + rw_pages);
+ }
+
+ ASSERT(ro_pages + rw_pages + text_pages == payload->payload_pages);
+
+ xfree(payload->mfn);
+ payload->mfn = NULL;
+
+ return rc;
+}
+
/* We MUST be holding the payload_lock spinlock. */
static void free_payload(struct payload *data)
{
@@ -106,12 +303,55 @@ static void free_payload(struct payload *data)
list_del(&data->list);
payload_cnt--;
payload_version++;
+ free_payload_data(data);
xfree(data);
}
+static int load_payload_data(struct payload *payload, void *raw, ssize_t len)
+{
+ struct xsplice_elf elf;
+ int rc = 0;
+
+ memset(&elf, 0, sizeof(elf));
+ elf.name = payload->name;
+ elf.len = len;
+
+ rc = arch_xsplice_verify_elf(&elf, raw);
+ if ( rc )
+ return rc;
+
+ rc = xsplice_elf_load(&elf, raw);
+ if ( rc )
+ goto out;
+
+ rc = move_payload(payload, &elf);
+ if ( rc )
+ goto out;
+
+ rc = xsplice_elf_resolve_symbols(&elf);
+ if ( rc )
+ goto out;
+
+ rc = xsplice_elf_perform_relocs(&elf);
+ if ( rc )
+ goto out;
+
+ rc = secure_payload(payload, &elf);
+
+ out:
+ if ( rc )
+ free_payload_data(payload);
+
+ /* Free our temporary data structure. */
+ xsplice_elf_free(&elf);
+
+ return rc;
+}
+
static int xsplice_upload(xen_sysctl_xsplice_upload_t *upload)
{
struct payload *data;
+ void *raw_data = NULL;
int rc;
rc = verify_payload(upload);
@@ -137,7 +377,19 @@ static int xsplice_upload(xen_sysctl_xsplice_upload_t *upload)
if ( data->name[upload->name.size - 1] )
goto out;
- rc = 0;
+ rc = -ENOMEM;
+ raw_data = vmalloc(upload->size);
+ if ( !raw_data )
+ goto out;
+
+ rc = -EFAULT;
+ if ( __copy_from_guest(raw_data, upload->payload, upload->size) )
+ goto out;
+
+ rc = load_payload_data(data, raw_data, upload->size);
+ if ( rc )
+ goto out;
+
data->state = XSPLICE_STATE_CHECKED;
INIT_LIST_HEAD(&data->list);
@@ -148,6 +400,7 @@ static int xsplice_upload(xen_sysctl_xsplice_upload_t *upload)
spin_unlock_recursive(&payload_lock);
out:
+ vfree(raw_data);
if ( rc )
xfree(data);
@@ -382,8 +635,9 @@ static void xsplice_printall(unsigned char key)
}
list_for_each_entry ( data, &payload_list, list )
- printk(" name=%s state=%s(%d)\n", data->name,
- state2str(data->state), data->state);
+ printk(" name=%s state=%s(%d) %p (.data=%p, .rodata=%p) using %zu pages.\n",
+ data->name, state2str(data->state), data->state, data->text_addr,
+ data->rw_addr, data->ro_addr, data->payload_pages);
spin_unlock_recursive(&payload_lock);
}
@@ -391,6 +645,8 @@ static void xsplice_printall(unsigned char key)
static int __init xsplice_init(void)
{
register_keyhandler('x', xsplice_printall, "print xsplicing info", 1);
+
+ arch_xsplice_register_find_space(&find_hole);
return 0;
}
__initcall(xsplice_init);
diff --git a/xen/common/xsplice_elf.c b/xen/common/xsplice_elf.c
index f22cede..e5c0b12 100644
--- a/xen/common/xsplice_elf.c
+++ b/xen/common/xsplice_elf.c
@@ -213,6 +213,97 @@ static int elf_get_sym(struct xsplice_elf *elf, const void *data)
return 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++ )
+ {
+ uint16_t idx = elf->sym[i].sym->st_shndx;
+
+ switch ( idx )
+ {
+ case SHN_COMMON:
+ printk(XENLOG_ERR "%s%s: Unexpected common symbol: %s\n",
+ XSPLICE, elf->name, elf->sym[i].name);
+ return -EINVAL;
+ break;
+
+ case SHN_UNDEF:
+ printk(XENLOG_ERR "%s%s: Unknown symbol: %s\n",
+ XSPLICE, elf->name, elf->sym[i].name);
+ return -ENOENT;
+ break;
+
+ case SHN_ABS:
+ dprintk(XENLOG_DEBUG, "%s%s: Absolute symbol: %s => 0x%"PRIx64"\n",
+ XSPLICE, elf->name, elf->sym[i].name,
+ elf->sym[i].sym->st_value);
+ break;
+
+ default:
+ if ( elf->sec[idx].sec->sh_flags & SHF_ALLOC )
+ {
+ elf->sym[i].sym->st_value +=
+ (unsigned long)elf->sec[idx].load_addr;
+ if ( elf->sym[i].name )
+ printk(XENLOG_DEBUG "%s%s: Symbol resolved: %s => 0x%"PRIx64"(%s)\n",
+ XSPLICE, elf->name, elf->sym[i].name,
+ (uint64_t)elf->sym[i].sym->st_value,
+ elf->sec[idx].name);
+ }
+ }
+ }
+
+ 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 = arch_xsplice_perform_rela(elf, base, rela);
+ else /* SHT_REL */
+ rc = arch_xsplice_perform_rel(elf, base, rela);
+
+ if ( rc )
+ return rc;
+ }
+
+ return 0;
+}
+
static int xsplice_header_check(const struct xsplice_elf *elf)
{
if ( sizeof(*elf->hdr) >= elf->len )
diff --git a/xen/include/asm-x86/x86_64/page.h b/xen/include/asm-x86/x86_64/page.h
index 86abb94..a854e05 100644
--- a/xen/include/asm-x86/x86_64/page.h
+++ b/xen/include/asm-x86/x86_64/page.h
@@ -38,6 +38,8 @@
#include <xen/pdx.h>
extern unsigned long xen_virt_end;
+extern unsigned long avail_virt_start;
+extern unsigned long avail_virt_end;
#define spage_to_pdx(spg) (((spg) - spage_table)<<(SUPERPAGE_SHIFT-PAGE_SHIFT))
#define pdx_to_spage(pdx) (spage_table + ((pdx)>>(SUPERPAGE_SHIFT-PAGE_SHIFT)))
diff --git a/xen/include/xen/xsplice.h b/xen/include/xen/xsplice.h
index 00482d0..74850ea 100644
--- a/xen/include/xen/xsplice.h
+++ b/xen/include/xen/xsplice.h
@@ -6,6 +6,9 @@
#ifndef __XEN_XSPLICE_H__
#define __XEN_XSPLICE_H__
+struct xsplice_elf;
+struct xsplice_elf_sec;
+struct xsplice_elf_sym;
struct xen_sysctl_xsplice_op;
#ifdef CONFIG_XSPLICE
@@ -15,6 +18,49 @@ struct xen_sysctl_xsplice_op;
int xsplice_op(struct xen_sysctl_xsplice_op *);
+/* Arch hooks. */
+int arch_xsplice_verify_elf(const struct xsplice_elf *elf, void *data);
+int arch_xsplice_perform_rel(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela);
+int arch_xsplice_perform_rela(struct xsplice_elf *elf,
+ const struct xsplice_elf_sec *base,
+ const struct xsplice_elf_sec *rela);
+enum va_type {
+ XSPLICE_VA_RX, /* .text */
+ XSPLICE_VA_RW, /* .data */
+ XSPLICE_VA_RO, /* .rodata */
+};
+
+#include <xen/mm.h>
+void *arch_xsplice_alloc_payload(unsigned int pages, mfn_t **mfn);
+
+/*
+ * Function to secure the allocate pages (from arch_xsplice_alloc_payload)
+ * with the right page permissions.
+ */
+int arch_xsplice_secure(void *va, unsigned int pages, enum va_type types,
+ const mfn_t *mfn);
+
+void arch_xsplice_free_payload(void *va, unsigned int pages);
+
+/*
+ * Callback to find available virtual address space in which the
+ * payload could be put in.
+ *
+ * The arguments are:
+ * - The size of the payload in bytes.
+ * - The starting virtual address to search. To be updated by
+ * callback if space found.
+ * - The ending virtual address to search. To be updated by
+ * callback if space found.
+ *
+ * The return value is zero if search was done. -EXX values
+ * if errors were encountered.
+ */
+typedef int (find_space_t)(size_t, unsigned long *, unsigned long *);
+void arch_xsplice_register_find_space(find_space_t *cb);
+
#else
#include <xen/errno.h> /* For -EOPNOTSUPP */
diff --git a/xen/include/xen/xsplice_elf.h b/xen/include/xen/xsplice_elf.h
index e2dea18..f6ffcbe 100644
--- a/xen/include/xen/xsplice_elf.h
+++ b/xen/include/xen/xsplice_elf.h
@@ -15,6 +15,8 @@ struct xsplice_elf_sec {
elf_resolve_section_names. */
const void *data; /* Pointer to the section (done by
elf_resolve_sections). */
+ uint8_t *load_addr; /* A pointer to the allocated destination.
+ Done by load_payload_data. */
};
struct xsplice_elf_sym {
@@ -38,6 +40,9 @@ struct xsplice_elf_sec *xsplice_elf_sec_by_name(const struct xsplice_elf *elf,
int xsplice_elf_load(struct xsplice_elf *elf, void *data);
void xsplice_elf_free(struct xsplice_elf *elf);
+int xsplice_elf_resolve_symbols(struct xsplice_elf *elf);
+int xsplice_elf_perform_relocs(struct xsplice_elf *elf);
+
#endif /* __XEN_XSPLICE_ELF_H__ */
/*
--
2.5.0
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2016-03-24 20:01 UTC|newest]
Thread overview: 190+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-24 20:00 [PATCH v5] xSplice v1 design and implementation Konrad Rzeszutek Wilk
2016-03-24 20:00 ` [PATCH v5 01/28] HYPERCALL_version_op. New hypercall mirroring XENVER_ but sane Konrad Rzeszutek Wilk
2016-03-24 20:22 ` Andrew Cooper
2016-03-24 21:07 ` Konrad Rzeszutek Wilk
2016-03-24 21:30 ` Konrad Rzeszutek Wilk
2016-03-30 15:43 ` Jan Beulich
2016-03-31 6:30 ` Jan Beulich
2016-03-31 11:43 ` Konrad Rzeszutek Wilk
2016-03-31 12:07 ` Jan Beulich
2016-03-31 13:28 ` REST MAINTAINERS feedback requested Was:Re: " Konrad Rzeszutek Wilk
2016-03-31 13:50 ` Jan Beulich
2016-04-08 16:33 ` Jan Beulich
2016-04-08 17:09 ` Konrad Rzeszutek Wilk
2016-04-08 17:13 ` Jan Beulich
2016-04-08 17:21 ` Wei Liu
2016-04-08 17:23 ` Konrad Rzeszutek Wilk
2016-04-08 17:27 ` Wei Liu
2016-04-08 17:21 ` Ian Jackson
2016-04-08 17:41 ` Andrew Cooper
2016-04-08 17:54 ` Jan Beulich
2016-04-11 10:50 ` Ian Jackson
2016-04-11 13:56 ` Konrad Rzeszutek Wilk
2016-04-11 14:22 ` Ian Jackson
2016-04-11 15:48 ` Jan Beulich
2016-04-11 16:25 ` Ian Jackson
2016-04-11 16:53 ` Konrad Rzeszutek Wilk
2016-04-11 17:06 ` Jan Beulich
2016-04-11 17:00 ` Jan Beulich
2016-04-11 17:13 ` Ian Jackson
2016-04-11 17:34 ` Jan Beulich
2016-04-11 17:46 ` Jan Beulich
2016-04-12 9:58 ` George Dunlap
2016-04-12 13:56 ` Konrad Rzeszutek Wilk
2016-04-12 14:38 ` George Dunlap
2016-04-12 15:00 ` Konrad Rzeszutek Wilk
2016-04-12 15:26 ` Ian Jackson
2016-04-13 4:21 ` Jan Beulich
2016-04-13 16:07 ` Ian Jackson
2016-04-14 15:13 ` George Dunlap
2016-04-14 15:59 ` Jan Beulich
2016-04-14 16:19 ` George Dunlap
2016-04-14 17:01 ` Jan Beulich
2016-04-14 18:11 ` REST MAINTAINERS feedback requested Was:Re: [PATCH v5 01/28] HYPERCALL_version_op. New hypercall mirroring XENVER_ but sane. [and 1 more messages] Ian Jackson
2016-04-14 19:22 ` Konrad Rzeszutek Wilk
2016-04-17 7:23 ` Jan Beulich
2016-04-15 11:23 ` REST MAINTAINERS feedback requested Was:Re: [PATCH v5 01/28] HYPERCALL_version_op. New hypercall mirroring XENVER_ but sane George Dunlap
2016-04-17 7:52 ` Jan Beulich
2016-04-12 15:31 ` Jan Beulich
2016-04-12 15:17 ` Jan Beulich
2016-04-12 15:28 ` Konrad Rzeszutek Wilk
2016-04-08 17:24 ` George Dunlap
2016-04-08 17:34 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 02/28] libxc/libxl/python/xenstat/ocaml: Use new XEN_VERSION hypercall Konrad Rzeszutek Wilk
2016-03-24 21:24 ` Wei Liu
2016-03-25 13:21 ` Konrad Rzeszutek Wilk
2016-03-24 20:00 ` [PATCH v5 03/28] arm/x86: Use struct virtual_region to do bug, symbol, and (x86) exception tables lookup Konrad Rzeszutek Wilk
2016-03-30 16:09 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 04/28] vmap: Add vmalloc_cb and vfree_cb Konrad Rzeszutek Wilk
2016-03-30 16:24 ` Jan Beulich
2016-03-30 16:44 ` Konrad Rzeszutek Wilk
2016-03-31 6:46 ` Jan Beulich
2016-03-31 11:49 ` Konrad Rzeszutek Wilk
2016-03-24 20:00 ` [PATCH v5 05/28] xsplice: Design document Konrad Rzeszutek Wilk
2016-03-29 9:36 ` Jan Beulich
2016-03-29 20:46 ` Konrad Rzeszutek Wilk
2016-03-24 20:00 ` [PATCH v5 06/28] xen/xsplice: Hypervisor implementation of XEN_XSPLICE_op Konrad Rzeszutek Wilk
2016-03-31 9:45 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 07/28] libxc: Implementation of XEN_XSPLICE_op in libxc Konrad Rzeszutek Wilk
2016-03-24 20:00 ` [PATCH v5 08/28] xen-xsplice: Tool to manipulate xsplice payloads Konrad Rzeszutek Wilk
2016-03-24 20:00 ` [PATCH v5 09/28] xsplice: Add helper elf routines Konrad Rzeszutek Wilk
2016-03-31 12:03 ` Jan Beulich
2016-04-06 1:38 ` Konrad Rzeszutek Wilk
2016-04-07 0:38 ` Jan Beulich
2016-03-24 20:00 ` Konrad Rzeszutek Wilk [this message]
2016-03-31 13:45 ` [PATCH v5 10/28] xsplice: Implement payload loading Jan Beulich
2016-03-31 21:26 ` Konrad Rzeszutek Wilk
2016-04-01 9:18 ` Jan Beulich
2016-04-04 19:44 ` Konrad Rzeszutek Wilk
2016-04-05 1:57 ` Konrad Rzeszutek Wilk
2016-04-05 7:34 ` Jan Beulich
2016-04-05 15:50 ` Konrad Rzeszutek Wilk
2016-04-05 16:15 ` Jan Beulich
2016-04-05 16:45 ` Konrad Rzeszutek Wilk
2016-04-05 17:48 ` Konrad Rzeszutek Wilk
2016-04-07 0:49 ` Jan Beulich
2016-04-07 0:46 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 11/28] xsplice: Implement support for applying/reverting/replacing patches Konrad Rzeszutek Wilk
2016-04-01 13:28 ` Jan Beulich
2016-04-01 21:04 ` Konrad Rzeszutek Wilk
2016-04-04 7:07 ` Jan Beulich
2016-04-07 3:05 ` Konrad Rzeszutek Wilk
2016-04-07 15:38 ` Jan Beulich
2016-04-09 14:42 ` Konrad Rzeszutek Wilk
2016-04-11 15:38 ` Jan Beulich
2016-04-07 3:09 ` Konrad Rzeszutek Wilk
2016-04-07 15:43 ` Jan Beulich
2016-04-10 2:36 ` Konrad Rzeszutek Wilk
2016-04-10 2:45 ` Konrad Rzeszutek Wilk
2016-04-11 15:41 ` Jan Beulich
2016-04-11 23:29 ` Konrad Rzeszutek Wilk
2016-04-10 19:47 ` Is: ARM maintainers advice ..Was:Re: " Konrad Rzeszutek Wilk
2016-04-10 20:58 ` Stefano Stabellini
2016-04-11 15:44 ` Jan Beulich
2016-04-11 15:50 ` Konrad Rzeszutek Wilk
2016-04-11 16:05 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 12/28] x86/xen_hello_world.xsplice: Test payload for patching 'xen_extra_version' Konrad Rzeszutek Wilk
2016-04-01 13:33 ` Jan Beulich
2016-04-06 2:03 ` Konrad Rzeszutek Wilk
2016-04-07 1:03 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 13/28] xsplice, symbols: Implement symbol name resolution on address Konrad Rzeszutek Wilk
2016-04-01 15:11 ` Jan Beulich
2016-04-07 3:14 ` Konrad Rzeszutek Wilk
2016-04-07 15:46 ` Jan Beulich
2016-04-08 1:32 ` Konrad Rzeszutek Wilk
2016-04-08 15:21 ` Jan Beulich
2016-04-08 15:27 ` Konrad Rzeszutek Wilk
2016-04-08 15:29 ` Jan Beulich
[not found] ` <5707D68A.8090006@citrix.com>
[not found] ` <5707FA8B02000078000E6178@prv-mh.provo.novell.com>
2016-04-11 8:07 ` Ross Lagerwall
2016-03-24 20:00 ` [PATCH v5 14/28] x86, xsplice: Print payload's symbol name and payload name in backtraces Konrad Rzeszutek Wilk
2016-04-01 15:23 ` Jan Beulich
2016-04-06 2:39 ` Konrad Rzeszutek Wilk
2016-04-07 1:07 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 15/28] xsplice: Add .xsplice.hooks functions and test-case Konrad Rzeszutek Wilk
2016-04-01 15:50 ` Jan Beulich
2016-04-06 2:42 ` Konrad Rzeszutek Wilk
2016-04-06 6:39 ` Martin Pohlack
2016-04-07 1:15 ` Jan Beulich
2016-04-08 15:57 ` Ross Lagerwall
2016-04-08 17:39 ` Jan Beulich
2016-04-11 8:23 ` Ross Lagerwall
2016-04-22 13:33 ` Jan Beulich
2016-04-22 13:58 ` Jan Beulich
2016-04-22 17:32 ` Konrad Rzeszutek Wilk
2016-04-07 1:11 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 16/28] xsplice: Add support for bug frames Konrad Rzeszutek Wilk
2016-04-01 16:00 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 17/28] xsplice: Add support for exception tables Konrad Rzeszutek Wilk
2016-04-01 16:06 ` Jan Beulich
2016-04-06 14:41 ` Konrad Rzeszutek Wilk
2016-04-06 15:32 ` Andrew Cooper
2016-04-07 1:21 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 18/28] xsplice: Add support for alternatives Konrad Rzeszutek Wilk
2016-04-01 16:20 ` Jan Beulich
2016-04-07 3:11 ` Konrad Rzeszutek Wilk
2016-03-24 20:00 ` [PATCH v5 19/28] build_id: Provide ld-embedded build-ids Konrad Rzeszutek Wilk
2016-04-04 12:46 ` Jan Beulich
2016-04-07 2:58 ` Konrad Rzeszutek Wilk
2016-04-08 15:49 ` Ross Lagerwall
2016-04-08 18:47 ` Konrad Rzeszutek Wilk
2016-04-08 18:54 ` Andrew Cooper
2016-04-08 19:54 ` Jan Beulich
2016-04-08 0:18 ` Konrad Rzeszutek Wilk
2016-04-08 1:52 ` Konrad Rzeszutek Wilk
2016-04-08 15:27 ` Jan Beulich
2016-04-08 17:06 ` Konrad Rzeszutek Wilk
2016-04-08 17:44 ` Jan Beulich
2016-04-08 19:23 ` Konrad Rzeszutek Wilk
2016-04-08 19:39 ` Konrad Rzeszutek Wilk
2016-04-08 20:14 ` Jan Beulich
2016-04-08 20:50 ` Konrad Rzeszutek Wilk
2016-04-08 21:11 ` Jan Beulich
2016-04-08 21:15 ` Konrad Rzeszutek Wilk
2016-04-08 15:25 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 20/28] HYPERCALL_version_op: Add VERSION_build_id to retrieve build-id Konrad Rzeszutek Wilk
2016-03-25 16:26 ` Daniel De Graaf
2016-04-04 13:35 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 21/28] libxl: info: Display build_id of the hypervisor using XEN_VERSION_build_id Konrad Rzeszutek Wilk
2016-03-25 13:25 ` Konrad Rzeszutek Wilk
2016-03-25 15:27 ` Wei Liu
2016-03-24 20:00 ` [PATCH v5 22/28] xsplice: Print build_id in keyhandler and on bootup Konrad Rzeszutek Wilk
2016-04-04 13:38 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 23/28] xsplice: Stacking build-id dependency checking Konrad Rzeszutek Wilk
2016-04-04 15:00 ` Jan Beulich
2016-04-04 20:01 ` Konrad Rzeszutek Wilk
2016-04-05 7:43 ` Jan Beulich
2016-04-08 16:15 ` Ross Lagerwall
2016-04-08 17:47 ` Jan Beulich
2016-04-06 20:05 ` Konrad Rzeszutek Wilk
2016-04-07 1:24 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 24/28] xsplice/xen_replace_world: Test-case for XSPLICE_ACTION_REPLACE Konrad Rzeszutek Wilk
2016-03-24 20:00 ` [PATCH v5 25/28] xsplice: Print dependency and payloads build_id in the keyhandler Konrad Rzeszutek Wilk
2016-04-04 15:03 ` Jan Beulich
2016-03-24 20:00 ` [PATCH v5 26/28] xsplice: Prevent duplicate payloads from being loaded Konrad Rzeszutek Wilk
2016-04-04 15:06 ` Jan Beulich
2016-04-04 19:52 ` Konrad Rzeszutek Wilk
2016-03-24 20:00 ` [PATCH v5 27/28] xsplice: Add support for shadow variables Konrad Rzeszutek Wilk
2016-04-04 15:18 ` Jan Beulich
2016-04-06 2:26 ` Konrad Rzeszutek Wilk
2016-04-08 15:58 ` Ross Lagerwall
2016-03-24 20:00 ` [PATCH v5 28/28] MAINTAINERS/xsplice: Add myself and Ross as the maintainers Konrad Rzeszutek Wilk
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1458849640-22588-11-git-send-email-konrad.wilk@oracle.com \
--to=konrad.wilk@oracle.com \
--cc=andrew.cooper3@citrix.com \
--cc=jbeulich@suse.com \
--cc=julien.grall@arm.com \
--cc=keir@xen.org \
--cc=konrad@kernel.org \
--cc=mpohlack@amazon.de \
--cc=ross.lagerwall@citrix.com \
--cc=sasha.levin@oracle.com \
--cc=stefano.stabellini@citrix.com \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).