|
[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
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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |