As AArch64v8R only has one secure state, we have to use secure EL2 hypervisor
timer for Xen in secure EL2.

In this patch, we introduce a Kconfig option ARM_SECURE_STATE.
With this new Kconfig option, we can re-define the timer's
system register name in different secure state, but keep the
timer code flow unchanged.

Signed-off-by: Penny Zheng <penny.zh...@arm.com>
Signed-off-by: Wei Chen <wei.c...@arm.com>
---
 xen/arch/arm/Kconfig                     |  7 +++++++
 xen/arch/arm/include/asm/arm64/sysregs.h | 21 ++++++++++++++++++++-
 xen/arch/arm/include/asm/cpregs.h        |  4 ++--
 xen/arch/arm/time.c                      | 14 +++++++-------
 4 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 91491341c4..ee942a33bc 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -47,6 +47,13 @@ config ARM_EFI
          be booted as an EFI application. This is only useful for
          Xen that may run on systems that have UEFI firmware.
 
+config ARM_SECURE_STATE
+       bool "Xen will run in Arm Secure State"
+       depends on ARM_V8R
+       help
+         In this state, a Processing Element (PE) can access the secure
+         physical address space, and the secure copy of banked registers.
+
 config GICV3
        bool "GICv3 driver"
        depends on !NEW_VGIC
diff --git a/xen/arch/arm/include/asm/arm64/sysregs.h 
b/xen/arch/arm/include/asm/arm64/sysregs.h
index c46daf6f69..9546e8e3d0 100644
--- a/xen/arch/arm/include/asm/arm64/sysregs.h
+++ b/xen/arch/arm/include/asm/arm64/sysregs.h
@@ -458,7 +458,6 @@
 #define ZCR_ELx_LEN_SIZE             9
 #define ZCR_ELx_LEN_MASK             0x1ff
 
-/* System registers for Armv8-R AArch64 */
 #ifdef CONFIG_HAS_MPU
 
 /* EL2 MPU Protection Region Base Address Register encode */
@@ -510,6 +509,26 @@
 
 #endif
 
+#ifdef CONFIG_ARM_SECURE_STATE
+/*
+ * The Armv8-R AArch64 architecture always executes code in Secure
+ * state with EL2 as the highest Exception.
+ *
+ * Hypervisor timer registers for Secure EL2.
+ */
+#define CNTHPS_TVAL_EL2  S3_4_C14_C5_0
+#define CNTHPS_CTL_EL2   S3_4_C14_C5_1
+#define CNTHPS_CVAL_EL2  S3_4_C14_C5_2
+#define CNTHPx_TVAL_EL2  CNTHPS_TVAL_EL2
+#define CNTHPx_CTL_EL2   CNTHPS_CTL_EL2
+#define CNTHPx_CVAL_EL2  CNTHPS_CVAL_EL2
+#else
+/* Hypervisor timer registers for Non-Secure EL2. */
+#define CNTHPx_TVAL_EL2  CNTHP_TVAL_EL2
+#define CNTHPx_CTL_EL2   CNTHP_CTL_EL2
+#define CNTHPx_CVAL_EL2  CNTHP_CVAL_EL2
+#endif /* CONFIG_ARM_SECURE_STATE */
+
 /* Access to system registers */
 
 #define WRITE_SYSREG64(v, name) do {                    \
diff --git a/xen/arch/arm/include/asm/cpregs.h 
b/xen/arch/arm/include/asm/cpregs.h
index 6b083de204..a704677fbc 100644
--- a/xen/arch/arm/include/asm/cpregs.h
+++ b/xen/arch/arm/include/asm/cpregs.h
@@ -374,8 +374,8 @@
 #define CLIDR_EL1               CLIDR
 #define CNTFRQ_EL0              CNTFRQ
 #define CNTHCTL_EL2             CNTHCTL
-#define CNTHP_CTL_EL2           CNTHP_CTL
-#define CNTHP_CVAL_EL2          CNTHP_CVAL
+#define CNTHPx_CTL_EL2          CNTHP_CTL
+#define CNTHPx_CVAL_EL2         CNTHP_CVAL
 #define CNTKCTL_EL1             CNTKCTL
 #define CNTPCT_EL0              CNTPCT
 #define CNTP_CTL_EL0            CNTP_CTL
diff --git a/xen/arch/arm/time.c b/xen/arch/arm/time.c
index 433d7be909..3bba733b83 100644
--- a/xen/arch/arm/time.c
+++ b/xen/arch/arm/time.c
@@ -196,13 +196,13 @@ int reprogram_timer(s_time_t timeout)
 
     if ( timeout == 0 )
     {
-        WRITE_SYSREG(0, CNTHP_CTL_EL2);
+        WRITE_SYSREG(0, CNTHPx_CTL_EL2);
         return 1;
     }
 
     deadline = ns_to_ticks(timeout) + boot_count;
-    WRITE_SYSREG64(deadline, CNTHP_CVAL_EL2);
-    WRITE_SYSREG(CNTx_CTL_ENABLE, CNTHP_CTL_EL2);
+    WRITE_SYSREG64(deadline, CNTHPx_CVAL_EL2);
+    WRITE_SYSREG(CNTx_CTL_ENABLE, CNTHPx_CTL_EL2);
     isb();
 
     /* No need to check for timers in the past; the Generic Timer fires
@@ -213,7 +213,7 @@ int reprogram_timer(s_time_t timeout)
 /* Handle the firing timer */
 static void htimer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
 {
-    if ( unlikely(!(READ_SYSREG(CNTHP_CTL_EL2) & CNTx_CTL_PENDING)) )
+    if ( unlikely(!(READ_SYSREG(CNTHPx_CTL_EL2) & CNTx_CTL_PENDING)) )
         return;
 
     perfc_incr(hyp_timer_irqs);
@@ -222,7 +222,7 @@ static void htimer_interrupt(int irq, void *dev_id, struct 
cpu_user_regs *regs)
     raise_softirq(TIMER_SOFTIRQ);
 
     /* Disable the timer to avoid more interrupts */
-    WRITE_SYSREG(0, CNTHP_CTL_EL2);
+    WRITE_SYSREG(0, CNTHPx_CTL_EL2);
 }
 
 static void vtimer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
@@ -281,7 +281,7 @@ void init_timer_interrupt(void)
     /* Do not let the VMs program the physical timer, only read the physical 
counter */
     WRITE_SYSREG(CNTHCTL_EL2_EL1PCTEN, CNTHCTL_EL2);
     WRITE_SYSREG(0, CNTP_CTL_EL0);    /* Physical timer disabled */
-    WRITE_SYSREG(0, CNTHP_CTL_EL2);   /* Hypervisor's timer disabled */
+    WRITE_SYSREG(0, CNTHPx_CTL_EL2);   /* Hypervisor's timer disabled */
     isb();
 
     request_irq(timer_irq[TIMER_HYP_PPI], 0, htimer_interrupt,
@@ -301,7 +301,7 @@ void init_timer_interrupt(void)
 static void deinit_timer_interrupt(void)
 {
     WRITE_SYSREG(0, CNTP_CTL_EL0);    /* Disable physical timer */
-    WRITE_SYSREG(0, CNTHP_CTL_EL2);   /* Disable hypervisor's timer */
+    WRITE_SYSREG(0, CNTHPx_CTL_EL2);   /* Disable hypervisor's timer */
     isb();
 
     release_irq(timer_irq[TIMER_HYP_PPI], NULL);
-- 
2.25.1


Reply via email to