From: Alejandro Vallejo <agarciav@amd.com>
To: <dmkhn@proton.me>
Cc: xen-devel@lists.xenproject.org,
"Andrew Cooper" <andrew.cooper3@citrix.com>,
"Anthony PERARD" <anthony.perard@vates.tech>,
"Michal Orzel" <michal.orzel@amd.com>,
"Jan Beulich" <jbeulich@suse.com>,
"Julien Grall" <julien@xen.org>,
"Roger Pau Monné" <roger.pau@citrix.com>,
"Stefano Stabellini" <sstabellini@kernel.org>,
"Bertrand Marquis" <bertrand.marquis@arm.com>,
"Jason Andryuk" <jason.andryuk@amd.com>
Subject: Re: [PATCH v4 05/13] x86/hyperlaunch: Add helpers to locate multiboot modules
Date: Wed, 23 Apr 2025 13:12:03 +0100 [thread overview]
Message-ID: <D9E0BL26H82L.2DEW4IC6FENYN@amd.com> (raw)
In-Reply-To: <aALSauQee7Z3O8Bj@kraken>
On Fri Apr 18, 2025 at 11:30 PM BST, dmkhn wrote:
> On Thu, Apr 17, 2025 at 01:48:27PM +0100, Alejandro Vallejo wrote:
>> Hyperlaunch mandates either a reg or module-index DT prop on nodes that
>> contain `multiboot,module" under their "compatible" prop. This patch
>> introduces a helper to generically find such index, appending the module
>> to the list of modules if it wasn't already (i.e: because it's given via
>> the "reg" prop).
>>
>> Signed-off-by: Jason Andryuk <jason.andryuk@amd.com>
>> Signed-off-by: Alejandro Vallejo <agarciav@amd.com>
>> ---
>> v4:
>> * Remove stray reg prop parser in libfdt-xen.h.
>> * Remove fdt32_as_uX accessors.
>> * Brough fdt_prop_as_u32() accesor from later patches.
>> * So it can be used in place of a hardcoded fdt32_as_u32().
>> * Limited MAX_NR_BOOTMODS to INT_MAX.
>> * Preserved BOOTMOD_XEN on module append logic.
>> * Add missing bounds check to module-index parsed in multiboot module helper.
>> * Converted idx variable to uint32_t for better bounds checking.
>> * Braces from switch statement to conform to coding style.
>> * Added missing XENLOG_X.
>> * Print address_cells and size_cells on error parsing reg properties.
>> * Added (transient) missing declaration for extern helper.
>> * becomes static on the next patch.
>> ---
>> xen/common/domain-builder/fdt.c | 162 ++++++++++++++++++++++++++++
>> xen/common/domain-builder/fdt.h | 2 +
>> xen/include/xen/domain-builder.h | 3 +
>> xen/include/xen/libfdt/libfdt-xen.h | 11 ++
>> 4 files changed, 178 insertions(+)
>>
>> diff --git a/xen/common/domain-builder/fdt.c b/xen/common/domain-builder/fdt.c
>> index b5ff8220da..d73536fed6 100644
>> --- a/xen/common/domain-builder/fdt.c
>> +++ b/xen/common/domain-builder/fdt.c
>> @@ -13,6 +13,168 @@
>>
>> #include "fdt.h"
>>
>> +/*
>> + * Unpacks a "reg" property into its address and size constituents.
>> + *
>> + * @param prop Pointer to an FDT "reg" property.
>> + * @param address_cells Number of 4-octet cells that make up an "address".
>> + * @param size_cells Number of 4-octet cells that make up a "size".
>> + * @param p_addr[out] Address encoded in the property.
>> + * @param p_size[out] Size encoded in the property.
>> + * @returns -EINVAL on malformed property, 0 otherwise.
>> + */
>> +static int __init read_fdt_prop_as_reg(const struct fdt_property *prop,
>
> I would do s/read_fdt_prop_as_reg/fdt_prop_as_reg/ similar to fdt_prop_as_u32()
> below.
Yes, that sounds better.
>
>> + int address_cells, int size_cells,
>> + uint64_t *p_addr, uint64_t *p_size)
>> +{
>> + const fdt32_t *cell = (const fdt32_t *)prop->data;
>> + uint64_t addr, size;
>> +
>> + if ( fdt32_to_cpu(prop->len) !=
>> + (address_cells + size_cells) * sizeof(*cell) )
>> + {
>> + printk(XENLOG_ERR " cannot read reg %lu+%lu from prop len %u\n",
>> + address_cells * sizeof(*cell), size_cells * sizeof(*cell),
>> + fdt32_to_cpu(prop->len));
>> + return -EINVAL;
>> + }
>> +
>> + switch ( address_cells )
>> + {
>> + case 1:
>> + addr = fdt32_to_cpu(*cell);
>> + break;
>> + case 2:
>> + addr = fdt64_to_cpu(*(const fdt64_t *)cell);
>> + break;
>> + default:
>> + printk(XENLOG_ERR " unsupported address_cells=%d\n", address_cells);
>> + return -EINVAL;
>> + }
>> +
>> + cell += address_cells;
>> + switch ( size_cells )
>> + {
>> + case 1:
>> + size = fdt32_to_cpu(*cell);
>> + break;
>> + case 2:
>> + size = fdt64_to_cpu(*(const fdt64_t *)cell);
>> + break;
>> + default:
>> + printk(XENLOG_ERR " unsupported size_cells=%d\n", size_cells);
>> + return -EINVAL;
>> + }
>> +
>> + *p_addr = addr;
>> + *p_size = size;
>> +
>> + return 0;
>> +}
>> +
>> +/*
>> + * Locate a multiboot module given its node offset in the FDT.
>> + *
>> + * The module location may be given via either FDT property:
>> + * * reg = <address, size>
>> + * * Mutates `bi` to append the module.
>> + * * module-index = <idx>
>> + * * Leaves `bi` unchanged.
>> + *
>> + * @param fdt Pointer to the full FDT.
>> + * @param node Offset for the module node.
>> + * @param address_cells Number of 4-octet cells that make up an "address".
>> + * @param size_cells Number of 4-octet cells that make up a "size".
>> + * @param bi[inout] Xen's representation of the boot parameters.
>> + * @return -EINVAL on malformed nodes, otherwise
>> + * index inside `bi->mods`
>> + */
>> +int __init fdt_read_multiboot_module(const void *fdt, int node,
>> + int address_cells, int size_cells,
>> + struct boot_info *bi)
>> +{
>> + const struct fdt_property *prop;
>> + uint64_t addr, size;
>> + int ret;
>> + uint32_t idx;
>> +
>> + if ( fdt_node_check_compatible(fdt, node, "multiboot,module") )
>> + {
>> + printk(XENLOG_ERR " bad module. multiboot,module not found");
>> + return -ENODATA;
>> + }
>> +
>> + /* Location given as a `module-index` property. */
>> + if ( (prop = fdt_get_property(fdt, node, "module-index", NULL)) )
>> + {
>> + if ( fdt_get_property(fdt, node, "reg", NULL) )
>> + {
>> + printk(XENLOG_ERR " found both reg and module-index for module\n");
>> + return -EINVAL;
>> + }
>> + if ( (ret = fdt_prop_as_u32(prop, &idx)) )
>> + {
>> + printk(XENLOG_ERR " bad module-index prop\n");
>> + return ret;
>> + }
>> + if ( idx >= MAX_NR_BOOTMODS )
>> + {
>> + printk(XENLOG_ERR " module-index overflow. %s=%u\n",
>> + STR(MAX_NR_BOOTMODS), MAX_NR_BOOTMODS);
>> + return -EINVAL;
>> + }
>> +
>> + return idx;
>> + }
>> +
>> + /* Otherwise location given as a `reg` property. */
>> + if ( !(prop = fdt_get_property(fdt, node, "reg", NULL)) )
>> + {
>> + printk(XENLOG_ERR " no location for multiboot,module\n");
>> + return -EINVAL;
>> + }
>> + if ( fdt_get_property(fdt, node, "module-index", NULL) )
>> + {
>> + printk(XENLOG_ERR " found both reg and module-index for module\n");
>> + return -EINVAL;
>> + }
>> +
>> + ret = read_fdt_prop_as_reg(prop, address_cells, size_cells, &addr, &size);
>> + if ( ret < 0 )
>> + {
>> + printk(XENLOG_ERR " failed reading reg for multiboot,module\n");
>> + return -EINVAL;
>> + }
>> +
>> + idx = bi->nr_modules;
>> + if ( idx > MAX_NR_BOOTMODS )
>> + {
>> + /*
>> + * MAX_NR_BOOTMODS must fit in 31 bits so it's representable in the
>> + * positive side of an int; for the return value.
>> + */
>> + BUILD_BUG_ON(MAX_NR_BOOTMODS > (uint64_t)INT_MAX);
>> + printk(XENLOG_ERR " idx=%u exceeds len=%u\n", idx, MAX_NR_BOOTMODS);
>> + return -EINVAL;
>> + }
>> +
>> + /*
>> + * Append new module to the existing list
>> + *
>> + * Note that bi->nr_modules points to Xen itself, so we must shift it first
>> + */
>> + bi->nr_modules++;
>> + bi->mods[bi->nr_modules] = bi->mods[idx];
>> + bi->mods[idx] = (struct boot_module){
>> + .start = addr,
>> + .size = size,
>> + };
>> +
>> + printk(XENLOG_INFO " module[%u]: addr %lx size %lx\n", idx, addr, size);
>> +
>> + return idx;
>> +}
>> +
>> static int __init find_hyperlaunch_node(const void *fdt)
>> {
>> int hv_node = fdt_path_offset(fdt, "/chosen/hypervisor");
>> diff --git a/xen/common/domain-builder/fdt.h b/xen/common/domain-builder/fdt.h
>> index 955aead497..8c98a256eb 100644
>> --- a/xen/common/domain-builder/fdt.h
>> +++ b/xen/common/domain-builder/fdt.h
>> @@ -2,6 +2,8 @@
>> #ifndef __XEN_DOMAIN_BUILDER_FDT_H__
>> #define __XEN_DOMAIN_BUILDER_FDT_H__
>>
>> +#include <xen/libfdt/libfdt-xen.h>
>> +
>> struct boot_info;
>>
>> /* hyperlaunch fdt is required to be module 0 */
>> diff --git a/xen/include/xen/domain-builder.h b/xen/include/xen/domain-builder.h
>> index ac2b84775d..ace6b6875b 100644
>> --- a/xen/include/xen/domain-builder.h
>> +++ b/xen/include/xen/domain-builder.h
>> @@ -5,5 +5,8 @@
>> struct boot_info;
>>
>> void builder_init(struct boot_info *bi);
>> +int fdt_read_multiboot_module(const void *fdt, int node,
>> + int address_cells, int size_cells,
>> + struct boot_info *bi)
>>
>> #endif /* __XEN_DOMAIN_BUILDER_H__ */
>> diff --git a/xen/include/xen/libfdt/libfdt-xen.h b/xen/include/xen/libfdt/libfdt-xen.h
>> index a5340bc9f4..deafb25d98 100644
>> --- a/xen/include/xen/libfdt/libfdt-xen.h
>> +++ b/xen/include/xen/libfdt/libfdt-xen.h
>> @@ -12,6 +12,17 @@
>> #define LIBFDT_XEN_H
>>
>> #include <xen/libfdt/libfdt.h>
>> +#include <xen/errno.h>
>> +
>> +static inline int __init fdt_prop_as_u32(
>> + const struct fdt_property *prop, uint32_t *val)
>> +{
>> + if ( !prop || fdt32_to_cpu(prop->len) < sizeof(u32) )
>> + return -EINVAL;
>> +
>> + *val = fdt32_to_cpu(*(const fdt32_t *)prop->data);
>> + return 0;
>> +}
>
> My understanding is domain builder establishes its own shims around libfdt so
> libfdt is kept unmodified and it is easier to pick up libfdt updates.
>
> So, IMO, this function should reside in xen/common/domain-builder/fdt.c
>
> Thoughts?
Ugh. Too much code motion is not good for your head. I did mean to move
them all (I mentioned it in an earlier response to Jan, I think). Will
do for good this time.
Cheers,
Alejandro
next prev parent reply other threads:[~2025-04-23 12:12 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-17 12:48 [PATCH v4 00/13] Hyperlaunch device tree for dom0 Alejandro Vallejo
2025-04-17 12:48 ` [PATCH v4 01/13] x86/boot: add cmdline to struct boot_domain Alejandro Vallejo
2025-04-17 14:54 ` Jan Beulich
2025-04-17 16:06 ` Alejandro Vallejo
2025-04-18 21:16 ` dmkhn
2025-04-23 11:40 ` Alejandro Vallejo
2025-04-17 12:48 ` [PATCH v4 02/13] kconfig: introduce domain builder config options Alejandro Vallejo
2025-04-17 15:00 ` Jan Beulich
2025-04-17 15:39 ` Jason Andryuk
2025-04-17 16:18 ` Alejandro Vallejo
2025-04-22 6:57 ` Jan Beulich
2025-04-17 12:48 ` [PATCH v4 03/13] common/hyperlaunch: introduce the domain builder Alejandro Vallejo
2025-04-18 21:55 ` dmkhn
2025-04-23 11:52 ` Alejandro Vallejo
2025-04-23 21:53 ` dmkhn
2025-04-17 12:48 ` [PATCH v4 04/13] x86/hyperlaunch: initial support for hyperlaunch device tree Alejandro Vallejo
2025-04-18 22:11 ` dmkhn
2025-04-23 11:54 ` Alejandro Vallejo
2025-04-17 12:48 ` [PATCH v4 05/13] x86/hyperlaunch: Add helpers to locate multiboot modules Alejandro Vallejo
2025-04-18 22:30 ` dmkhn
2025-04-23 12:12 ` Alejandro Vallejo [this message]
2025-04-17 12:48 ` [PATCH v4 06/13] x86/hyperlaunch: locate dom0 kernel with hyperlaunch Alejandro Vallejo
2025-04-18 22:39 ` dmkhn
2025-04-23 12:16 ` Alejandro Vallejo
2025-04-17 12:48 ` [PATCH v4 07/13] x86/hyperlaunch: obtain cmdline from device tree Alejandro Vallejo
2025-04-18 22:53 ` dmkhn
2025-04-23 13:01 ` Alejandro Vallejo
2025-04-23 13:08 ` Jan Beulich
2025-04-24 5:11 ` dmkhn
2025-04-17 12:48 ` [PATCH v4 08/13] x86/hyperlaunch: locate dom0 initrd with hyperlaunch Alejandro Vallejo
2025-04-18 22:58 ` dmkhn
2025-04-23 13:01 ` Alejandro Vallejo
2025-04-17 12:48 ` [PATCH v4 09/13] x86/hyperlaunch: add domain id parsing to domain config Alejandro Vallejo
2025-04-18 23:08 ` dmkhn
2025-04-23 13:03 ` Alejandro Vallejo
2025-04-17 12:48 ` [PATCH v4 10/13] x86/hyperlaunch: specify dom0 mode with device tree Alejandro Vallejo
2025-04-18 23:10 ` dmkhn
2025-04-17 12:48 ` [PATCH v4 11/13] x86/hyperlaunch: add memory parsing to domain config Alejandro Vallejo
2025-04-18 23:21 ` dmkhn
2025-04-23 13:05 ` Alejandro Vallejo
2025-04-17 12:48 ` [PATCH v4 12/13] x86/hyperlaunch: add max vcpu parsing of hyperlaunch device tree Alejandro Vallejo
2025-04-18 23:22 ` dmkhn
2025-04-17 12:48 ` [PATCH v4 13/13] x86/hyperlaunch: add capabilities to boot domain Alejandro Vallejo
2025-04-18 23:24 ` dmkhn
2025-04-23 13:07 ` Alejandro Vallejo
2025-04-17 13:00 ` [PATCH v4 00/13] Hyperlaunch device tree for dom0 Alejandro Vallejo
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=D9E0BL26H82L.2DEW4IC6FENYN@amd.com \
--to=agarciav@amd.com \
--cc=andrew.cooper3@citrix.com \
--cc=anthony.perard@vates.tech \
--cc=bertrand.marquis@arm.com \
--cc=dmkhn@proton.me \
--cc=jason.andryuk@amd.com \
--cc=jbeulich@suse.com \
--cc=julien@xen.org \
--cc=michal.orzel@amd.com \
--cc=roger.pau@citrix.com \
--cc=sstabellini@kernel.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.