diff options
author | Atish Patra <atish.patra@wdc.com> | 2019-11-25 10:33:47 +0300 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2019-12-23 06:42:13 +0300 |
commit | 9777aeef41a613b3c27056a695d4d6007760b3a8 (patch) | |
tree | a50c68b24fa6caf5932f0b96aafaf2509cc6be62 /lib/sbi/sbi_ecall.c | |
parent | 109266397a6d8a37f4450c5ff80ea3737a6acd3e (diff) | |
download | opensbi-9777aeef41a613b3c27056a695d4d6007760b3a8.tar.xz |
lib: Add IPI extension in SBI
This patch adds new IPI extension which replaces ipi related
v0.1 extensions. This also adds a new API for ipi sending as trap
handling is not necessary in v0.2 SBI IPI related extensions.
It also modifies the IPI sending code which now accepts hart mask as a value
instead of S-mode virtual address. Thus, the caller should set it to exact hart
mask value everytime.
Signed-off-by: Atish Patra <atish.patra@wdc.com>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
Diffstat (limited to 'lib/sbi/sbi_ecall.c')
-rw-r--r-- | lib/sbi/sbi_ecall.c | 70 |
1 files changed, 59 insertions, 11 deletions
diff --git a/lib/sbi/sbi_ecall.c b/lib/sbi/sbi_ecall.c index d472165..891cdbe 100644 --- a/lib/sbi/sbi_ecall.c +++ b/lib/sbi/sbi_ecall.c @@ -17,6 +17,7 @@ #include <sbi/sbi_timer.h> #include <sbi/sbi_tlb.h> #include <sbi/sbi_trap.h> +#include <sbi/sbi_unpriv.h> #include <sbi/sbi_hart.h> #include <sbi/sbi_version.h> #include <sbi/riscv_asm.h> @@ -35,6 +36,22 @@ u16 sbi_ecall_version_minor(void) return SBI_ECALL_VERSION_MINOR; } +static int sbi_load_hart_mask_unpriv(struct sbi_scratch *scratch, ulong *pmask, + ulong *hmask, struct sbi_trap_info *uptrap) +{ + ulong mask = 0; + + if (pmask) { + mask = sbi_load_ulong(pmask, scratch, uptrap); + if (uptrap->cause) + return SBI_ETRAP; + } else { + mask = sbi_hart_available_mask(); + } + *hmask = mask; + return 0; +} + int sbi_check_extension(struct sbi_scratch *scratch, unsigned long extid, unsigned long *out_val) { @@ -49,7 +66,8 @@ 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_TIME)) { + (extid == SBI_EXT_TIME) || + (extid == SBI_EXT_IPI)) { *out_val = 1; } else if (extid >= SBI_EXT_VENDOR_START && extid <= SBI_EXT_VENDOR_END) { @@ -130,12 +148,27 @@ int sbi_ecall_time_handler(struct sbi_scratch *scratch, unsigned long funcid, return ret; } +int sbi_ecall_ipi_handler(struct sbi_scratch *scratch, unsigned long funcid, + unsigned long *args, unsigned long *tval) +{ + int ret = 0; + + if (funcid == SBI_EXT_IPI_SEND_IPI) + ret = sbi_ipi_send_many(scratch, args[0], args[1], + SBI_IPI_EVENT_SOFT, NULL); + else + ret = SBI_ENOTSUPP; + + return ret; +} + int sbi_ecall_0_1_handler(struct sbi_scratch *scratch, unsigned long extid, unsigned long *args, struct sbi_trap_info *out_trap) { int ret = 0; struct sbi_tlb_info tlb_info; u32 source_hart = sbi_current_hartid(); + ulong hmask = 0; switch (extid) { case SBI_EXT_0_1_SET_TIMER: @@ -156,25 +189,35 @@ int sbi_ecall_0_1_handler(struct sbi_scratch *scratch, unsigned long extid, sbi_ipi_clear_smode(scratch); break; case SBI_EXT_0_1_SEND_IPI: - ret = sbi_ipi_send_many(scratch, out_trap, (ulong *)args[0], - SBI_IPI_EVENT_SOFT, NULL); + ret = sbi_load_hart_mask_unpriv(scratch, (ulong *)args[0], + &hmask, out_trap); + if (ret != SBI_ETRAP) + ret = sbi_ipi_send_many(scratch, hmask, 0, + SBI_IPI_EVENT_SOFT, NULL); break; case SBI_EXT_0_1_REMOTE_FENCE_I: tlb_info.start = 0; tlb_info.size = 0; tlb_info.type = SBI_ITLB_FLUSH; tlb_info.shart_mask = 1UL << source_hart; - ret = sbi_ipi_send_many(scratch, out_trap, (ulong *)args[0], - SBI_IPI_EVENT_FENCE, &tlb_info); + ret = sbi_load_hart_mask_unpriv(scratch, (ulong *)args[0], + &hmask, out_trap); + if (ret != SBI_ETRAP) + ret = sbi_ipi_send_many(scratch, hmask, 0, + SBI_IPI_EVENT_FENCE, + &tlb_info); break; case SBI_EXT_0_1_REMOTE_SFENCE_VMA: tlb_info.start = (unsigned long)args[1]; tlb_info.size = (unsigned long)args[2]; tlb_info.type = SBI_TLB_FLUSH_VMA; tlb_info.shart_mask = 1UL << source_hart; - - ret = sbi_ipi_send_many(scratch, out_trap, (ulong *)args[0], - SBI_IPI_EVENT_FENCE, &tlb_info); + ret = sbi_load_hart_mask_unpriv(scratch, (ulong *)args[0], + &hmask, out_trap); + if (ret != SBI_ETRAP) + ret = sbi_ipi_send_many(scratch, hmask, 0, + SBI_IPI_EVENT_FENCE, + &tlb_info); break; case SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID: tlb_info.start = (unsigned long)args[1]; @@ -183,9 +226,12 @@ int sbi_ecall_0_1_handler(struct sbi_scratch *scratch, unsigned long extid, tlb_info.type = SBI_TLB_FLUSH_VMA_ASID; tlb_info.shart_mask = 1UL << source_hart; - ret = sbi_ipi_send_many(scratch, out_trap, (ulong *)args[0], - SBI_IPI_EVENT_FENCE, - &tlb_info); + ret = sbi_load_hart_mask_unpriv(scratch, (ulong *)args[0], + &hmask, out_trap); + if (ret != SBI_ETRAP) + ret = sbi_ipi_send_many(scratch, hmask, 0, + SBI_IPI_EVENT_FENCE, + &tlb_info); break; case SBI_EXT_0_1_SHUTDOWN: sbi_system_shutdown(scratch, 0); @@ -225,6 +271,8 @@ int sbi_ecall_handler(u32 hartid, ulong mcause, struct sbi_trap_regs *regs, args, &out_val, &trap); else if (extension_id == SBI_EXT_TIME) ret = sbi_ecall_time_handler(scratch, func_id, args); + else if (extension_id == SBI_EXT_IPI) + ret = sbi_ecall_ipi_handler(scratch, func_id, args, &out_val); else if (extension_id >= SBI_EXT_VENDOR_START && extension_id <= SBI_EXT_VENDOR_END) { ret = sbi_ecall_vendor_ext_handler(scratch, extension_id, |