Introduce pointer to function which points to a specific sbi_set_timer()
implementation. It is done in this way as different OpenSBI version can
have different Extenion ID and/or funcion ID for TIME extension.

sbi_set_time() programs the clock for next event after stime_value
time. This function also clears the pending timer interrupt bit.

Introduce extension ID and SBI function ID for TIME extension.

Implement only sbi_set_timer_v02() as there is not to much sense
to support earlier version and, at the moment, Xen supports only v02.

Signed-off-by: Oleksii Kurochko <[email protected]>
---
 xen/arch/riscv/include/asm/sbi.h | 17 +++++++++++++++++
 xen/arch/riscv/sbi.c             | 26 ++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/xen/arch/riscv/include/asm/sbi.h b/xen/arch/riscv/include/asm/sbi.h
index a88d3d57127a..c54dc7642ff1 100644
--- a/xen/arch/riscv/include/asm/sbi.h
+++ b/xen/arch/riscv/include/asm/sbi.h
@@ -33,6 +33,7 @@
 
 #define SBI_EXT_BASE                    0x10
 #define SBI_EXT_RFENCE                  0x52464E43
+#define SBI_EXT_TIME                    0x54494D45
 
 /* SBI function IDs for BASE extension */
 #define SBI_EXT_BASE_GET_SPEC_VERSION   0x0
@@ -65,6 +66,9 @@
 
 #define SBI_SPEC_VERSION_DEFAULT 0x1
 
+/* SBI function IDs for TIME extension */
+#define SBI_EXT_TIME_SET_TIMER  0x0
+
 struct sbiret {
     long error;
     long value;
@@ -138,6 +142,19 @@ int sbi_remote_hfence_gvma(const cpumask_t *cpu_mask, 
vaddr_t start,
 int sbi_remote_hfence_gvma_vmid(const cpumask_t *cpu_mask, vaddr_t start,
                                 size_t size, unsigned long vmid);
 
+/*
+ * Programs the clock for next event after stime_value time. This function also
+ * clears the pending timer interrupt bit.
+ * If the supervisor wishes to clear the timer interrupt without scheduling the
+ * next timer event, it can either request a timer interrupt infinitely far
+ * into the future (i.e., (uint64_t)-1), or it can instead mask the timer
+ * interrupt by clearing sie.STIE CSR bit.
+ *
+ * This SBI call returns 0 upon success or an implementation specific negative
+ * error code.
+ */
+extern int (*sbi_set_timer)(uint64_t stime_value);
+
 /*
  * Initialize SBI library
  *
diff --git a/xen/arch/riscv/sbi.c b/xen/arch/riscv/sbi.c
index 425dce44c679..206ea3462c50 100644
--- a/xen/arch/riscv/sbi.c
+++ b/xen/arch/riscv/sbi.c
@@ -249,6 +249,26 @@ static int (* __ro_after_init sbi_rfence)(unsigned long 
fid,
                                           unsigned long arg4,
                                           unsigned long arg5);
 
+static int cf_check sbi_set_timer_v02(uint64_t stime_value)
+{
+    struct sbiret ret;
+
+#ifdef CONFIG_RISCV_64
+    ret = sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value, 0,
+                    0, 0, 0, 0);
+#else
+    ret = sbi_ecall(SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, stime_value,
+                    stime_value >> 32, 0, 0, 0, 0);
+#endif
+
+    if ( ret.error )
+        return sbi_err_map_xen_errno(ret.error);
+    else
+        return 0;
+}
+
+int (* __ro_after_init sbi_set_timer)(uint64_t stime_value);
+
 int sbi_remote_sfence_vma(const cpumask_t *cpu_mask, vaddr_t start,
                           size_t size)
 {
@@ -326,6 +346,12 @@ int __init sbi_init(void)
             sbi_rfence = sbi_rfence_v02;
             printk("SBI v0.2 RFENCE extension detected\n");
         }
+
+        if ( sbi_probe_extension(SBI_EXT_TIME) > 0 )
+        {
+            sbi_set_timer = sbi_set_timer_v02;
+            printk("SBI v0.2 TIME extension detected\n");
+        }
     }
     else
         panic("Ooops. SBI spec version 0.1 detected. Need to add support");
-- 
2.52.0


Reply via email to