summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sbi/sbi_ecall_interface.h2
-rw-r--r--include/sbi/sbi_platform.h58
-rw-r--r--lib/sbi/sbi_ecall.c29
3 files changed, 86 insertions, 3 deletions
diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h
index cfdf9e1..98c5ce6 100644
--- a/include/sbi/sbi_ecall_interface.h
+++ b/include/sbi/sbi_ecall_interface.h
@@ -38,6 +38,8 @@ enum sbi_ext_base_fid {
#define SBI_SPEC_VERSION_MAJOR_OFFSET 24
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
#define SBI_SPEC_VERSION_MINOR_MASK 0xffffff
+#define SBI_EXT_VENDOR_START 0x09000000
+#define SBI_EXT_VENDOR_END 0x09FFFFFF
/* clang-format on */
#endif
diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
index 3de69b5..fdf30b9 100644
--- a/include/sbi/sbi_platform.h
+++ b/include/sbi/sbi_platform.h
@@ -43,6 +43,8 @@
#include <sbi/sbi_version.h>
#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_ecall.h>
+#include <sbi/sbi_error.h>
/** Possible feature flags of a platform */
enum sbi_platform_features {
@@ -112,6 +114,14 @@ struct sbi_platform_operations {
int (*system_reboot)(u32 type);
/** Shutdown or poweroff the platform */
int (*system_shutdown)(u32 type);
+
+ /** platform specific SBI extension implementation probe function */
+ int (*vendor_ext_check)(long extid);
+ /** platform specific SBI extension implementation provider */
+ int (*vendor_ext_provider)(long extid, long funcid,
+ unsigned long *args, unsigned long *out_value,
+ unsigned long *out_trap_cause,
+ unsigned long *out_trap_val);
} __packed;
/** Representation of a platform */
@@ -506,6 +516,54 @@ static inline int sbi_platform_system_shutdown(const struct sbi_platform *plat,
return 0;
}
+/**
+ * Check if a vendor extension is implemented or not.
+ *
+ * @param plat pointer to struct sbi_platform
+ * @param extid vendor SBI extension id
+ *
+ * @return 0 if extid is not implemented and 1 if implemented
+ */
+static inline int sbi_platform_vendor_ext_check(const struct sbi_platform *plat,
+ long extid)
+{
+ if (plat && sbi_platform_ops(plat)->vendor_ext_check)
+ return sbi_platform_ops(plat)->vendor_ext_check(extid);
+
+ return 0;
+}
+
+/**
+ * Invoke platform specific vendor SBI extension implementation.
+ *
+ * @param plat pointer to struct sbi_platform
+ * @param extid vendor SBI extension id
+ * @param funcid SBI function id within the extension id
+ * @param args pointer to arguments passed by the caller
+ * @param out_value output value that can be filled the callee
+ * @param out_tcause trap cause that can be filled the callee
+ * @param out_tvalue possible trap value that can be filled the callee
+ *
+ * @return 0 on success and negative error code on failure
+ */
+static inline int sbi_platform_vendor_ext_provider(const struct sbi_platform *plat,
+ long extid, long funcid,
+ unsigned long *args,
+ unsigned long *out_value,
+ unsigned long *out_tcause,
+ unsigned long *out_tval)
+{
+ if (plat && sbi_platform_ops(plat)->vendor_ext_provider) {
+ return sbi_platform_ops(plat)->vendor_ext_provider(extid,
+ funcid, args,
+ out_value,
+ out_tcause,
+ out_tval);
+ }
+
+ return SBI_ENOTSUPP;
+}
+
#endif
#endif
diff --git a/lib/sbi/sbi_ecall.c b/lib/sbi/sbi_ecall.c
index 0a934e9..5864590 100644
--- a/lib/sbi/sbi_ecall.c
+++ b/lib/sbi/sbi_ecall.c
@@ -12,6 +12,7 @@
#include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_ipi.h>
+#include <sbi/sbi_platform.h>
#include <sbi/sbi_system.h>
#include <sbi/sbi_timer.h>
#include <sbi/sbi_tlb.h>
@@ -47,14 +48,30 @@ int sbi_check_extension(struct sbi_scratch *scratch, unsigned long extid,
*/
if ((extid >= SBI_EXT_0_1_SET_TIMER &&
- extid <= SBI_EXT_0_1_SHUTDOWN) || (extid == SBI_EXT_BASE))
+ extid <= SBI_EXT_0_1_SHUTDOWN) || (extid == SBI_EXT_BASE)) {
*out_val = 1;
- else
+ } else if (extid >= SBI_EXT_VENDOR_START &&
+ extid <= SBI_EXT_VENDOR_END) {
+ *out_val = sbi_platform_vendor_ext_check(
+ sbi_platform_ptr(scratch),
+ extid);
+ } else
*out_val = 0;
return 0;
}
+int sbi_ecall_vendor_ext_handler(struct sbi_scratch *scratch,
+ unsigned long extid, unsigned long funcid,
+ unsigned long *args, unsigned long *out_val,
+ unsigned long *out_tcause,
+ unsigned long *out_tval)
+{
+ return sbi_platform_vendor_ext_provider(sbi_platform_ptr(scratch),
+ extid, funcid, args, out_val,
+ out_tcause, out_tval);
+}
+
int sbi_ecall_base_handler(struct sbi_scratch *scratch, unsigned long extid,
unsigned long funcid, unsigned long *args,
unsigned long *out_val, unsigned long *out_tcause,
@@ -195,8 +212,14 @@ int sbi_ecall_handler(u32 hartid, ulong mcause, struct sbi_trap_regs *regs,
ret = sbi_ecall_base_handler(scratch, extension_id, func_id,
args, &out_val,
&out_tval, &out_tcause);
- else
+ else if (extension_id >= SBI_EXT_VENDOR_START &&
+ extension_id <= SBI_EXT_VENDOR_END) {
+ ret = sbi_ecall_vendor_ext_handler(scratch, extension_id,
+ func_id, args, &out_val,
+ &out_tval, &out_tcause);
+ } else {
ret = SBI_ENOTSUPP;
+ }
if (ret == SBI_ETRAP) {
sbi_trap_redirect(regs, scratch, regs->mepc,