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

[RFC PATCH v1 23/26] xen/arm/cca: handle Realm RIPAS and GIC sysreg exits


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Koichiro Den <den@xxxxxxxxxxxxx>
  • Date: Fri, 15 May 2026 13:08:09 +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=S5/dP4DpjlJzyHFiGX9Dvr0WUYwSm5khsV8ePzx5S4I=; b=nmXuiUvdJ3Flt5/DT6NdKZ+A+dIDNxEmujoQV8WKWtYx4BU9X0SopJBgOr89fzHVPDAntfmSiHlnT5nNK9HD+Wo5R6ApOLUPQgydzW3Pk+PUOJLgFoAg+ql2VKFFV/QiRIE+9exzqW6+o1Amef6g/89ktFiso/zxjbRclDSaWmrp3j3d5Z7+47wE4jB2+xjJzpSfyy9KkwEl6z4piJ+lSnpUgxXV5ZxmSeUEW86aQo/AKW+hqbVmFoSH/tpQDmIlsKZ+sQSa7nWmyirpwD/16aEcN78nFBhjt50hbZxk27oXHF10mSh5ZD3Ll3j5bmFQsoxxOrJ36ZbftXFsESRIJQ==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=KHS27FapKNanGflrIFw/hM2kwNkQX/WePq3xlEM6xUNYPVEYtmx9BWO1Z6lo57SRVOTwKuWv/ZAJVGpMYzH/t45gcDmFMPL1TpT2xoz3DMHu0x4mJ25XYlLDKFkJ2k/pQfa7vfCntNIiyNowixl92fsBWYKmN/RVp5nEVX9ukyEYCxAd6vtJRwOOq2LhVMVcC4+is4oVh7CikZ9lWQMnKq0BINvo4jlkHpm0fg7JFXCeTT/ELG9LUT2CbPQtXyK32qdst02MDTmNjd1lSMdfBxhjdxGAoDxCMDE6HHyVHjLxUlzHs+p7zQnHi81MjMV7GtcnDF1bsUi9BOaLbfAQ3Q==
  • 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:48 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Handle RIPAS changes and selected GICv3 sysreg exits. RIPAS work runs
before the next REC entry, and sysreg transfers use ESR_EL2.ISS.Rt.

Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
 xen/arch/arm/cca/rec.c | 209 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 206 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/cca/rec.c b/xen/arch/arm/cca/rec.c
index efff7fa48745..7959fb767e11 100644
--- a/xen/arch/arm/cca/rec.c
+++ b/xen/arch/arm/cca/rec.c
@@ -399,6 +399,66 @@ static void arm_cca_set_mmio_result(unsigned long 
*entry_flags,
     entry_gprs[0] = value;
 }
 
+static register_t
+arm_cca_rec_exit_gpr(const struct arm_cca_rmi_rec_exit *exit,
+                     unsigned int reg)
+{
+    return reg < ARM_CCA_RMI_REC_NR_GPRS ? exit->gprs[reg] : 0;
+}
+
+static void arm_cca_rec_enter_set_gpr(register_t *entry_gprs,
+                                      unsigned int reg,
+                                      register_t value)
+{
+    if ( reg < ARM_CCA_RMI_REC_NR_GPRS )
+        entry_gprs[reg] = value;
+}
+
+static bool arm_cca_vgic_emulate_sgi1r(struct vcpu *v, register_t sgir)
+{
+    return vgic_v3_to_sgi(v, sgir);
+}
+
+static bool arm_cca_vgic_emulate_dir(struct vcpu *v, register_t dir)
+{
+    unsigned int virq = dir & GICC_IAR_INTID_MASK;
+    struct gic_lr lr;
+    unsigned int i;
+
+    /*
+     * RMM may exit to Xen for Realm ICC_DIR_EL1 accesses.  Handle the
+     * deactivation locally when Xen can find a matching software LR.
+     * DEN0137 2.0-bet1 - A6.1 Realm interrupts.
+     */
+    if ( virq >= vgic_num_irqs(v->domain) )
+        return true;
+
+    for ( i = 0; i < gic_get_nr_lrs(); i++ )
+    {
+        gic_hw_ops->read_lr(i, &lr);
+
+        if ( lr.virq != virq || !lr.active )
+            continue;
+
+        if ( lr.hw_status )
+        {
+            gprintk(XENLOG_ERR,
+                    "ARM CCA: ICC_DIR_EL1 on hw-backed vIRQ %u is 
unsupported\n",
+                    virq);
+            return false;
+        }
+
+        lr.active = false;
+        gic_hw_ops->write_lr(i, &lr);
+        isb();
+        vgic_sync_from_lrs(v);
+
+        return true;
+    }
+
+    return true;
+}
+
 static void arm_cca_request_sea(unsigned long *entry_flags,
                                 register_t *entry_gprs)
 {
@@ -560,6 +620,87 @@ static void arm_cca_handle_psci_exit(struct vcpu *v,
     }
 }
 
+/*
+ * DEN0137 2.0-bet1 - D1.5.3 RIPAS change flow.
+ * RIPAS_EMPTY and RIPAS_RAM changes are applied with RMI_RTT_SET_RIPAS.
+ * RIPAS_DEV requires VDEV mapping validation support, while RIPAS_DESTROYED
+ * is not a Realm-requested target state.
+ */
+static void
+arm_cca_handle_ripas_change(struct vcpu *v,
+                            const struct arm_cca_rmi_rec_exit *exit,
+                            unsigned long *entry_flags)
+{
+    struct arm_smccc_res res;
+    paddr_t base = exit->ripas_base;
+    paddr_t top = exit->ripas_top;
+    int rc;
+
+    if ( v->domain->arch.cca.rd == INVALID_PADDR )
+    {
+        gprintk(XENLOG_ERR,
+                "ARM CCA: missing RD for RIPAS completion\n");
+        arm_cca_domain_crash(v);
+    }
+
+    switch ( exit->ripas_value )
+    {
+    case ARM_CCA_RMI_RIPAS_EMPTY:
+    case ARM_CCA_RMI_RIPAS_RAM:
+        break;
+
+    default:
+        gprintk(XENLOG_ERR,
+                "ARM CCA: unsupported RIPAS change value=%u "
+                "range=%#lx-%#lx\n",
+                (unsigned int)exit->ripas_value,
+                (unsigned long)base, (unsigned long)top);
+        arm_cca_domain_crash(v);
+    }
+
+    /*
+     * Note that RMI_RTT_SET_RIPAS uses the pending request recorded in the
+     * REC, so the Host does not pass the target RIPAS value explicitly here.
+     *
+     * Xen accepts the request while progress is possible. If a RIPAS_RAM
+     * request reaches a point the RMM cannot change, report Host rejection on
+     * the next REC_ENTER so the Realm sees the normal RSI response.
+     */
+    while ( base < top )
+    {
+        rc = arm_cca_rmi_rtt_set_ripas(v->domain->arch.cca.rd,
+                                       v->arch.cca.rec,
+                                       base, top, &res);
+        if ( rc != 0 )
+        {
+            if ( exit->ripas_value == ARM_CCA_RMI_RIPAS_RAM &&
+                 arm_cca_rmi_status_is(arm_cca_rmi_result(&res),
+                                       ARM_CCA_RMI_ERROR_RTT) )
+            {
+                /* The RIPAS response flag value 1 means Host reject. */
+                *entry_flags |= ARM_CCA_RMI_REC_ENTER_FLAG_RIPAS_RESPONSE;
+                return;
+            }
+
+            gprintk(XENLOG_ERR,
+                    "ARM CCA: RMI_RTT_SET_RIPAS failed status=%#x data=%#lx\n",
+                    arm_cca_rmi_status_code(arm_cca_rmi_result(&res)),
+                    (unsigned long)arm_cca_rmi_result_data(
+                        arm_cca_rmi_result(&res)));
+            arm_cca_domain_crash(v);
+        }
+
+        if ( res.a1 <= base || res.a1 > top )
+        {
+            gprintk(XENLOG_ERR,
+                    "ARM CCA: invalid RIPAS progress %#lx -> %#lx (top 
%#lx)\n",
+                    (unsigned long)base, res.a1, (unsigned long)top);
+            arm_cca_domain_crash(v);
+        }
+
+        base = res.a1;
+    }
+}
 
 /*
  * DEN0137 2.0-bet1 - D1.3.3 REC exit due to Data Abort fault flow.
@@ -573,6 +714,55 @@ static void arm_cca_handle_sync_exit(struct vcpu *v,
 
     switch ( hsr.ec )
     {
+    case HSR_EC_SYSREG:
+    {
+        unsigned int rt = hsr.sysreg.reg;
+        register_t val = arm_cca_rec_exit_gpr(exit, rt);
+
+        /*
+         * Realm guests use the GICv3 sysreg CPU interface:
+         * - Linux expects ICC_SRE_EL1.SRE to read as enabled.
+         * - SGI generation and explicit deactivate stay in Xen's vGIC path.
+         *
+         * DEN0137 2.0-bet1 A6.1 makes ICC_* traps System register exits,
+         * but A4.3.4.4 only guarantees ESR.  Use the Rt encoded in ESR_EL2.ISS
+         * for the transfer GPR.  Current TF-RMM clears Rt for these exits,
+         * making this equivalent to its gprs[0] convention.
+         */
+        switch ( hsr.bits & HSR_SYSREG_REGS_MASK )
+        {
+        case HSR_SYSREG_ICC_SRE_EL1:
+            arm_cca_rec_enter_set_gpr(entry_gprs, rt,
+                                      ARM_CCA_ICC_SRE_EL1_VALUE);
+            break;
+        case HSR_SYSREG_ICC_DIR_EL1:
+            if ( hsr.sysreg.read ||
+                 !arm_cca_vgic_emulate_dir(v, val) )
+            {
+                gprintk(XENLOG_ERR,
+                        "ARM CCA: unsupported ICC_DIR_EL1 access read=%u 
val=%#lx\n",
+                        hsr.sysreg.read, val);
+                arm_cca_domain_crash(v);
+            }
+            break;
+        case HSR_SYSREG_ICC_SGI1R_EL1:
+            if ( hsr.sysreg.read ||
+                 !arm_cca_vgic_emulate_sgi1r(v, val) )
+            {
+                gprintk(XENLOG_ERR,
+                        "ARM CCA: unsupported ICC_SGI1R_EL1 access read=%u 
val=%#lx\n",
+                        hsr.sysreg.read, val);
+                arm_cca_domain_crash(v);
+            }
+            break;
+        default:
+            gprintk(XENLOG_ERR,
+                    "ARM CCA: unsupported SYSREG ec=%#x sysreg=%#lx\n",
+                    hsr.ec, (unsigned long)(hsr.bits & HSR_SYSREG_REGS_MASK));
+            arm_cca_domain_crash(v);
+        }
+        break;
+    }
     case HSR_EC_WFI_WFE:
         /*
          * DEN0137 2.0-bet1 - A4.3.4.1 REC exit due to WFI or WFE.
@@ -619,6 +809,7 @@ void noreturn arm_cca_vcpu_run(struct vcpu *v)
     struct arm_smccc_res res;
     unsigned long entry_flags;
     register_t entry_gprs[ARM_CCA_RMI_REC_NR_GPRS];
+    bool pending_ripas = false;
     int rc;
 
     ASSERT(v == current);
@@ -663,6 +854,19 @@ void noreturn arm_cca_vcpu_run(struct vcpu *v)
         arm_cca_check_for_vcpu_work(v);
         arm_cca_service_host_events();
 
+        /*
+         * RMI_RTT_SET_RIPAS can cover a large range.  The REC exit buffer
+         * remains valid until the next REC_ENTER, so complete the request
+         * here with IRQs enabled rather than in the exit dispatch path.
+         */
+        if ( pending_ripas )
+        {
+            local_irq_enable();
+            arm_cca_handle_ripas_change(v, &run->exit, &entry_flags);
+            local_irq_disable();
+            pending_ripas = false;
+        }
+
         arm_cca_prepare_rec_enter(run, entry_flags, entry_gprs);
         entry_flags = ARM_CCA_RMI_REC_ENTER_FLAG_TRAP_WFI |
                       ARM_CCA_RMI_REC_ENTER_FLAG_TRAP_WFE;
@@ -700,9 +904,8 @@ void noreturn arm_cca_vcpu_run(struct vcpu *v)
             break;
 
         case ARM_CCA_RMI_EXIT_RIPAS_CHANGE:
-            gprintk(XENLOG_ERR,
-                    "ARM CCA: RIPAS change exits are unsupported\n");
-            arm_cca_domain_crash(v);
+            pending_ripas = true;
+            break;
 
         case ARM_CCA_RMI_EXIT_SYNC:
             arm_cca_handle_sync_exit(v, &run->exit, &entry_flags,
-- 
2.51.0




 


Rackspace

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