[PATCH v2 2/4] xen/riscv: add csr_read_safe() helper

Oleksii Kurochko posted 4 patches 1 day, 4 hours ago
[PATCH v2 2/4] xen/riscv: add csr_read_safe() helper
Posted by Oleksii Kurochko 1 day, 4 hours ago
Accessing some CSRs may trap when the corresponding extension is not
implemented or enabled. Introduce csr_read_safe() which attempts to
read a CSR and relies on the exception table mechanism to safely recover
if the access faults.

This helper allows Xen to probe CSR availability without taking a fatal
trap and will be used for feature detection during early boot as we
can't always rely on what is in riscv,isa string in DTS.

While touching the header, reorder the include directives to follow the
usual Xen style.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in v2:
 - s/extables.h/extable.h.
 - s/csr_allowed_read/csr_read_safe() to follow the common nomenclature.
 - asm/asm_inline in csr_allowed_safe().
 - Drop the comment inside csr_allowed_safe().
 - Add ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
 - Drop memory clobber as a memory which is going to be changed is explicitly
   mentioned in output list.
 - Rename local variable error to allowed.
---
 xen/arch/riscv/include/asm/csr.h | 36 +++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/xen/arch/riscv/include/asm/csr.h b/xen/arch/riscv/include/asm/csr.h
index 01876f828981..1d47f70f7251 100644
--- a/xen/arch/riscv/include/asm/csr.h
+++ b/xen/arch/riscv/include/asm/csr.h
@@ -6,8 +6,10 @@
 #ifndef ASM__RISCV__CSR_H
 #define ASM__RISCV__CSR_H
 
-#include <asm/asm.h>
 #include <xen/const.h>
+
+#include <asm/asm.h>
+#include <asm/extable.h>
 #include <asm/riscv_encoding.h>
 
 #ifndef __ASSEMBLER__
@@ -78,6 +80,38 @@
                            : "memory" );                        \
 })
 
+static always_inline bool csr_read_safe(unsigned long csr,
+                                        unsigned long *val)
+{
+#ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
+    asm_inline goto (
+        "1: csrr %[val], %[csr]\n"
+        ASM_EXTABLE(1b, %l[fault])
+        : [val] "=&r" (*val)
+        : [csr] "i" (csr)
+        :
+        : fault );
+
+    return true;
+
+ fault:
+    return false;
+#else
+    bool allowed = false;
+
+    asm_inline volatile (
+        "1: csrr %[val], %[csr]\n"
+        "   li %[allowed], 1\n"
+        "2:\n"
+        ASM_EXTABLE(1b, 2b)
+        : [val] "=&r" (*val), [allowed] "+r" (allowed)
+        : [csr] "i" (csr)
+        : );
+
+    return allowed;
+#endif
+}
+
 #endif /* __ASSEMBLER__ */
 
 #endif /* ASM__RISCV__CSR_H */
-- 
2.53.0