From 86a31f54371c56f0ca94a8d9dfcec05a76dfa53c Mon Sep 17 00:00:00 2001 From: Atish Patra <atish.patra@wdc.com> Date: Sun, 24 Nov 2019 23:33:50 -0800 Subject: lib: Implement RFENCE extension This patch adds RFENCE extension support in OpenSBI. Signed-off-by: Atish Patra <atish.patra@wdc.com> Reviewed-by: Anup Patel <anup.patel@wdc.com> --- lib/sbi/sbi_ecall.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/lib/sbi/sbi_ecall.c b/lib/sbi/sbi_ecall.c index 891cdbe..30e47c3 100644 --- a/lib/sbi/sbi_ecall.c +++ b/lib/sbi/sbi_ecall.c @@ -67,7 +67,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_IPI)) { + (extid == SBI_EXT_IPI) || + (extid == SBI_EXT_RFENCE)) { *out_val = 1; } else if (extid >= SBI_EXT_VENDOR_START && extid <= SBI_EXT_VENDOR_END) { @@ -162,6 +163,95 @@ int sbi_ecall_ipi_handler(struct sbi_scratch *scratch, unsigned long funcid, return ret; } +int sbi_ecall_rfence_handler(struct sbi_scratch *scratch, unsigned long funcid, + unsigned long *args, unsigned long *tval) +{ + int ret = 0; + struct sbi_tlb_info tlb_info; + u32 source_hart = sbi_current_hartid(); + + if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA && + funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID) + if (!misa_extension('H')) + return SBI_ENOTSUPP; + + switch (funcid) { + case SBI_EXT_RFENCE_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, args[0], args[1], + SBI_IPI_EVENT_FENCE, &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA: + tlb_info.start = (unsigned long)args[2]; + tlb_info.size = (unsigned long)args[3]; + tlb_info.type = SBI_TLB_FLUSH_GVMA; + tlb_info.shart_mask = 1UL << source_hart; + + ret = sbi_ipi_send_many(scratch, args[0], args[1], + SBI_IPI_EVENT_FENCE, &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID: + tlb_info.start = (unsigned long)args[2]; + tlb_info.size = (unsigned long)args[3]; + tlb_info.asid = (unsigned long)args[4]; + tlb_info.type = SBI_TLB_FLUSH_GVMA_VMID; + tlb_info.shart_mask = 1UL << source_hart; + + ret = sbi_ipi_send_many(scratch, args[0], args[1], + SBI_IPI_EVENT_FENCE, + &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA: + tlb_info.start = (unsigned long)args[2]; + tlb_info.size = (unsigned long)args[3]; + tlb_info.type = SBI_TLB_FLUSH_VVMA; + tlb_info.shart_mask = 1UL << source_hart; + + ret = sbi_ipi_send_many(scratch, args[0], args[1], + SBI_IPI_EVENT_FENCE, &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID: + tlb_info.start = (unsigned long)args[2]; + tlb_info.size = (unsigned long)args[3]; + tlb_info.asid = (unsigned long)args[4]; + tlb_info.type = SBI_TLB_FLUSH_VVMA_ASID; + tlb_info.shart_mask = 1UL << source_hart; + + ret = sbi_ipi_send_many(scratch, args[0], args[1], + SBI_IPI_EVENT_FENCE, + &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA: + tlb_info.start = (unsigned long)args[2]; + tlb_info.size = (unsigned long)args[3]; + tlb_info.type = SBI_TLB_FLUSH_VMA; + tlb_info.shart_mask = 1UL << source_hart; + + ret = sbi_ipi_send_many(scratch, args[0], args[1], + SBI_IPI_EVENT_FENCE, &tlb_info); + break; + case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID: + tlb_info.start = (unsigned long)args[2]; + tlb_info.size = (unsigned long)args[3]; + tlb_info.asid = (unsigned long)args[4]; + tlb_info.type = SBI_TLB_FLUSH_VMA_ASID; + tlb_info.shart_mask = 1UL << source_hart; + + ret = sbi_ipi_send_many(scratch, args[0], args[1], + SBI_IPI_EVENT_FENCE, + &tlb_info); + break; + + default: + 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) { @@ -273,6 +363,9 @@ int sbi_ecall_handler(u32 hartid, ulong mcause, struct sbi_trap_regs *regs, 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_RFENCE) + ret = sbi_ecall_rfence_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, -- cgit v1.2.3