diff mbox series

[v1,17/18] builder: introduce domain builder hypfs tree

Message ID 20220706210454.30096-18-dpsmith@apertussolutions.com (mailing list archive)
State New, archived
Headers show
Series Hyperlaunch | expand

Commit Message

Daniel P. Smith July 6, 2022, 9:04 p.m. UTC
This enables domain builder to construct a hypfs tree to expose relevant domain
creation information for use by the boot domain and/or the runtime system.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
Reviewed-by: Christopher Clark <christopher.clark@starlab.io>
---
 xen/common/domain-builder/Kconfig  |  11 ++
 xen/common/domain-builder/Makefile |   1 +
 xen/common/domain-builder/core.c   |   3 +
 xen/common/domain-builder/hypfs.c  | 193 +++++++++++++++++++++++++++++
 xen/include/xen/domain_builder.h   |  13 ++
 5 files changed, 221 insertions(+)
 create mode 100644 xen/common/domain-builder/hypfs.c

Comments

Jan Beulich July 27, 2022, 2:30 p.m. UTC | #1
On 06.07.2022 23:04, Daniel P. Smith wrote:
> --- a/xen/common/domain-builder/core.c
> +++ b/xen/common/domain-builder/core.c
> @@ -134,6 +134,9 @@ uint32_t __init builder_create_domains(struct boot_info *info)
>          /* Free temporary buffers. */
>          discard_initial_images();
>  
> +    if ( IS_ENABLED(CONFIG_BUILDER_HYPFS) )
> +        builder_hypfs(info);

No need for the if() here when you provide a stub in the header file.
Just that of course the stub vs prototype there needs to depend on
CONFIG_BUILDER_HYPFS, not CONFIG_HYPFS.

> +static int __init alloc_hypfs(struct boot_info *info)
> +{
> +    if ( !(builder_dir = (struct hypfs_entry_dir *)xmalloc_bytes(
> +                        sizeof(struct hypfs_entry_dir))) )

Why not xmalloc() (or xzalloc()), which specifically exists to avoid
open-coded casts like the one here?

> +    {
> +        printk(XENLOG_WARNING "%s: unable to allocate hypfs dir\n", __func__);
> +        return -ENOMEM;
> +    }
> +
> +    builder_dir->e.type = XEN_HYPFS_TYPE_DIR;
> +    builder_dir->e.encoding = XEN_HYPFS_ENC_PLAIN;
> +    builder_dir->e.name = "builder";
> +    builder_dir->e.size = 0;
> +    builder_dir->e.max_size = 0;
> +    INIT_LIST_HEAD(&builder_dir->e.list);
> +    builder_dir->e.funcs = &hypfs_dir_funcs;
> +    INIT_LIST_HEAD(&builder_dir->dirlist);
> +
> +    if ( !(entries = (struct domain_node *)xmalloc_bytes(
> +                        sizeof(struct domain_node) * info->builder->nr_doms)) )

xmalloc_array()?

> +    {
> +        printk(XENLOG_WARNING "%s: unable to allocate hypfs nodes\n", __func__);
> +        return -ENOMEM;
> +    }
> +
> +    return 0;
> +}
> +
> +void __init builder_hypfs(struct boot_info *info)
> +{
> +    int i;
> +
> +    printk("Domain Builder: creating hypfs nodes\n");

If at all, then dprintk().

> +    if ( alloc_hypfs(info) != 0 )
> +        return;
> +
> +    for ( i = 0; i < info->builder->nr_doms; i++ )
> +    {
> +        struct domain_node *e = &entries[i];
> +        struct boot_domain *bd = &info->builder->domains[i];
> +        uint8_t *uuid = bd->uuid;
> +
> +        snprintf(e->dir_name, sizeof(e->dir_name), "%d", bd->domid);
> +
> +        snprintf(e->uuid, sizeof(e->uuid), "%08x-%04x-%04x-%04x-%04x%08x",
> +                 *(uint32_t *)uuid, *(uint16_t *)(uuid+4),
> +                 *(uint16_t *)(uuid+6), *(uint16_t *)(uuid+8),
> +                 *(uint16_t *)(uuid+10), *(uint32_t *)(uuid+12));

Perhaps better introduce a properly typed structure? Endian-ness-wise
I'm also unsure about the last 12 nibbles: Isn't this an array of bytes
really? Actually the second-to-last 16-bit item is an array of two
bytes as well, if Linux'es %pU vsprintf() formatting is to be trusted.

> +        e->functions = bd->functions;
> +        e->constructed = bd->constructed;
> +
> +        e->ncpus = bd->ncpus;
> +        e->mem_size = (bd->meminfo.mem_size.nr_pages * PAGE_SIZE)/1024;
> +        e->mem_max = (bd->meminfo.mem_max.nr_pages * PAGE_SIZE)/1024;

Nit: Blanks around / please.

> +        e->xs.evtchn = bd->store.evtchn;
> +        e->xs.mfn = bd->store.mfn;
> +
> +        e->con_dev.evtchn = bd->console.evtchn;
> +        e->con_dev.mfn = bd->console.mfn;
> +
> +        /* Initialize and construct builder hypfs tree */
> +        INIT_HYPFS_DIR(e->dir, e->dir_name);
> +        INIT_HYPFS_DIR(e->xs.dir, "xenstore");
> +        INIT_HYPFS_DIR(e->dev_dir, "devices");
> +        INIT_HYPFS_DIR(e->con_dev.dir, "console");
> +
> +        INIT_HYPFS_STRING(e->uuid_leaf, "uuid");
> +        hypfs_string_set_reference(&e->uuid_leaf, e->uuid);
> +        INIT_HYPFS_UINT(e->func_leaf, "functions", e->functions);
> +        INIT_HYPFS_UINT(e->ncpus_leaf, "ncpus", e->ncpus);
> +        INIT_HYPFS_UINT(e->mem_sz_leaf, "mem_size", e->mem_size);
> +        INIT_HYPFS_UINT(e->mem_mx_leaf, "mem_max", e->mem_max);

May I suggest to prefer - over _ in node names?

> --- a/xen/include/xen/domain_builder.h
> +++ b/xen/include/xen/domain_builder.h
> @@ -72,4 +72,17 @@ int alloc_system_evtchn(
>      const struct boot_info *info, struct boot_domain *bd);
>  void arch_create_dom(const struct boot_info *bi, struct boot_domain *bd);
>  
> +#ifdef CONFIG_HYPFS
> +
> +void builder_hypfs(struct boot_info *info);
> +
> +#else
> +
> +static inline void builder_hypfs(struct boot_info *info)
> +{
> +    return;
> +}
> +
> +#endif

This would better go in a private header in xen/common/domain-builder/.

Jan
diff mbox series

Patch

diff --git a/xen/common/domain-builder/Kconfig b/xen/common/domain-builder/Kconfig
index 0232e1ed8a..4b98cccfab 100644
--- a/xen/common/domain-builder/Kconfig
+++ b/xen/common/domain-builder/Kconfig
@@ -22,4 +22,15 @@  config MULTIDOM_BUILDER
 
 	  If unsure, say N.
 
+config BUILDER_HYPFS
+	bool "Domain builder hypfs support (UNSUPPORTED)" if UNSUPPORTED
+	depends on HYPFS
+	---help---
+	  Exposes the domain builder construction information
+	  through hypfs.
+
+	  This feature is currently experimental.
+
+	  If unsure, say N.
+
 endmenu
diff --git a/xen/common/domain-builder/Makefile b/xen/common/domain-builder/Makefile
index 9561602502..7aa2ea2a53 100644
--- a/xen/common/domain-builder/Makefile
+++ b/xen/common/domain-builder/Makefile
@@ -1,2 +1,3 @@ 
 obj-$(CONFIG_BUILDER_FDT) += fdt.o
+obj-$(CONFIG_HYPFS) += hypfs.o
 obj-y += core.o
diff --git a/xen/common/domain-builder/core.c b/xen/common/domain-builder/core.c
index c6a268eb96..f41ca3ed35 100644
--- a/xen/common/domain-builder/core.c
+++ b/xen/common/domain-builder/core.c
@@ -134,6 +134,9 @@  uint32_t __init builder_create_domains(struct boot_info *info)
         /* Free temporary buffers. */
         discard_initial_images();
 
+    if ( IS_ENABLED(CONFIG_BUILDER_HYPFS) )
+        builder_hypfs(info);
+
     return build_count;
 }
 
diff --git a/xen/common/domain-builder/hypfs.c b/xen/common/domain-builder/hypfs.c
new file mode 100644
index 0000000000..28f8b13d85
--- /dev/null
+++ b/xen/common/domain-builder/hypfs.c
@@ -0,0 +1,193 @@ 
+#include <xen/bootinfo.h>
+#include <xen/domain_builder.h>
+#include <xen/hypfs.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/list.h>
+#include <xen/string.h>
+#include <xen/xmalloc.h>
+
+#define INIT_HYPFS_DIR(var, nam)                 \
+    var.e.type = XEN_HYPFS_TYPE_DIR;             \
+    var.e.encoding = XEN_HYPFS_ENC_PLAIN;        \
+    var.e.name = (nam);                          \
+    var.e.size = 0;                              \
+    var.e.max_size = 0;                          \
+    INIT_LIST_HEAD(&var.e.list);                 \
+    var.e.funcs = (&hypfs_dir_funcs);            \
+    INIT_LIST_HEAD(&var.dirlist)
+
+#define INIT_HYPFS_FIXEDSIZE(var, typ, nam, contvar, fn, wr) \
+    var.e.type = (typ);                                      \
+    var.e.encoding = XEN_HYPFS_ENC_PLAIN;                    \
+    var.e.name = (nam);                                      \
+    var.e.size = sizeof(contvar);                            \
+    var.e.max_size = (wr) ? sizeof(contvar) : 0;             \
+    var.e.funcs = (fn);                                      \
+    var.u.content = &(contvar)
+
+#define INIT_HYPFS_UINT(var, nam, contvar)                       \
+    INIT_HYPFS_FIXEDSIZE(var, XEN_HYPFS_TYPE_UINT, nam, contvar, \
+                         &hypfs_leaf_ro_funcs, 0)
+
+#define INIT_HYPFS_BOOL(var, nam, contvar)                       \
+    INIT_HYPFS_FIXEDSIZE(var, XEN_HYPFS_TYPE_BOOL, nam, contvar, \
+                         &hypfs_leaf_ro_funcs, 0)
+
+#define INIT_HYPFS_VARSIZE(var, typ, nam, msz, fn) \
+    var.e.type = (typ) ;                           \
+    var.e.encoding = XEN_HYPFS_ENC_PLAIN;          \
+    var.e.name = (nam);                            \
+    var.e.max_size = (msz);                        \
+    var.e.funcs = (fn)
+
+#define INIT_HYPFS_STRING(var, nam)               \
+    INIT_HYPFS_VARSIZE(var, XEN_HYPFS_TYPE_STRING, nam, 0, &hypfs_leaf_ro_funcs)
+
+struct device_node {
+    struct hypfs_entry_dir dir;
+
+    uint32_t evtchn;
+    struct hypfs_entry_leaf evtchn_leaf;
+
+    xen_pfn_t mfn;
+    struct hypfs_entry_leaf mfn_leaf;
+};
+
+struct domain_node {
+    char dir_name[HYPFS_DYNDIR_ID_NAMELEN];
+    struct hypfs_entry_dir dir;
+
+    char uuid[40];
+    struct hypfs_entry_leaf uuid_leaf;
+
+    uint16_t functions;
+    struct hypfs_entry_leaf func_leaf;
+
+    uint32_t ncpus;
+    struct hypfs_entry_leaf ncpus_leaf;
+
+    uint32_t mem_size;
+    struct hypfs_entry_leaf mem_sz_leaf;
+
+    uint32_t mem_max;
+    struct hypfs_entry_leaf mem_mx_leaf;
+
+    bool constructed;
+    struct hypfs_entry_leaf const_leaf;
+
+    struct device_node xs;
+
+    struct hypfs_entry_dir dev_dir;
+
+    struct device_node con_dev;
+};
+
+static struct hypfs_entry_dir __read_mostly *builder_dir;
+static struct domain_node __read_mostly *entries;
+
+static int __init alloc_hypfs(struct boot_info *info)
+{
+    if ( !(builder_dir = (struct hypfs_entry_dir *)xmalloc_bytes(
+                        sizeof(struct hypfs_entry_dir))) )
+    {
+        printk(XENLOG_WARNING "%s: unable to allocate hypfs dir\n", __func__);
+        return -ENOMEM;
+    }
+
+    builder_dir->e.type = XEN_HYPFS_TYPE_DIR;
+    builder_dir->e.encoding = XEN_HYPFS_ENC_PLAIN;
+    builder_dir->e.name = "builder";
+    builder_dir->e.size = 0;
+    builder_dir->e.max_size = 0;
+    INIT_LIST_HEAD(&builder_dir->e.list);
+    builder_dir->e.funcs = &hypfs_dir_funcs;
+    INIT_LIST_HEAD(&builder_dir->dirlist);
+
+    if ( !(entries = (struct domain_node *)xmalloc_bytes(
+                        sizeof(struct domain_node) * info->builder->nr_doms)) )
+    {
+        printk(XENLOG_WARNING "%s: unable to allocate hypfs nodes\n", __func__);
+        return -ENOMEM;
+    }
+
+    return 0;
+}
+
+void __init builder_hypfs(struct boot_info *info)
+{
+    int i;
+
+    printk("Domain Builder: creating hypfs nodes\n");
+
+    if ( alloc_hypfs(info) != 0 )
+        return;
+
+    for ( i = 0; i < info->builder->nr_doms; i++ )
+    {
+        struct domain_node *e = &entries[i];
+        struct boot_domain *bd = &info->builder->domains[i];
+        uint8_t *uuid = bd->uuid;
+
+        snprintf(e->dir_name, sizeof(e->dir_name), "%d", bd->domid);
+
+        snprintf(e->uuid, sizeof(e->uuid), "%08x-%04x-%04x-%04x-%04x%08x",
+                 *(uint32_t *)uuid, *(uint16_t *)(uuid+4),
+                 *(uint16_t *)(uuid+6), *(uint16_t *)(uuid+8),
+                 *(uint16_t *)(uuid+10), *(uint32_t *)(uuid+12));
+
+        e->functions = bd->functions;
+        e->constructed = bd->constructed;
+
+        e->ncpus = bd->ncpus;
+        e->mem_size = (bd->meminfo.mem_size.nr_pages * PAGE_SIZE)/1024;
+        e->mem_max = (bd->meminfo.mem_max.nr_pages * PAGE_SIZE)/1024;
+
+        e->xs.evtchn = bd->store.evtchn;
+        e->xs.mfn = bd->store.mfn;
+
+        e->con_dev.evtchn = bd->console.evtchn;
+        e->con_dev.mfn = bd->console.mfn;
+
+        /* Initialize and construct builder hypfs tree */
+        INIT_HYPFS_DIR(e->dir, e->dir_name);
+        INIT_HYPFS_DIR(e->xs.dir, "xenstore");
+        INIT_HYPFS_DIR(e->dev_dir, "devices");
+        INIT_HYPFS_DIR(e->con_dev.dir, "console");
+
+        INIT_HYPFS_STRING(e->uuid_leaf, "uuid");
+        hypfs_string_set_reference(&e->uuid_leaf, e->uuid);
+        INIT_HYPFS_UINT(e->func_leaf, "functions", e->functions);
+        INIT_HYPFS_UINT(e->ncpus_leaf, "ncpus", e->ncpus);
+        INIT_HYPFS_UINT(e->mem_sz_leaf, "mem_size", e->mem_size);
+        INIT_HYPFS_UINT(e->mem_mx_leaf, "mem_max", e->mem_max);
+        INIT_HYPFS_BOOL(e->const_leaf, "constructed", e->constructed);
+
+        INIT_HYPFS_UINT(e->xs.evtchn_leaf, "evtchn", e->xs.evtchn);
+        INIT_HYPFS_UINT(e->xs.mfn_leaf, "mfn", e->xs.mfn);
+
+        INIT_HYPFS_UINT(e->con_dev.evtchn_leaf, "evtchn", e->con_dev.evtchn);
+        INIT_HYPFS_UINT(e->con_dev.mfn_leaf, "mfn", e->con_dev.mfn);
+
+        hypfs_add_leaf(&e->con_dev.dir, &e->con_dev.evtchn_leaf, true);
+        hypfs_add_leaf(&e->con_dev.dir, &e->con_dev.mfn_leaf, true);
+        hypfs_add_dir(&e->dev_dir, &e->con_dev.dir, true);
+
+        hypfs_add_dir(&e->dir, &e->dev_dir, true);
+
+        hypfs_add_leaf(&e->xs.dir, &e->xs.evtchn_leaf, true);
+        hypfs_add_leaf(&e->xs.dir, &e->xs.mfn_leaf, true);
+        hypfs_add_dir(&e->dir, &e->xs.dir, true);
+
+        hypfs_add_leaf(&e->dir, &e->uuid_leaf, true);
+        hypfs_add_leaf(&e->dir, &e->func_leaf, true);
+        hypfs_add_leaf(&e->dir, &e->ncpus_leaf, true);
+        hypfs_add_leaf(&e->dir, &e->mem_sz_leaf, true);
+        hypfs_add_leaf(&e->dir, &e->mem_mx_leaf, true);
+        hypfs_add_leaf(&e->dir, &e->const_leaf, true);
+
+        hypfs_add_dir(builder_dir, &e->dir, true);
+    }
+
+    hypfs_add_dir(&hypfs_root, builder_dir, true);
+}
diff --git a/xen/include/xen/domain_builder.h b/xen/include/xen/domain_builder.h
index f9e43c9689..086968b0fe 100644
--- a/xen/include/xen/domain_builder.h
+++ b/xen/include/xen/domain_builder.h
@@ -72,4 +72,17 @@  int alloc_system_evtchn(
     const struct boot_info *info, struct boot_domain *bd);
 void arch_create_dom(const struct boot_info *bi, struct boot_domain *bd);
 
+#ifdef CONFIG_HYPFS
+
+void builder_hypfs(struct boot_info *info);
+
+#else
+
+static inline void builder_hypfs(struct boot_info *info)
+{
+    return;
+}
+
+#endif
+
 #endif /* XEN_DOMAIN_BUILDER_H */