[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH v1 25/26] libxl/arm: add and validate Realm guest support


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Koichiro Den <den@xxxxxxxxxxxxx>
  • Date: Fri, 15 May 2026 13:08:11 +0900
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=valinux.co.jp; dmarc=pass action=none header.from=valinux.co.jp; dkim=pass header.d=valinux.co.jp; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=uUEonI82EmDhnjoUm3kfT18UbhTpOT2nksAcbviCf7Q=; b=aQET2pp3uemV1zGmgN4xkf4vVcB/GNIMFESSnVQ8oH1oTOSRsEZRP1PeMnPxwpwiR6uELxY2BvUfpv6jClZDrkl0ib0mXvcEKQ8KlB3jeuUVCRzZ8b5RjjsR50mLWX68mNxU//yEBmSOS67B7lsST8ufDnl4R4AfhpzVSq92Jsw3eI94/imqCtgL5GjbVWHFJxB6tQ0FCQLvCV+ZwS36q14U/yZ55qQ5brpVpTCIYipVJXFRxYViZ30XHdSRZz7r0IXFAmCNz051pPJCkUSiXwc3gB6U8A7fYvad0o+ZNR+lwLDTx59pujoTW34Nnz1adi2WdMTh3e0Nry76tv4Gog==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=bkv1vfI5O59KWDyXSA5ViGCg2IXxkdwp7owGBtNvMwvokpEomtjQnXw+JxUN9uamIOV1l+YqoK059pLHKbU69Sm7OI4vFocvHSFWQl0MjctEz+sJ8VQqn8aqIuxFFI44khV3vFW/25kexn/xCFrN5dR7nSe0P9ElRbqK0zEh8efvOkpON6K7QjDwW5bXZcKv2M3YHVDYQ3F4tk18r5Xq9e9075efGYRILKJA5RABY80xqnZk5cieAF0DyMJNP5SAeQSFv2IdK1FgXv/1+v3CwAP8TMuBR4Cu3x/qSpPvf7AfhKClFbbpj7CTCUezZeEDhZ6lvUUuIpLiJte0Gv2Aew==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=valinux.co.jp header.i="@valinux.co.jp" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp;
  • Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Anthony PERARD <anthony.perard@xxxxxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Julien Grall <julien@xxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, "Daniel P. Smith" <dpsmith@xxxxxxxxxxxxxxxxxxxx>, Juergen Gross <jgross@xxxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Delivery-date: Fri, 15 May 2026 04:11:52 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Add realm=true for Arm guests, reject unsupported combinations, and call
the CCA finalization domctl after the guest is built.

Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
 docs/man/xl.cfg.5.pod.in         |  46 +++++++++-
 tools/include/libxl.h            |   5 ++
 tools/libs/light/libxl_arm.c     | 140 ++++++++++++++++++++++++++-----
 tools/libs/light/libxl_create.c  |   2 +
 tools/libs/light/libxl_types.idl |   1 +
 tools/xl/xl_parse.c              |   2 +
 6 files changed, 173 insertions(+), 23 deletions(-)

diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
index 2f77016ecfae..7ca7dba4d29d 100644
--- a/docs/man/xl.cfg.5.pod.in
+++ b/docs/man/xl.cfg.5.pod.in
@@ -1704,6 +1704,47 @@ i.e. enable grants if backend-domid != 0.
 
 =back
 
+=item B<realm=BOOLEAN>
+
+B<Arm only.> Create the guest as an Arm CCA Realm guest.
+
+Realm guests use the Arm PVH guest model and currently support only a
+minimal configuration:
+
+=over 4
+
+=item *
+
+type=E<quot>pvhE<quot>
+
+=item *
+
+guest RAM fully contained within the first guest RAM bank
+
+=item *
+
+GICv3 only
+
+=item *
+
+Xen-generated device tree only
+
+=item *
+
+no passthrough, no virtio, no Xen grant or IOMMU exposure to the guest,
+and no ACPI
+
+=back
+
+When B<realm=true>, Realm DTBs set the PSCI method to B<"smc">. They do
+not expose the Xen hypervisor node because this series does not provide
+Xen PV interfaces for Realm guests.
+
+Realm guests may use B<vuart="sbsa_uart"> only when Xen was built with
+B<CONFIG_ARM_CCA_REALM_DEBUG_VUART=y>. This is a host-visible clear-text
+debug console for Realm debug access, not a confidentiality-oriented guest
+access path.
+
 =item B<tee="STRING">
 
 B<Arm only.> Set TEE type for the guest. TEE is a Trusted Execution
@@ -3096,6 +3137,10 @@ vuart = "sbsa_uart"
 
 Currently, only the "sbsa_uart" model is supported for ARM.
 
+For Realm guests, B<vuart="sbsa_uart"> is supported with the same device
+model only when B<CONFIG_ARM_CCA_REALM_DEBUG_VUART=y>. The guest kernel should
+use C<ttyAMA0>.
+
 =back
 
 =over 4
@@ -3249,4 +3294,3 @@ documentation. Patches to improve incomplete items (or 
any other item)
 are gratefully received on the xen-devel@xxxxxxxxxxxxxxxxxxxx mailing
 list. Please see 
L<https://wiki.xenproject.org/wiki/Submitting_Xen_Project_Patches> for
 information on how to submit a patch to Xen.
-
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index 7c098edab663..9b9398401029 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -293,6 +293,11 @@
  */
 #define LIBXL_HAVE_BUILDINFO_ARM_GIC_VERSION 1
 
+/*
+ * libxl_domain_build_info has the realm field.
+ */
+#define LIBXL_HAVE_BUILDINFO_ARM_REALM 1
+
 /*
  * libxl_domain_build_info has the arch_arm.tee field.
  */
diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
index 7e9f8a1bc366..fa13703bb98b 100644
--- a/tools/libs/light/libxl_arm.c
+++ b/tools/libs/light/libxl_arm.c
@@ -80,6 +80,70 @@ static const char *gicv_to_string(libxl_gic_version 
gic_version)
     }
 }
 
+static bool arm_guest_is_realm(const libxl_domain_build_info *info)
+{
+    return libxl_defbool_val(info->realm);
+}
+
+static int arm_realm_reject(libxl__gc *gc, const char *what)
+{
+    LOG(ERROR, "Realm guests do not support %s", what);
+    return ERROR_INVAL;
+}
+
+static int arm_realm_check_config(libxl__gc *gc,
+                                  const libxl_domain_config *d_config)
+{
+    const libxl_domain_build_info *const info = &d_config->b_info;
+    const uint64_t bank0_memkb = GUEST_RAM0_SIZE >> 10;
+
+    if ( !arm_guest_is_realm(info) )
+        return 0;
+
+    if ( info->type != LIBXL_DOMAIN_TYPE_PVH )
+        return arm_realm_reject(gc, "non-PVH build types");
+
+    if ( info->target_memkb > bank0_memkb || info->max_memkb > bank0_memkb )
+        return arm_realm_reject(gc, "guest RAM beyond the first RAM bank");
+
+    if ( info->device_tree )
+        return arm_realm_reject(gc, "partial device trees");
+
+    if ( libxl_defbool_val(info->acpi) )
+        return arm_realm_reject(gc, "ACPI");
+
+    if ( info->arch_arm.gic_version != LIBXL_GIC_VERSION_V3 )
+        return arm_realm_reject(gc, "non-GICv3 interrupt controllers");
+
+    if ( info->tee != LIBXL_TEE_TYPE_NONE )
+        return arm_realm_reject(gc, "TEE/FF-A plumbing");
+
+    if ( info->num_irqs || info->num_iomem )
+        return arm_realm_reject(gc, "IRQ/IOMEM passthrough");
+
+    if ( info->num_vnuma_nodes )
+        return arm_realm_reject(gc, "vNUMA");
+
+    if ( d_config->c_info.passthrough != LIBXL_PASSTHROUGH_DISABLED )
+        return arm_realm_reject(gc, "passthrough mode");
+
+    if ( d_config->num_pcidevs || d_config->num_dtdevs )
+        return arm_realm_reject(gc, "passthrough devices");
+
+    if ( d_config->num_disks || d_config->num_nics ||
+         d_config->num_virtios || d_config->num_vkbs ||
+         d_config->num_p9s || d_config->num_pvcallsifs )
+        return arm_realm_reject(gc, "frontend/backend devices");
+
+    if ( d_config->num_vtpms || d_config->num_vfbs ||
+         d_config->num_vdispls || d_config->num_vsnds ||
+         d_config->num_channels || d_config->num_usbctrls ||
+         d_config->num_usbdevs )
+        return arm_realm_reject(gc, "auxiliary frontend devices");
+
+    return 0;
+}
+
 int libxl__arch_domain_prepare_config(libxl__gc *gc,
                                       libxl_domain_config *d_config,
                                       struct xen_domctl_createdomain *config)
@@ -92,6 +156,10 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
     uint32_t virtio_mmio_irq = GUEST_VIRTIO_MMIO_SPI_FIRST;
     int rc;
 
+    rc = arm_realm_check_config(gc, d_config);
+    if ( rc )
+        return rc;
+
     /*
      * If pl011 vuart is enabled then increment the nr_spis to allow allocation
      * of SPI VIRQ for pl011.
@@ -617,7 +685,7 @@ static int make_cpus_node(libxl__gc *gc, void *fdt, int 
nr_cpus,
     return 0;
 }
 
-static int make_psci_node(libxl__gc *gc, void *fdt)
+static int make_psci_node(libxl__gc *gc, void *fdt, bool realm)
 {
     int res;
 
@@ -628,7 +696,7 @@ static int make_psci_node(libxl__gc *gc, void *fdt)
                               "arm,psci-0.2", "arm,psci");
     if (res) return res;
 
-    res = fdt_property_string(fdt, "method", "hvc");
+    res = fdt_property_string(fdt, "method", realm ? "smc" : "hvc");
     if (res) return res;
 
     res = fdt_property_cell(fdt, "cpu_off", PSCI_cpu_off);
@@ -1363,7 +1431,7 @@ next_resize:
         FDT( make_root_properties(gc, vers, fdt) );
         FDT( make_chosen_node(gc, fdt, !!dom->modules[0].blob, state, info) );
         FDT( make_cpus_node(gc, fdt, info->max_vcpus, ainfo) );
-        FDT( make_psci_node(gc, fdt) );
+        FDT( make_psci_node(gc, fdt, arm_guest_is_realm(info)) );
 
         FDT( make_memory_nodes(gc, fdt, dom) );
 
@@ -1384,7 +1452,13 @@ next_resize:
         }
 
         FDT( make_timer_node(gc, fdt, ainfo, state->clock_frequency) );
-        FDT( make_hypervisor_node(gc, fdt, vers) );
+        /*
+         * Common domain creation may still allocate grant-table resources,
+         * but this is the guest-visible path to them. Realm guests
+         * deliberately omit Xen PV interfaces, including grant-table space.
+         */
+        if (!arm_guest_is_realm(info))
+            FDT( make_hypervisor_node(gc, fdt, vers) );
 
         if (info->arch_arm.vuart == LIBXL_VUART_TYPE_SBSA_UART)
             FDT( make_vpl011_uart_node(gc, fdt, ainfo, dom) );
@@ -1427,7 +1501,7 @@ next_resize:
          * The iommu node should be created only once for all virtio-mmio
          * devices.
          */
-        if (iommu_needed)
+        if (iommu_needed && !arm_guest_is_realm(info))
             FDT( make_xen_iommu_node(gc, fdt) );
 
         if (pfdt)
@@ -1559,6 +1633,9 @@ static int finalize_hypervisor_node(libxl__gc *gc,
     libxl_dominfo info;
     int offset, rc;
 
+    if ( arm_guest_is_realm(b_info) )
+        return 0;
+
     offset = fdt_path_offset(fdt, "/hypervisor");
     if (offset < 0)
         return offset;
@@ -1732,31 +1809,50 @@ int 
libxl__arch_domain_finalise_hw_description(libxl__gc *gc,
     return 0;
 }
 
+static int arm_realm_finalize_guest(libxl__gc *gc, struct xc_dom_image *dom)
+{
+    int rc;
+
+    if (dom->rambank_size[1] != 0) {
+        LOG(ERROR, "Realm guests must fit entirely within the first RAM bank");
+        return ERROR_INVAL;
+    }
+
+    rc = xc_arm_cca_init_realm(CTX->xch, dom->guest_domid,
+                               GUEST_RAM_BASE >> XC_PAGE_SHIFT,
+                               dom->rambank_size[0]);
+    if (rc < 0) {
+        LOGE(ERROR, "xc_arm_cca_init_realm failed");
+        return ERROR_FAIL;
+    }
+
+    return 0;
+}
+
 int libxl__arch_build_dom_finish(libxl__gc *gc,
                                  libxl_domain_build_info *info,
                                  struct xc_dom_image *dom,
                                  libxl__domain_build_state *state)
 {
-    int rc = 0, ret;
-
-    if (info->arch_arm.vuart != LIBXL_VUART_TYPE_SBSA_UART) {
-        rc = 0;
-        goto out;
+    int ret;
+
+    if (info->arch_arm.vuart == LIBXL_VUART_TYPE_SBSA_UART) {
+        ret = xc_dom_vuart_init(CTX->xch,
+                                XEN_DOMCTL_VUART_TYPE_VPL011,
+                                dom->guest_domid,
+                                dom->console_domid,
+                                dom->vuart_gfn,
+                                &state->vuart_port);
+        if (ret < 0) {
+            LOG(ERROR, "xc_dom_vuart_init failed\n");
+            return ERROR_FAIL;
+        }
     }
 
-    ret = xc_dom_vuart_init(CTX->xch,
-                            XEN_DOMCTL_VUART_TYPE_VPL011,
-                            dom->guest_domid,
-                            dom->console_domid,
-                            dom->vuart_gfn,
-                            &state->vuart_port);
-    if (ret < 0) {
-        rc = ERROR_FAIL;
-        LOG(ERROR, "xc_dom_vuart_init failed\n");
-    }
+    if (arm_guest_is_realm(info))
+        return arm_realm_finalize_guest(gc, dom);
 
-out:
-    return rc;
+    return 0;
 }
 
 int libxl__arch_vnuma_build_vmemrange(libxl__gc *gc,
diff --git a/tools/libs/light/libxl_create.c b/tools/libs/light/libxl_create.c
index bfc9149096a3..1401697ab1d4 100644
--- a/tools/libs/light/libxl_create.c
+++ b/tools/libs/light/libxl_create.c
@@ -407,6 +407,8 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
         libxl_defbool_setdefault(&b_info->nested_hvm,               false);
     }
 
+    libxl_defbool_setdefault(&b_info->realm, false);
+
     if (b_info->max_grant_version == LIBXL_MAX_GRANT_DEFAULT) {
         if (info.cap_gnttab_v2)
             b_info->max_grant_version = 2;
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index a7893460f013..d2fa3535ab18 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -657,6 +657,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
     ("apic",             libxl_defbool),
     ("dm_restrict",      libxl_defbool),
     ("tee",              libxl_tee_type),
+    ("realm",            libxl_defbool),
     ("u", KeyedUnion(None, libxl_domain_type, "type",
                 [("hvm", Struct(None, [("firmware",         string),
                                        ("bios",             libxl_bios_type),
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index 48c72dce9c6d..742c203a0326 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -3058,6 +3058,8 @@ skip_usbdev:
         }
     }
 
+    xlu_cfg_get_defbool(config, "realm", &b_info->realm, 0);
+
     if (!xlu_cfg_get_string (config, "sve", &buf, 1)) {
         e = libxl_sve_type_from_string(buf, &b_info->arch_arm.sve_vl);
         if (e) {
-- 
2.51.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.