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

[RFC PATCH v1 21/26] xen/arm/cca: add Realm vCPU timer state


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Koichiro Den <den@xxxxxxxxxxxxx>
  • Date: Fri, 15 May 2026 13:08:07 +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=S1HxX8zYRrTCNBvxhpZ+y28N68FN7W38vZ7TVisM/bg=; b=BfnGHp5+NGIW/3h41SWaBuhVNDgsWFtVh0q6uE0C7iZJyYekKPMTFUANsCO8H3LozPN6kZwcQhYgT/wV1mM1mg4rgw90xzja1IL10UcDCSjmTImQf0qSrw3EV5dSpbPa+18Bg9lRUhpO36bFjrFnFE8L2n9hWHkhZKQhZzTO3h6PCR8/smRZkWDMRS5VRZCpvg7xg4j68c4K4KdB9l+UuTDVPOir87tsvYpp4lGkk5hrwgZu/JckICeCnwjv8SpYnAaZGjQi0wfgRxyVp+2PvnXzWmNeVNlUY+8qYoCjZBfd14EQDt3HeASCYC6twyY66yc6ls92eZhUTFmcOGMc+Q==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=HA06MtBcnpkwE0Cqf2kjqUkO/DvAm2x3nhmIe+AMCI0v7Thz8LUADuRv7z18pWHuPDXsEHFXs2gQDKAERXCDlq/GGvKA7PRxdp3h8s5/fpJioH6T7twL5T/r5f6lIgedMUAypzLnzl3YZCEV4SSGlNZS+w2C0FHLkExE6W5HQdOaIcITegPYtoSOs/HlNH+7HJfY3NO61YPIxyWKDoxOMAscww6+czkY4KGrniIsXhwgZw9Mfju5mR//vOzShUFv7G+f6flkvLPGi6q/CHZhw1qZmGlFBUCMmlGxzlq6VpjgQzu0eW+KJjBk5YXnlkbReJaOydTgGAJ2cFGdHBYvXg==
  • 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:12:44 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Keep Realm timer state separate from the normal guest timer registers.
The RMM reports timer snapshots on REC exit.

Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
 xen/arch/arm/cca/Makefile      |  1 +
 xen/arch/arm/cca/build.c       | 10 +++-
 xen/arch/arm/cca/rec.c         | 90 ++++++++++++++++++++++++++++++++++
 xen/arch/arm/cca/state.c       |  3 ++
 xen/arch/arm/domain.c          |  6 ++-
 xen/arch/arm/include/asm/cca.h |  5 ++
 6 files changed, 112 insertions(+), 3 deletions(-)
 create mode 100644 xen/arch/arm/cca/rec.c

diff --git a/xen/arch/arm/cca/Makefile b/xen/arch/arm/cca/Makefile
index 0e66280012b7..b473132c1a67 100644
--- a/xen/arch/arm/cca/Makefile
+++ b/xen/arch/arm/cca/Makefile
@@ -4,3 +4,4 @@ obj-y += rmi.o
 obj-y += sro.o
 obj-y += state.o
 obj-y += build.o
+obj-y += rec.o
diff --git a/xen/arch/arm/cca/build.c b/xen/arch/arm/cca/build.c
index 29eb0c6057b0..18e825eec83a 100644
--- a/xen/arch/arm/cca/build.c
+++ b/xen/arch/arm/cca/build.c
@@ -851,7 +851,7 @@ static int arm_cca_create_rec(struct domain *d, struct vcpu 
*v, bool runnable,
     struct arm_cca_rmi_rec_params *params;
     struct page_info *rec_pg = NULL;
     struct page_info *params_pg = NULL;
-    bool rec_delegated = false, run_created = false;
+    bool rec_delegated = false, run_created = false, timers_created = false;
     void *va;
     int rc = -ENOMEM;
 
@@ -872,6 +872,11 @@ static int arm_cca_create_rec(struct domain *d, struct 
vcpu *v, bool runnable,
         run_created = true;
     }
 
+    rc = arm_cca_vcpu_timer_init(v);
+    if ( rc != 0 )
+        goto out;
+    timers_created = true;
+
     rc = arm_cca_delegate_granule(page_to_maddr(rec_pg));
     if ( rc != 0 )
         goto out;
@@ -913,6 +918,9 @@ out:
     if ( rc != 0 && rec_pg )
         arm_cca_free_or_abandon_build_page(d, rec_pg, rec_delegated);
 
+    if ( rc != 0 && timers_created )
+        arm_cca_vcpu_timer_destroy(v);
+
     if ( rc != 0 && run_created )
     {
         arm_cca_free_rec_run(v->arch.cca.run);
diff --git a/xen/arch/arm/cca/rec.c b/xen/arch/arm/cca/rec.c
new file mode 100644
index 000000000000..8314a7a45d95
--- /dev/null
+++ b/xen/arch/arm/cca/rec.c
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <xen/lib.h>
+#include <xen/sched.h>
+#include <xen/timer.h>
+#include <xen/xmalloc.h>
+
+#include <asm/cca.h>
+#include <asm/time.h>
+#include <asm/vgic.h>
+
+struct arm_cca_timer {
+    struct vcpu *v;
+    unsigned int irq;
+    struct timer timer;
+    register_t ctl;
+    uint64_t cval;
+};
+
+struct arm_cca_vcpu_timers {
+    struct arm_cca_timer phys;
+    struct arm_cca_timer virt;
+    struct timer wfx;
+};
+
+static void arm_cca_timer_update_irq(struct arm_cca_timer *timer)
+{
+    register_t ctl = timer->ctl;
+    bool level;
+
+    ctl &= (CNTx_CTL_ENABLE | CNTx_CTL_PENDING | CNTx_CTL_MASK);
+    level = (ctl == (CNTx_CTL_ENABLE | CNTx_CTL_PENDING));
+
+    vgic_inject_irq(timer->v->domain, timer->v, timer->irq, level);
+}
+
+static void arm_cca_timer_expired(void *data)
+{
+    struct arm_cca_timer *timer = data;
+
+    timer->ctl |= CNTx_CTL_PENDING;
+    arm_cca_timer_update_irq(timer);
+}
+
+static void arm_cca_wfx_timer_expired(void *data)
+{
+    vcpu_unblock(data);
+}
+
+static void arm_cca_timer_init(struct vcpu *v, struct arm_cca_timer *timer,
+                               unsigned int irq)
+{
+    init_timer(&timer->timer, arm_cca_timer_expired, timer, v->processor);
+    timer->v = v;
+    timer->irq = irq;
+    timer->ctl = 0;
+    timer->cval = 0;
+}
+
+int arm_cca_vcpu_timer_init(struct vcpu *v)
+{
+    struct arm_cca_vcpu_timers *timers;
+
+    ASSERT(!v->arch.cca.timers);
+
+    timers = xzalloc(struct arm_cca_vcpu_timers);
+    if ( !timers )
+        return -ENOMEM;
+
+    v->arch.cca.timers = timers;
+
+    arm_cca_timer_init(v, &timers->phys, GUEST_TIMER_PHYS_NS_PPI);
+    arm_cca_timer_init(v, &timers->virt, GUEST_TIMER_VIRT_PPI);
+    init_timer(&timers->wfx, arm_cca_wfx_timer_expired, v, v->processor);
+
+    return 0;
+}
+
+void arm_cca_vcpu_timer_destroy(struct vcpu *v)
+{
+    struct arm_cca_vcpu_timers *timers = v->arch.cca.timers;
+
+    if ( !timers )
+        return;
+
+    kill_timer(&timers->phys.timer);
+    kill_timer(&timers->virt.timer);
+    kill_timer(&timers->wfx);
+    XFREE(v->arch.cca.timers);
+}
diff --git a/xen/arch/arm/cca/state.c b/xen/arch/arm/cca/state.c
index d85a20a9e7d2..03e0d1d2382b 100644
--- a/xen/arch/arm/cca/state.c
+++ b/xen/arch/arm/cca/state.c
@@ -51,6 +51,7 @@ static void arm_cca_reset_vcpu_state(struct vcpu *v)
     v->arch.cca.rec = INVALID_PADDR;
     v->arch.cca.run = NULL;
     v->arch.cca.run_pa = INVALID_PADDR;
+    v->arch.cca.timers = NULL;
     v->arch.cca.rec_page = NULL;
     v->arch.cca.nr_aux = 0;
 
@@ -439,6 +440,8 @@ void arm_cca_vcpu_init(struct vcpu *v)
 
 void arm_cca_vcpu_destroy(struct vcpu *v)
 {
+    arm_cca_vcpu_timer_destroy(v);
+
     if ( v->arch.cca.run )
         arm_cca_free_rec_run(v->arch.cca.run);
 
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 2d9469f388c6..d2ee90248a44 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -113,7 +113,8 @@ static void ctxt_switch_from(struct vcpu *p)
 
     /* Arch timer */
     p->arch.cntkctl = READ_SYSREG(CNTKCTL_EL1);
-    virt_timer_save(p);
+    if ( !is_vcpu_realm(p) )
+        virt_timer_save(p);
 
 #ifdef CONFIG_ARM_32
     p->arch.joscr = READ_CP32(JOSCR);
@@ -265,7 +266,8 @@ static void ctxt_switch_to(struct vcpu *n)
     /* This is could trigger an hardware interrupt from the virtual
      * timer. The interrupt needs to be injected into the guest. */
     WRITE_SYSREG(n->arch.cntkctl, CNTKCTL_EL1);
-    virt_timer_restore(n);
+    if ( !is_vcpu_realm(n) )
+        virt_timer_restore(n);
 
     WRITE_SYSREG(n->arch.mdcr_el2, MDCR_EL2);
 }
diff --git a/xen/arch/arm/include/asm/cca.h b/xen/arch/arm/include/asm/cca.h
index 5e6b11a3693d..323988b379ba 100644
--- a/xen/arch/arm/include/asm/cca.h
+++ b/xen/arch/arm/include/asm/cca.h
@@ -29,6 +29,7 @@ struct vcpu;
 struct arm_cca_rmi_realm_params;
 struct arm_cca_rmi_rec_params;
 struct arm_cca_rmi_rec_run;
+struct arm_cca_vcpu_timers;
 struct page_info;
 
 struct arm_cca_rtt_record {
@@ -99,6 +100,8 @@ struct arm_cca_vcpu_state {
     void *run;
     paddr_t run_pa;
 
+    struct arm_cca_vcpu_timers *timers;
+
     struct page_info *rec_page;
     struct page_info *aux_pages[ARM_CCA_MAX_REC_AUX];
     unsigned int nr_aux;
@@ -114,6 +117,8 @@ int arm_cca_domain_finalize(struct domain *d, gfn_t 
base_gfn,
 void arm_cca_vcpu_init(struct vcpu *v);
 void noreturn arm_cca_vcpu_run(struct vcpu *v);
 void arm_cca_vcpu_destroy(struct vcpu *v);
+int arm_cca_vcpu_timer_init(struct vcpu *v);
+void arm_cca_vcpu_timer_destroy(struct vcpu *v);
 
 void *arm_cca_alloc_rec_run(void);
 void arm_cca_free_rec_run(void *run);
-- 
2.51.0




 


Rackspace

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