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

[PATCH v1 3/4] xen/riscv: allow Xen to use SSTC while hiding it from guests



OpenSBI currently does not advertise the SSTC extension via the device
tree. Additionally, SSTC can no longer be reliably disabled by removing
the "sstc" string from riscv,isa, as OpenSBI probes support by attempting
to access CSR_STIMECMP.

Introduce a runtime probe in Xen to determine whether SSTC is available.
The probe attempts to read CSR_STIMECMP using csr_allowed_read(). If the
access succeeds, SSTC is considered available; if a trap occurs, it is
treated as unsupported.

When SSTC is detected, Xen may use it internally to program timers.
However, the extension is not exposed to guests because the required
context switch handling for the SSTC CSRs is not yet implemented.

To prevent guests from using SSTC, RISCV_ISA_EXT_sstc is cleared from the
riscv_isa bitmap. As a result, the corresponding HENVCFG bit is not set
and guests fall back to the SBI timer interface. Timer requests are then
handled by Xen via the usual SBI interception path.

Introduce set_xen_timer() to abstract how the timer is programmed,
either via the SSTC extension or an SBI call. This also reduces the
number of if statements in reprogram_timer().

The set_xen_timer function pointer is selected based on
csr_allowed_read() rather than riscv_isa_extension(). The latter
reflects features supported by both Xen and the guest, while SSTC is
currently only supported for Xen. Therefore, relying solely on
riscv_isa_extension() would not reliably determine whether SSTC can be
used.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
---
 xen/arch/riscv/cpufeature.c                 | 33 +++++++++++++++++++
 xen/arch/riscv/domain.c                     |  3 ++
 xen/arch/riscv/include/asm/cpufeature.h     |  1 +
 xen/arch/riscv/include/asm/riscv_encoding.h |  2 ++
 xen/arch/riscv/time.c                       | 36 +++++++++++++--------
 xen/arch/riscv/vtimer.c                     |  7 +++-
 6 files changed, 67 insertions(+), 15 deletions(-)

diff --git a/xen/arch/riscv/cpufeature.c b/xen/arch/riscv/cpufeature.c
index 03e27b037be0..a7aa2358b73b 100644
--- a/xen/arch/riscv/cpufeature.c
+++ b/xen/arch/riscv/cpufeature.c
@@ -17,6 +17,7 @@
 #include <xen/sections.h>
 
 #include <asm/cpufeature.h>
+#include <asm/csr.h>
 
 #ifdef CONFIG_ACPI
 # error "cpufeature.c functions should be updated to support ACPI"
@@ -139,6 +140,7 @@ const struct riscv_isa_ext_data __initconst riscv_isa_ext[] 
= {
     RISCV_ISA_EXT_DATA(smaia),
     RISCV_ISA_EXT_DATA(smstateen),
     RISCV_ISA_EXT_DATA(ssaia),
+    RISCV_ISA_EXT_DATA(sstc),
     RISCV_ISA_EXT_DATA(svade),
     RISCV_ISA_EXT_DATA(svpbmt),
 };
@@ -483,6 +485,7 @@ void __init riscv_fill_hwcap(void)
     unsigned int i;
     const size_t req_extns_amount = ARRAY_SIZE(required_extensions);
     bool all_extns_available = true;
+    unsigned long tmp;
 
     riscv_fill_hwcap_from_isa_string();
 
@@ -495,6 +498,36 @@ void __init riscv_fill_hwcap(void)
         panic("HW capabilities parsing failed: %s\n", failure_msg);
     }
 
+    if ( csr_allowed_read(CSR_STIMECMP, &tmp) )
+    {
+        printk("SSTC is detected but is supported only for Xen usage not for "
+               "a guest.\n");
+
+        /*
+         * As SSTC for guest isn't supported it is needed temprorary to:
+         *
+         * 1. Clear bit RISCV_ISA_EXT_sstc in riscv_isa as theoretuically it
+         *    could be that OpenSBI (it doesn't pass it now) or whatever ran
+         *    before Xen will add SSTC to riscv,isa string. This bit  clear
+         *    willn't allow guest to use SSTC extension as vtimer context
+         *    switch and restore isn't ready for that.
+         */
+        __clear_bit(RISCV_ISA_EXT_sstc, riscv_isa);
+
+        /*
+         * 2. A VS-timer interrupt becomes pending whenever the value of
+         *    (time + htimedelta) is greater than or equal to vstimecmp CSR.
+         *    Thereby to avoid spurious VS-timer irqs set vstimecmp CSR to
+         *    -1.
+         *
+         * It should be dropped when SSTC for guests will be supported.
+         */
+        csr_write(CSR_VSTIMECMP, ULONG_MAX);
+#ifdef CONFIG_RISCV_32
+        csr_write(CSR_VSTIMECMPH, ULONG_MAX);
+#endif
+    }
+
     for ( i = 0; i < req_extns_amount; i++ )
     {
         const struct riscv_isa_ext_data ext = required_extensions[i];
diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c
index c327f44d07ca..5f15dda88c8e 100644
--- a/xen/arch/riscv/domain.c
+++ b/xen/arch/riscv/domain.c
@@ -99,6 +99,9 @@ static void vcpu_csr_init(struct vcpu *v)
     if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_svpbmt) )
         v->arch.henvcfg = ENVCFG_PBMTE & csr_masks.henvcfg;
 
+    if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_sstc) )
+        v->arch.henvcfg |= ENVCFG_STCE & csr_masks.henvcfg;
+
     if ( riscv_isa_extension_available(NULL, RISCV_ISA_EXT_smstateen) )
     {
         /* Allow guest to access CSR_SENVCFG */
diff --git a/xen/arch/riscv/include/asm/cpufeature.h 
b/xen/arch/riscv/include/asm/cpufeature.h
index ef02a3e26d2c..0c48d57a03bb 100644
--- a/xen/arch/riscv/include/asm/cpufeature.h
+++ b/xen/arch/riscv/include/asm/cpufeature.h
@@ -38,6 +38,7 @@ enum riscv_isa_ext_id {
     RISCV_ISA_EXT_smaia,
     RISCV_ISA_EXT_smstateen,
     RISCV_ISA_EXT_ssaia,
+    RISCV_ISA_EXT_sstc,
     RISCV_ISA_EXT_svade,
     RISCV_ISA_EXT_svpbmt,
     RISCV_ISA_EXT_MAX
diff --git a/xen/arch/riscv/include/asm/riscv_encoding.h 
b/xen/arch/riscv/include/asm/riscv_encoding.h
index dd15731a86fa..7fc379cab588 100644
--- a/xen/arch/riscv/include/asm/riscv_encoding.h
+++ b/xen/arch/riscv/include/asm/riscv_encoding.h
@@ -396,6 +396,8 @@
 #define CSR_VSTVAL                     0x243
 #define CSR_VSIP                       0x244
 #define CSR_VSATP                      0x280
+#define CSR_VSTIMECMP          0x24D
+#define CSR_VSTIMECMPH         0x25D
 
 /* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */
 #define CSR_HVIEN                      0x608
diff --git a/xen/arch/riscv/time.c b/xen/arch/riscv/time.c
index 7efa76fdbcb1..98eca2887d5c 100644
--- a/xen/arch/riscv/time.c
+++ b/xen/arch/riscv/time.c
@@ -13,6 +13,20 @@
 unsigned long __ro_after_init cpu_khz; /* CPU clock frequency in kHz. */
 uint64_t __ro_after_init boot_clock_cycles;
 
+static int cf_check sstc_set_xen_timer(uint64_t deadline)
+{
+#ifdef CONFIG_RISCV_32
+    csr_write(CSR_STIMECMP, deadline & 0xFFFFFFFF);
+    csr_write(CSR_STIMECMPH, deadline >> 32);
+#else
+    csr_write(CSR_STIMECMP, deadline);
+#endif
+
+    return 0;
+}
+
+int (* __ro_after_init set_xen_timer)(uint64_t deadline);
+
 s_time_t get_s_time(void)
 {
     uint64_t ticks = get_cycles() - boot_clock_cycles;
@@ -61,20 +75,7 @@ int reprogram_timer(s_time_t timeout)
     if ( deadline <= now )
         return 0;
 
-    /*
-     * TODO: When the SSTC extension is supported, it would be preferable to
-     *       use the supervisor timer registers directly here for better
-     *       performance, since an SBI call and mode switch would no longer
-     *       be required.
-     *
-     *       This would also reduce reliance on a specific SBI implementation.
-     *       For example, it is not ideal to panic() if sbi_set_timer() returns
-     *       a non-zero value. Currently it can return 0 or -ENOSUPP, and
-     *       without SSTC we still need an implementation because only the
-     *       M-mode timer is available, and it can only be programmed in
-     *       M-mode.
-     */
-    if ( (rc = sbi_set_timer(deadline)) )
+    if ( (rc = set_xen_timer(deadline)) )
         panic("%s: timer wasn't set because: %d\n", __func__, rc);
 
     /* Enable timer interrupt */
@@ -85,10 +86,17 @@ int reprogram_timer(s_time_t timeout)
 
 void __init preinit_xen_time(void)
 {
+    unsigned long tmp;
+
     if ( acpi_disabled )
         preinit_dt_xen_time();
     else
         panic("%s: ACPI isn't supported\n", __func__);
 
     boot_clock_cycles = get_cycles();
+
+    if ( csr_allowed_read(CSR_STIMECMP, &tmp) )
+        set_xen_timer = sstc_set_xen_timer;
+    else
+        set_xen_timer = sbi_set_timer;
 }
diff --git a/xen/arch/riscv/vtimer.c b/xen/arch/riscv/vtimer.c
index afd8a53a7387..c065052afeb7 100644
--- a/xen/arch/riscv/vtimer.c
+++ b/xen/arch/riscv/vtimer.c
@@ -4,6 +4,7 @@
 #include <xen/sched.h>
 #include <xen/timer.h>
 
+#include <asm/cpufeature.h>
 #include <asm/vtimer.h>
 
 static void vtimer_expired(void *data)
@@ -75,12 +76,16 @@ void vtimer_ctxt_switch_from(struct vcpu *p)
 {
     ASSERT(!is_idle_vcpu(p));
 
-    /* Nothing to do at the moment as SSTC isn't supported now. */
+    BUG_ON(riscv_isa_extension_available(NULL, RISCV_ISA_EXT_sstc));
+
+    /* Nothing to do at the moment as SSTC for guests isn't supported now */
 }
 
 void vtimer_ctxt_switch_to(struct vcpu *n)
 {
     ASSERT(!is_idle_vcpu(n));
 
+    BUG_ON(riscv_isa_extension_available(NULL, RISCV_ISA_EXT_sstc));
+
     migrate_timer(&n->arch.vtimer.timer, n->processor);
 }
-- 
2.53.0




 


Rackspace

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