[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v1 10/18] x86: introduce the domain builder
On 06.07.2022 23:04, Daniel P. Smith wrote: > 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@xxxxxxxxxxxxxxxxxxxx> > Reviewed-by: Christopher Clark <christopher.clark@xxxxxxxxxx> > --- > 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(+) With this diffstat - why the x86: prefix in the subject? Also note the naming inconsistency: domain-builder/ (preferred) vs domain_builder.h (adjustment would require touching earlier patches). > --- 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); > +} You're not removing any code in exchange - is Dom0 now being built twice? Or is the function above effectively dead code? > --- 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/ At least as long as all of this is still experimental I would really like to see a way to disable all of it via Kconfig. > --- /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)) ) Besides requiring fixed order looking inflexible to me, what guarantees there is at least one module? (Perhaps there is, but once again - without seeing where this function is being called from, how am I to judge?) > + { > + case 0: > + printk("Domain Builder: initialized from config\n"); > + info->builder->fdt_enabled = true; > + return; > + case -EINVAL: > + info->builder->fdt_enabled = false; > + break; Aiui this is the case where no FDT is present. I'd strongly suggest to use a less common / ambiguous error code to cover that case. Maybe -ENODEV or -EOPNOTSUPP or ... > + case -ENODATA: ... -ENODATA, albeit you having that here suggests this has some other specific meaning already. > + 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; Nit: Indentation. > + d->kernel->arch->headroom = bzimage_headroom(bootstrap_map(d->kernel), > + d->kernel->size); bzimage isn't an arch-agnostic concept afaict, so I don't see this function legitimately being called from here. And nit again: Indentation. (And at least one more further down.) > + 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]; Can variables of this type please not be named "d", but e.g. "bd"? > + if ( ! IS_ENABLED(CONFIG_MULTIDOM_BUILDER) && > + ! builder_is_initdom(d) && Nit: Stray blanks after ! . > --- /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); Why the cast? > +static int process_domain_node( __init? > + 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; > + } For larger switch() statements please have blank lines between non-fall- through case blocks. > +/* 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; So you'd happily accept BUILDER_FDT_TARGET_ARM on x86 or BUILDER_FDT_TARGET_X86 on Arm? And there's no distinction between Arm32 and Arm64? > --- /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 Nit: Please put another blank line before #endif. Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |