Hi,

On 03/12/2025 18:58, Oleksandr Tyshchenko wrote:
Creating a dom0less guest with a high vCPU count (e.g., >32) fails
because the fixed 4KiB device tree buffer (DOMU_DTB_SIZE) overflows
during creation.

The FDT nodes for each vCPU are the primary consumer of space,
and the previous fixed-size buffer was insufficient.

This patch replaces the fixed size with a formula that calculates
the required buffer size based on a fixed baseline plus a scalable
portion for each potential vCPU up to the MAX_VIRT_CPUS limit.

Signed-off-by: Oleksandr Tyshchenko <[email protected]>
---
V1: 
https://patchew.org/Xen/[email protected]/

   V2:
    - update commit subj/desc
    - use a formula that accounts MAX_VIRT_CPUS
    - add BUILD_BUG_ON
---
---
  xen/common/device-tree/dom0less-build.c | 16 +++++++++++++---
  1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/xen/common/device-tree/dom0less-build.c 
b/xen/common/device-tree/dom0less-build.c
index 3f5b987ed8..38a5830813 100644
--- a/xen/common/device-tree/dom0less-build.c
+++ b/xen/common/device-tree/dom0less-build.c
@@ -461,15 +461,25 @@ static int __init domain_handle_dtb_boot_module(struct 
domain *d,
/*
   * The max size for DT is 2MB. However, the generated DT is small (not 
including
- * domU passthrough DT nodes whose size we account separately), 4KB are enough
- * for now, but we might have to increase it in the future.
+ * domU passthrough DT nodes whose size we account separately). The size is
+ * calculated from a fixed baseline plus a scalable portion for each potential
+ * vCPU node up to the system limit (MAX_VIRT_CPUS), as the vCPU nodes are
+ * the primary consumer of space.
+ *
+ * The baseline of 2KiB is a safe buffer for all non-vCPU FDT content.

What if the use decides to pass a DTB fragment? How do we know this will fit in the 2KiB?

+ * Empirical testing with the maximum number of other device tree nodes shows
+ * a final compacted base size of ~1.5KiB. The 128 bytes per vCPU is derived
+ * from a worst-case analysis of the FDT construction-time size for a single
+ * vCPU node.

For in-code documentation, this is ok to just provide some numbers. But this needs a bit more details in the commit message with the exact tests you did. This would be helpful if we ever need to change the size (for instance we could have extra emulated devices or we need another property per CPU).

   */
-#define DOMU_DTB_SIZE 4096
+#define DOMU_DTB_SIZE (2048 + (MAX_VIRT_CPUS * 128))

On Arm32, MAX_VIRT_CPUS is 8. This means the new DOMU_DTB_SIZE is going to be smaller than 4096. Why is it ok?

  static int __init prepare_dtb_domU(struct domain *d, struct kernel_info 
*kinfo)
  {
      int addrcells, sizecells;
      int ret, fdt_size = DOMU_DTB_SIZE;
+ BUILD_BUG_ON(DOMU_DTB_SIZE > SZ_2M);
+
      kinfo->phandle_intc = GUEST_PHANDLE_GIC;
#ifdef CONFIG_GRANT_TABLE

Cheers,

--
Julien Grall


Reply via email to