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 #include +#include +#include /** 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 #include #include +#include #include #include #include @@ -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,