All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Daniel P. Smith" <dpsmith@apertussolutions.com>
To: xen-devel@lists.xenproject.org, Wei Liu <wl@xen.org>
Cc: "Daniel P. Smith" <dpsmith@apertussolutions.com>,
	scott.davis@starlab.io, christopher.clark@starlab.io,
	"Jan Beulich" <jbeulich@suse.com>,
	"Andrew Cooper" <andrew.cooper3@citrix.com>,
	"Roger Pau Monné" <roger.pau@citrix.com>,
	"George Dunlap" <george.dunlap@citrix.com>,
	"Julien Grall" <julien@xen.org>,
	"Stefano Stabellini" <sstabellini@kernel.org>
Subject: [PATCH v1 10/18] x86: introduce the domain builder
Date: Wed,  6 Jul 2022 17:04:45 -0400	[thread overview]
Message-ID: <20220706210454.30096-11-dpsmith@apertussolutions.com> (raw)
In-Reply-To: <20220706210454.30096-1-dpsmith@apertussolutions.com>

This commit introduces the domain builder configuration FDT parser along with
the domain builder core for domain creation. To enable domain builder to be a
cross architecture internal API, a new arch domain creation call is introduced
for use by the domain builder.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Reviewed-by: Christopher Clark <christopher.clark@starlab.io>
---
 xen/arch/x86/setup.c               |   9 +
 xen/common/Makefile                |   1 +
 xen/common/domain-builder/Makefile |   2 +
 xen/common/domain-builder/core.c   |  96 ++++++++++
 xen/common/domain-builder/fdt.c    | 295 +++++++++++++++++++++++++++++
 xen/common/domain-builder/fdt.h    |   7 +
 xen/include/xen/bootinfo.h         |  16 ++
 xen/include/xen/domain_builder.h   |   1 +
 8 files changed, 427 insertions(+)
 create mode 100644 xen/common/domain-builder/Makefile
 create mode 100644 xen/common/domain-builder/core.c
 create mode 100644 xen/common/domain-builder/fdt.c
 create mode 100644 xen/common/domain-builder/fdt.h

diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index e4060d6219..28dbfcd209 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1,4 +1,6 @@
+#include <xen/bootdomain.h>
 #include <xen/bootinfo.h>
+#include <xen/domain_builder.h>
 #include <xen/init.h>
 #include <xen/lib.h>
 #include <xen/err.h>
@@ -826,6 +828,13 @@ static struct domain *__init create_dom0(const struct boot_info *bi)
     return d;
 }
 
+void __init arch_create_dom(
+    const struct boot_info *bi, struct boot_domain *bd)
+{
+    if ( builder_is_initdom(bd) )
+        create_dom0(bi);
+}
+
 /* How much of the directmap is prebuilt at compile time. */
 #define PREBUILT_MAP_LIMIT (1 << L2_PAGETABLE_SHIFT)
 
diff --git a/xen/common/Makefile b/xen/common/Makefile
index ebd3e2d659..eb108fa107 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -72,6 +72,7 @@ extra-y := symbols-dummy.o
 obj-$(CONFIG_COVERAGE) += coverage/
 obj-y += sched/
 obj-$(CONFIG_UBSAN) += ubsan/
+obj-y += domain-builder/
 
 obj-$(CONFIG_NEEDS_LIBELF) += libelf/
 obj-$(CONFIG_CORE_DEVICE_TREE) += libfdt/
diff --git a/xen/common/domain-builder/Makefile b/xen/common/domain-builder/Makefile
new file mode 100644
index 0000000000..9561602502
--- /dev/null
+++ b/xen/common/domain-builder/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_BUILDER_FDT) += fdt.o
+obj-y += core.o
diff --git a/xen/common/domain-builder/core.c b/xen/common/domain-builder/core.c
new file mode 100644
index 0000000000..b030b07d71
--- /dev/null
+++ b/xen/common/domain-builder/core.c
@@ -0,0 +1,96 @@
+#include <xen/bootdomain.h>
+#include <xen/bootinfo.h>
+#include <xen/domain_builder.h>
+#include <xen/init.h>
+#include <xen/types.h>
+
+#include <asm/bzimage.h>
+#include <asm/setup.h>
+
+#include "fdt.h"
+
+static struct domain_builder __initdata builder;
+
+void __init builder_init(struct boot_info *info)
+{
+    struct boot_domain *d = NULL;
+
+    info->builder = &builder;
+
+    if ( IS_ENABLED(CONFIG_BUILDER_FDT) )
+    {
+        /* fdt is required to be module 0 */
+        switch ( check_fdt(info, __va(info->mods[0].start)) )
+        {
+        case 0:
+            printk("Domain Builder: initialized from config\n");
+            info->builder->fdt_enabled = true;
+            return;
+        case -EINVAL:
+            info->builder->fdt_enabled = false;
+            break;
+        case -ENODATA:
+        default:
+            panic("%s: error occured processing DTB\n", __func__);
+        }
+    }
+
+    /*
+     * No FDT config support or an FDT wasn't present, do an initial
+     * domain construction
+     */
+    printk("Domain Builder: falling back to initial domain build\n");
+    info->builder->nr_doms = 1;
+    d = &info->builder->domains[0];
+
+    d->mode = opt_dom0_pvh ? 0 : BUILD_MODE_PARAVIRTUALIZED;
+
+    d->kernel = &info->mods[0];
+    d->kernel->kind = BOOTMOD_KERNEL;
+
+    d->permissions = BUILD_PERMISSION_CONTROL | BUILD_PERMISSION_HARDWARE;
+    d->functions = BUILD_FUNCTION_CONSOLE | BUILD_FUNCTION_XENSTORE |
+                     BUILD_FUNCTION_INITIAL_DOM;
+
+    d->kernel->arch->headroom = bzimage_headroom(bootstrap_map(d->kernel),
+                                                   d->kernel->size);
+    bootstrap_map(NULL);
+
+    if ( d->kernel->string.len )
+        d->kernel->string.kind = BOOTSTR_CMDLINE;
+}
+
+uint32_t __init builder_create_domains(struct boot_info *info)
+{
+    uint32_t build_count = 0, functions_built = 0;
+    int i;
+
+    for ( i = 0; i < info->builder->nr_doms; i++ )
+    {
+        struct boot_domain *d = &info->builder->domains[i];
+
+        if ( ! IS_ENABLED(CONFIG_MULTIDOM_BUILDER) &&
+             ! builder_is_initdom(d) &&
+             functions_built & BUILD_FUNCTION_INITIAL_DOM )
+            continue;
+
+        if ( d->kernel == NULL )
+        {
+            if ( builder_is_initdom(d) )
+                panic("%s: intial domain missing kernel\n", __func__);
+
+            printk(XENLOG_ERR "%s:Dom%d definiton has no kernel\n", __func__,
+                    d->domid);
+            continue;
+        }
+
+        arch_create_dom(info, d);
+        if ( d->domain )
+        {
+            functions_built |= d->functions;
+            build_count++;
+        }
+    }
+
+    return build_count;
+}
diff --git a/xen/common/domain-builder/fdt.c b/xen/common/domain-builder/fdt.c
new file mode 100644
index 0000000000..937cc61e7a
--- /dev/null
+++ b/xen/common/domain-builder/fdt.c
@@ -0,0 +1,295 @@
+#include <xen/bootdomain.h>
+#include <xen/bootinfo.h>
+#include <xen/domain_builder.h>
+#include <xen/fdt.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/libfdt/libfdt.h>
+#include <xen/page-size.h>
+#include <xen/pfn.h>
+#include <xen/types.h>
+
+#include <asm/bzimage.h>
+#include <asm/setup.h>
+
+#include "fdt.h"
+
+#define BUILDER_FDT_TARGET_UNK 0
+#define BUILDER_FDT_TARGET_X86 1
+#define BUILDER_FDT_TARGET_ARM 2
+static int __initdata target_arch = BUILDER_FDT_TARGET_UNK;
+
+static struct boot_module *read_module(
+    const void *fdt, int node, uint32_t address_cells, uint32_t size_cells,
+    struct boot_info *info)
+{
+    const struct fdt_property *prop;
+    const __be32 *cell;
+    struct boot_module *bm;
+    bootmodule_kind kind = BOOTMOD_UNKNOWN;
+    int len;
+
+    if ( device_tree_node_compatible(fdt, node, "module,kernel") )
+        kind = BOOTMOD_KERNEL;
+
+    if ( device_tree_node_compatible(fdt, node, "module,ramdisk") )
+        kind = BOOTMOD_RAMDISK;
+
+    if ( device_tree_node_compatible(fdt, node, "module,microcode") )
+        kind = BOOTMOD_UCODE;
+
+    if ( device_tree_node_compatible(fdt, node, "module,xsm-policy") )
+        kind = BOOTMOD_XSM;
+
+    if ( device_tree_node_compatible(fdt, node, "module,config") )
+        kind = BOOTMOD_GUEST_CONF;
+
+    if ( device_tree_node_compatible(fdt, node, "module,index") )
+    {
+        uint32_t idx;
+
+        idx = (uint32_t)device_tree_get_u32(fdt, node, "module-index", 0);
+        if ( idx == 0 )
+            return NULL;
+
+        bm = &info->mods[idx];
+
+        bm->kind = kind;
+
+        return bm;
+    }
+
+    if ( device_tree_node_compatible(fdt, node, "module,addr") )
+    {
+        uint64_t addr, size;
+
+        prop = fdt_get_property(fdt, node, "module-addr", &len);
+        if ( !prop )
+            return NULL;
+
+        if ( len < dt_cells_to_size(address_cells + size_cells) )
+            return NULL;
+
+        cell = (const __be32 *)prop->data;
+        device_tree_get_reg(
+            &cell, address_cells, size_cells, &addr, &size);
+
+        bm = bootmodule_next_by_addr(info, addr, NULL);
+
+        bm->kind = kind;
+
+        return bm;
+    }
+
+    printk(XENLOG_WARNING
+           "builder fdt: module node %d, no index or addr provided\n",
+           node);
+
+    return NULL;
+}
+
+static int process_config_node(
+    const void *fdt, int node, const char *name, int depth,
+    uint32_t address_cells, uint32_t size_cells, void *data)
+{
+    struct boot_info *info = (struct boot_info *)data;
+    int node_next;
+
+    if ( !info )
+        return -1;
+
+    for ( node_next = fdt_first_subnode(fdt, node);
+          node_next > 0;
+          node_next = fdt_next_subnode(fdt, node_next))
+        read_module(fdt, node_next, address_cells, size_cells, info);
+
+    return 0;
+}
+
+static int process_domain_node(
+    const void *fdt, int node, const char *name, int depth,
+    uint32_t address_cells, uint32_t size_cells, void *data)
+{
+    struct boot_info *info = (struct boot_info *)data;
+    const struct fdt_property *prop;
+    struct boot_domain *domain;
+    int node_next, i, plen;
+
+    if ( !info )
+        return -1;
+
+    if ( info->builder->nr_doms >= BUILD_MAX_BOOT_DOMAINS )
+        return -1;
+
+    domain = &info->builder->domains[info->builder->nr_doms];
+
+    domain->domid = (domid_t)device_tree_get_u32(fdt, node, "domid", 0);
+    domain->permissions = device_tree_get_u32(fdt, node, "permissions", 0);
+    domain->functions = device_tree_get_u32(fdt, node, "functions", 0);
+    domain->mode = device_tree_get_u32(fdt, node, "mode", 0);
+
+    prop = fdt_get_property(fdt, node, "domain-uuid", &plen);
+    if ( prop )
+        for ( i=0; i < sizeof(domain->uuid) % sizeof(uint32_t); i++ )
+            *(domain->uuid + i) = fdt32_to_cpu((uint32_t)prop->data[i]);
+
+    domain->ncpus = device_tree_get_u32(fdt, node, "cpus", 1);
+
+    if ( target_arch == BUILDER_FDT_TARGET_X86 )
+    {
+        prop = fdt_get_property(fdt, node, "memory", &plen);
+        if ( prop )
+        {
+            int sz = fdt32_to_cpu(prop->len);
+            char s[64];
+            unsigned long val;
+
+            if ( sz >= 64 )
+                panic("node %s invalid `memory' property\n", name);
+
+            memcpy(s, prop->data, sz);
+            s[sz] = '\0';
+            val = parse_size_and_unit(s, NULL);
+
+            domain->meminfo.mem_size.nr_pages = PFN_UP(val);
+            domain->meminfo.mem_max.nr_pages = PFN_UP(val);
+        }
+        else
+            panic("node %s missing `memory' property\n", name);
+    }
+    else
+            panic("%s: only x86 memory parsing supported\n", __func__);
+
+    prop = fdt_get_property(fdt, node, "security-id",
+                                &plen);
+    if ( prop )
+    {
+        int sz = fdt32_to_cpu(prop->len);
+        sz = sz > BUILD_MAX_SECID_LEN ?  BUILD_MAX_SECID_LEN : sz;
+        memcpy(domain->secid, prop->data, sz);
+    }
+
+    for ( node_next = fdt_first_subnode(fdt, node);
+          node_next > 0;
+          node_next = fdt_next_subnode(fdt, node_next))
+    {
+        struct boot_module *bm = read_module(fdt, node_next, address_cells,
+                                             size_cells, info);
+
+        switch ( bm->kind )
+        {
+        case BOOTMOD_KERNEL:
+            /* kernel was already found */
+            if ( domain->kernel != NULL )
+                continue;
+
+            bm->arch->headroom = bzimage_headroom(bootstrap_map(bm), bm->size);
+            bootstrap_map(NULL);
+
+            if ( bm->string.len )
+                bm->string.kind = BOOTSTR_CMDLINE;
+            else
+            {
+                prop = fdt_get_property(fdt, node_next, "bootargs", &plen);
+                if ( prop )
+                {
+                    int size = fdt32_to_cpu(prop->len);
+                    size = size > BOOTMOD_MAX_STRING ?
+                           BOOTMOD_MAX_STRING : size;
+                    memcpy(bm->string.bytes, prop->data, size);
+                    bm->string.kind = BOOTSTR_CMDLINE;
+                }
+            }
+
+            domain->kernel = bm;
+
+            break;
+        case BOOTMOD_RAMDISK:
+            /* ramdisk was already found */
+            if ( domain->ramdisk != NULL )
+                continue;
+
+            domain->ramdisk = bm;
+
+            break;
+        case BOOTMOD_GUEST_CONF:
+            /* guest config was already found */
+            if ( domain->configs[BUILD_DOM_CONF_IDX] != NULL )
+                continue;
+
+            domain->configs[BUILD_DOM_CONF_IDX] = bm;
+
+            break;
+        default:
+            continue;
+        }
+    }
+
+    info->builder->nr_doms++;
+
+    return 0;
+}
+
+static int __init scan_node(
+    const void *fdt, int node, const char *name, int depth, u32 address_cells,
+    u32 size_cells, void *data)
+{
+    int rc = -1;
+
+    /* skip nodes that are not direct children of the hyperlaunch node */
+    if ( depth > 1 )
+        return 0;
+
+    if ( device_tree_node_compatible(fdt, node, "xen,config") )
+        rc = process_config_node(fdt, node, name, depth,
+                                 address_cells, size_cells, data);
+    else if ( device_tree_node_compatible(fdt, node, "xen,domain") )
+        rc = process_domain_node(fdt, node, name, depth,
+                                 address_cells, size_cells, data);
+
+    if ( rc < 0 )
+        printk("hyperlaunch fdt: node `%s'failed to parse\n", name);
+
+    return rc;
+}
+
+/* check_fdt
+ *   Attempts to initialize hyperlaunch config
+ *
+ * Returns:
+ *    -EINVAL: Not a valid DTB
+ *   -ENODATA: Valid DTB but not a valid hyperlaunch device tree
+ *          0: Valid hyperlaunch device tree
+ */
+int __init check_fdt(struct boot_info *info, void *fdt)
+{
+    int hv_node, ret;
+
+    ret = fdt_check_header(fdt);
+    if ( ret < 0 )
+        return -EINVAL;
+
+    hv_node = fdt_path_offset(fdt, "/chosen/hypervisor");
+    if ( hv_node < 0 )
+        return -ENODATA;
+
+    if ( !device_tree_node_compatible(fdt, hv_node, "hypervisor,xen") )
+        return -EINVAL;
+
+    if ( IS_ENABLED(CONFIG_X86) &&
+         device_tree_node_compatible(fdt, hv_node, "xen,x86") )
+        target_arch = BUILDER_FDT_TARGET_X86;
+    else if ( IS_ENABLED(CONFIG_ARM) &&
+              device_tree_node_compatible(fdt, hv_node, "xen,arm") )
+        target_arch = BUILDER_FDT_TARGET_ARM;
+
+    if ( target_arch != BUILDER_FDT_TARGET_X86 &&
+         target_arch != BUILDER_FDT_TARGET_ARM )
+        return -EINVAL;
+
+    ret = device_tree_for_each_node(fdt, hv_node, scan_node, boot_info);
+    if ( ret > 0 )
+        return -ENODATA;
+
+    return 0;
+}
diff --git a/xen/common/domain-builder/fdt.h b/xen/common/domain-builder/fdt.h
new file mode 100644
index 0000000000..b185718412
--- /dev/null
+++ b/xen/common/domain-builder/fdt.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef COMMON_BUILDER_FDT_H
+#define COMMON_BUILDER_FDT_H
+
+int __init check_fdt(struct boot_info *info, void *fdt);
+#endif
diff --git a/xen/include/xen/bootinfo.h b/xen/include/xen/bootinfo.h
index 1d76d99a40..07b151e318 100644
--- a/xen/include/xen/bootinfo.h
+++ b/xen/include/xen/bootinfo.h
@@ -101,6 +101,22 @@ static inline struct boot_module *bootmodule_next_by_kind(
     return NULL;
 }
 
+static inline struct boot_module *bootmodule_next_by_addr(
+    const struct boot_info *bi, paddr_t addr, struct boot_module *start)
+{
+    /* point end at the entry for xen */
+    struct boot_module *end = &bi->mods[bi->nr_mods];
+
+    if ( !start )
+        start = bi->mods;
+
+    for ( ; start < end; start++ )
+        if ( start->start == addr )
+            return start;
+
+    return NULL;
+}
+
 static inline void bootmodule_update_start(struct boot_module *b, paddr_t new_start)
 {
     b->start = new_start;
diff --git a/xen/include/xen/domain_builder.h b/xen/include/xen/domain_builder.h
index 79785ef251..c0d997f7bd 100644
--- a/xen/include/xen/domain_builder.h
+++ b/xen/include/xen/domain_builder.h
@@ -51,5 +51,6 @@ static inline struct domain *builder_get_hwdom(struct boot_info *info)
 
 void builder_init(struct boot_info *info);
 uint32_t builder_create_domains(struct boot_info *info);
+void arch_create_dom(const struct boot_info *bi, struct boot_domain *bd);
 
 #endif /* XEN_DOMAIN_BUILDER_H */
-- 
2.20.1



  parent reply	other threads:[~2022-07-06 21:08 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-06 21:04 [PATCH v1 00/18] Hyperlaunch Daniel P. Smith
2022-07-06 21:04 ` [PATCH v1 01/18] kconfig: allow configuration of maximum modules Daniel P. Smith
2022-07-07  1:44   ` Henry Wang
2022-07-15 19:16   ` Julien Grall
2022-07-19 16:36     ` Daniel P. Smith
2022-07-26 18:07       ` Julien Grall
2022-07-27  6:12         ` Jan Beulich
2022-07-19  9:32   ` Jan Beulich
2022-07-19 17:02     ` Daniel P. Smith
2022-07-20  7:27       ` Jan Beulich
2022-07-22 15:00         ` Daniel P. Smith
2022-07-06 21:04 ` [PATCH v1 02/18] introduction of generalized boot info Daniel P. Smith
2022-07-15 19:25   ` Julien Grall
2022-07-20 18:32     ` Daniel P. Smith
2022-07-19 13:11   ` Jan Beulich
2022-07-21 14:28     ` Daniel P. Smith
2022-07-21 16:00       ` Jan Beulich
2022-07-22 16:01         ` Daniel P. Smith
2022-07-25  7:05           ` Jan Beulich
2022-07-21 16:00       ` Jan Beulich
2022-07-06 21:04 ` [PATCH v1 03/18] x86: adopt new boot info structures Daniel P. Smith
2022-07-19 13:19   ` Jan Beulich
2022-07-22 12:34     ` Daniel P. Smith
2022-07-06 21:04 ` [PATCH v1 04/18] x86: refactor entrypoints to new boot info Daniel P. Smith
2022-07-18 13:58   ` Smith, Jackson
2022-07-22 12:59     ` Daniel P. Smith
2022-07-06 21:04 ` [PATCH v1 05/18] x86: refactor xen cmdline into general framework Daniel P. Smith
2022-07-19 13:26   ` Jan Beulich
2022-07-22 13:12     ` Daniel P. Smith
2022-07-25  7:09       ` Jan Beulich
2022-07-06 21:04 ` [PATCH v1 06/18] fdt: make fdt handling reusable across arch Daniel P. Smith
2022-07-07  1:44   ` Henry Wang
2022-07-19  9:36   ` Jan Beulich
2022-07-22 13:18     ` Daniel P. Smith
2022-07-06 21:04 ` [PATCH v1 07/18] docs: update hyperlaunch device tree documentation Daniel P. Smith
2022-07-18 13:57   ` Smith, Jackson
2022-07-22 13:34     ` Daniel P. Smith
2022-07-06 21:04 ` [PATCH v1 08/18] kconfig: introduce domain builder config option Daniel P. Smith
2022-07-07  1:44   ` Henry Wang
2022-07-19 13:29   ` Jan Beulich
2022-07-22 13:47     ` Daniel P. Smith
2022-07-06 21:04 ` [PATCH v1 09/18] x86: introduce abstractions for domain builder Daniel P. Smith
2022-07-26 14:22   ` Jan Beulich
2022-07-06 21:04 ` Daniel P. Smith [this message]
2022-07-18 13:59   ` [PATCH v1 10/18] x86: introduce the " Smith, Jackson
2022-07-22 14:36     ` Daniel P. Smith
2022-07-22 20:33       ` Smith, Jackson
2022-07-23 10:45         ` Daniel P. Smith
2022-07-26 14:46   ` Jan Beulich
2022-07-06 21:04 ` [PATCH v1 11/18] x86: initial conversion to " Daniel P. Smith
2022-07-26 15:01   ` Jan Beulich
2022-07-06 21:04 ` [PATCH v1 12/18] x86: convert dom0 creation " Daniel P. Smith
2022-07-27 12:25   ` Jan Beulich
2022-07-06 21:04 ` [PATCH v1 13/18] x86: generalize physmap logic Daniel P. Smith
2022-07-27 12:33   ` Jan Beulich
2022-07-06 21:04 ` [PATCH v1 14/18] x86: generalize vcpu for domain building Daniel P. Smith
2022-07-27 12:46   ` Jan Beulich
2022-07-06 21:04 ` [PATCH v1 15/18] x86: rework domain page allocation Daniel P. Smith
2022-07-27 13:22   ` Jan Beulich
2022-07-06 21:04 ` [PATCH v1 16/18] x86: add pv multidomain construction Daniel P. Smith
2022-07-27 14:12   ` Jan Beulich
2022-07-06 21:04 ` [PATCH v1 17/18] builder: introduce domain builder hypfs tree Daniel P. Smith
2022-07-27 14:30   ` Jan Beulich
2022-07-06 21:04 ` [PATCH v1 18/18] tools: introduce example late pv helper Daniel P. Smith
2022-07-19 17:06 ` [PATCH v1 00/18] Hyperlaunch Smith, Jackson
2022-07-22 14:51   ` Daniel P. Smith

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=20220706210454.30096-11-dpsmith@apertussolutions.com \
    --to=dpsmith@apertussolutions.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=christopher.clark@starlab.io \
    --cc=george.dunlap@citrix.com \
    --cc=jbeulich@suse.com \
    --cc=julien@xen.org \
    --cc=roger.pau@citrix.com \
    --cc=scott.davis@starlab.io \
    --cc=sstabellini@kernel.org \
    --cc=wl@xen.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.