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

[RFC PATCH v1 24/26] xen/arm, tools: add domctl for Realm finalization


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Koichiro Den <den@xxxxxxxxxxxxx>
  • Date: Fri, 15 May 2026 13:08:10 +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=j+krazXWRn2IuLifiPb7Tk1sDo3QwLMY07VSIfj1R9Q=; b=JLf/JE1AvzGG77CrgGrsAcnKvu/5rl5t7Dox0sd3K0A3AGhdJmn8Q4MH6idQDO4uuK1mU2DlPCJmnY4YMzc9euGhVFm4K6C5nchPOd+Ud9wU5J/N0rKmPRws9P6Un+lKcZ8kJiuHCInDEzH7rbEdurk/6xmihINLkcEMBWBgHRCr6VJ33KDh3haqXklaWVm408zfZg39q8rjvnWoC3nteTPO9EWPgen34TpirXfFIvEVYOS+j7LzcIfHE0m/iT05RlX3pIpH67F64QVXDakpjb+YEpuga+Ykk1nySmoM+vz2ReJwJ/ooqmf1J/LbWeiVVRQ3Y92RK0oTB987GV7R/A==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=CL7k9eAPnqhprtJL9gq5e6Uvy1RbIs0+K4ile2ZQU/gp19XQxVncZNG0Zvaog81fp/26iu51TNwGeWK6WjLPRlkWoq1WeVv7xM0CW27CI2tFEdRi+18Y8C8DKJ1GuKjsaOqoD2+KeVHd0mHl4AUiPr5SPY+cG4PDxIkj3qYgBs/WXYZR2YCOJTRp5Fgt8WMDCb2GQqMH2s+ftUZwOoybquSWEOcnZUwAwjEaqT8gOFK1T227mnLotM9sACIffpaZzaJoDA+GRYZ85NQtTng+r32GpOhRufUGmB34YErV/fbaHRATFG6wCPFy2z7PDnAoWEIiFtSzCeK3MBc9QpogIg==
  • 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:08:49 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Add the domctl, libxc wrapper and XSM permission used by libxl to turn a
paused Arm guest into a Realm. RMI failures are reported back as-is.

Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
 tools/flask/policy/modules/xen.if   |  1 +
 tools/include/xenctrl.h             | 12 ++++++
 tools/libs/ctrl/xc_domain.c         | 37 ++++++++++++++++++
 xen/arch/arm/domctl.c               | 60 +++++++++++++++++++++++++++++
 xen/include/public/domctl.h         | 12 ++++++
 xen/xsm/flask/hooks.c               |  3 ++
 xen/xsm/flask/policy/access_vectors |  2 +
 7 files changed, 127 insertions(+)

diff --git a/tools/flask/policy/modules/xen.if 
b/tools/flask/policy/modules/xen.if
index ef7d8f438c65..5eb2d98341e9 100644
--- a/tools/flask/policy/modules/xen.if
+++ b/tools/flask/policy/modules/xen.if
@@ -98,6 +98,7 @@ define(`create_domain_common', `
                vuart_op
                set_llc_colors
                get_domain_state
+               arm_cca_op
        };
        allow $1 $2:security check_context;
        allow $1 $2:shadow enable;
diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h
index d5dbf69c8968..149e15f7c531 100644
--- a/tools/include/xenctrl.h
+++ b/tools/include/xenctrl.h
@@ -808,6 +808,18 @@ int xc_dom_vuart_init(xc_interface *xch,
                       xen_pfn_t gfn,
                       evtchn_port_t *evtchn);
 
+/*
+ * Finalize a paused ARM domain as a Realm backed by RMM. The toolstack is
+ * expected to have already built a normal ARM guest image in the domain RAM.
+ *
+ * Returns 0 on success, or -1 with errno set. If Xen receives an RMI error
+ * result from RMM, libxc logs the raw RMI result and reports EPROTO.
+ */
+int xc_arm_cca_init_realm(xc_interface *xch,
+                          uint32_t domid,
+                          xen_pfn_t base_gfn,
+                          uint64_t nr_pages);
+
 /**
  * This function returns information about the XSAVE state of a particular
  * vcpu of a domain. If extstate->size and extstate->xfeature_mask are 0,
diff --git a/tools/libs/ctrl/xc_domain.c b/tools/libs/ctrl/xc_domain.c
index 01c0669c8863..3cb8da9cc07d 100644
--- a/tools/libs/ctrl/xc_domain.c
+++ b/tools/libs/ctrl/xc_domain.c
@@ -345,6 +345,43 @@ int xc_dom_vuart_init(xc_interface *xch,
     return rc;
 }
 
+int xc_arm_cca_init_realm(xc_interface *xch,
+                          uint32_t domid,
+                          xen_pfn_t base_gfn,
+                          uint64_t nr_pages)
+{
+    struct xen_domctl domctl = {};
+    int rc;
+
+    memset(&domctl, 0, sizeof(domctl));
+
+    domctl.cmd = XEN_DOMCTL_arm_cca_op;
+    domctl.domain = domid;
+    domctl.u.arm_cca_op.cmd = XEN_DOMCTL_ARM_CCA_OP_INIT_REALM;
+    domctl.u.arm_cca_op.flags = 0;
+    domctl.u.arm_cca_op.base_gfn = base_gfn;
+    domctl.u.arm_cca_op.nr_pages = nr_pages;
+
+    rc = do_domctl(xch, &domctl);
+    if ( rc < 0 )
+    {
+        if ( domctl.u.arm_cca_op.rmi_result )
+        {
+            xc_report_error(xch, XC_INTERNAL_ERROR,
+                            "xc_arm_cca_init_realm failed with raw RMI "
+                            "result 0x%llx",
+                            (unsigned long long)
+                            domctl.u.arm_cca_op.rmi_result);
+            errno = EPROTO;
+            return -1;
+        }
+
+        return rc;
+    }
+
+    return rc;
+}
+
 int xc_domain_getinfo_single(xc_interface *xch,
                              uint32_t domid,
                              xc_domaininfo_t *info)
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index ad914c915f81..36461eeda633 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -16,6 +16,7 @@
 #include <xen/types.h>
 #include <xsm/xsm.h>
 #include <public/domctl.h>
+#include <public/sched.h>
 
 void arch_get_domain_info(const struct domain *d,
                           struct xen_domctl_getdomaininfo *info)
@@ -49,6 +50,42 @@ static int handle_vuart_init(struct domain *d,
     return rc;
 }
 
+static int handle_arm_cca_init_realm(struct domain *d,
+                                     struct xen_domctl_arm_cca_op *cca_op)
+{
+#ifdef CONFIG_ARM_CCA
+    uint64_t rmi_result = 0;
+    int rc;
+#endif
+
+    if ( cca_op->flags )
+        return -EINVAL;
+
+    cca_op->rmi_result = 0;
+
+#ifdef CONFIG_ARM_CCA
+    rc = arm_cca_domain_finalize(d, _gfn(cca_op->base_gfn),
+                                 cca_op->nr_pages, &rmi_result);
+
+    /*
+     * Once Realm data conversion starts, the original guest RAM image can no
+     * longer be trusted after a failed finalization attempt.
+     */
+    if ( rc == -EIO )
+        domain_shutdown(d, SHUTDOWN_crash);
+
+    if ( rc == -EIO && rmi_result )
+    {
+        cca_op->rmi_result = rmi_result;
+        return rc;
+    }
+
+    return rc;
+#else
+    return -EOPNOTSUPP;
+#endif
+}
+
 long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
                     XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
 {
@@ -177,6 +214,29 @@ long arch_do_domctl(struct xen_domctl *domctl, struct 
domain *d,
 
         return rc;
     }
+    case XEN_DOMCTL_arm_cca_op:
+    {
+        struct xen_domctl_arm_cca_op *cca_op = &domctl->u.arm_cca_op;
+
+        switch ( cca_op->cmd )
+        {
+        case XEN_DOMCTL_ARM_CCA_OP_INIT_REALM:
+        {
+            long rc = handle_arm_cca_init_realm(d, cca_op);
+
+            if ( rc == -ERESTART )
+                rc = hypercall_create_continuation(__HYPERVISOR_domctl,
+                                                   "h", u_domctl);
+            else if ( rc == -EIO && cca_op->rmi_result &&
+                      copy_to_guest(u_domctl, domctl, 1) )
+                rc = -EFAULT;
+
+            return rc;
+        }
+        default:
+            return -EINVAL;
+        }
+    }
     case XEN_DOMCTL_dt_overlay:
         return dt_overlay_domctl(d, &domctl->u.dt_overlay);
     default:
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 8f6708c0a7cd..2562647d93d3 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -1201,6 +1201,16 @@ struct xen_domctl_vuart_op {
                                  */
 };
 
+/* XEN_DOMCTL_arm_cca_op */
+struct xen_domctl_arm_cca_op {
+#define XEN_DOMCTL_ARM_CCA_OP_INIT_REALM  0
+        uint32_t cmd;              /* IN - XEN_DOMCTL_ARM_CCA_OP_* */
+        uint32_t flags;            /* IN - reserved, must be zero */
+        uint64_aligned_t base_gfn;   /* IN - first guest RAM gfn to protect */
+        uint64_aligned_t nr_pages;   /* IN - number of 4K pages to protect */
+        uint64_aligned_t rmi_result; /* OUT - raw RMI result on -EIO */
+};
+
 /* XEN_DOMCTL_vmtrace_op: Perform VM tracing operations. */
 struct xen_domctl_vmtrace_op {
     uint32_t cmd;           /* IN */
@@ -1368,6 +1378,7 @@ struct xen_domctl {
 #define XEN_DOMCTL_gsi_permission                88
 #define XEN_DOMCTL_set_llc_colors                89
 #define XEN_DOMCTL_get_domain_state              90 /* stable interface */
+#define XEN_DOMCTL_arm_cca_op                    91
 #define XEN_DOMCTL_gdbsx_guestmemio            1000
 #define XEN_DOMCTL_gdbsx_pausevcpu             1001
 #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
@@ -1429,6 +1440,7 @@ struct xen_domctl {
         struct xen_domctl_monitor_op        monitor_op;
         struct xen_domctl_psr_alloc         psr_alloc;
         struct xen_domctl_vuart_op          vuart_op;
+        struct xen_domctl_arm_cca_op        arm_cca_op;
         struct xen_domctl_vmtrace_op        vmtrace_op;
         struct xen_domctl_paging_mempool    paging_mempool;
 #if defined(__arm__) || defined(__aarch64__)
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 28522dcbd271..f95552992a26 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -805,6 +805,9 @@ static int cf_check flask_domctl(struct domain *d, unsigned 
int cmd,
     case XEN_DOMCTL_vuart_op:
         return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__VUART_OP);
 
+    case XEN_DOMCTL_arm_cca_op:
+        return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__ARM_CCA_OP);
+
     case XEN_DOMCTL_get_cpu_policy:
         return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__GET_CPU_POLICY);
 
diff --git a/xen/xsm/flask/policy/access_vectors 
b/xen/xsm/flask/policy/access_vectors
index bbb9c117ec4a..dee895bef673 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -253,6 +253,8 @@ class domain2
     set_llc_colors
 # XEN_DOMCTL_get_domain_state
     get_domain_state
+# XEN_DOMCTL_arm_cca_op
+    arm_cca_op
 }
 
 # Similar to class domain, but primarily contains domctls related to HVM 
domains
-- 
2.51.0




 


Rackspace

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