aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sbi/sbi_tlb.h5
-rw-r--r--lib/sbi/sbi_tlb.c102
2 files changed, 102 insertions, 5 deletions
diff --git a/include/sbi/sbi_tlb.h b/include/sbi/sbi_tlb.h
index d1d6f22..83f9458 100644
--- a/include/sbi/sbi_tlb.h
+++ b/include/sbi/sbi_tlb.h
@@ -24,7 +24,10 @@
enum sbi_tlb_info_types {
SBI_TLB_FLUSH_VMA,
SBI_TLB_FLUSH_VMA_ASID,
- SBI_TLB_FLUSH_VMA_VMID,
+ SBI_TLB_FLUSH_GVMA,
+ SBI_TLB_FLUSH_GVMA_VMID,
+ SBI_TLB_FLUSH_VVMA,
+ SBI_TLB_FLUSH_VVMA_ASID,
SBI_ITLB_FLUSH
};
diff --git a/lib/sbi/sbi_tlb.c b/lib/sbi/sbi_tlb.c
index 5c4c596..d821516 100644
--- a/lib/sbi/sbi_tlb.c
+++ b/lib/sbi/sbi_tlb.c
@@ -16,6 +16,7 @@
#include <sbi/sbi_hart.h>
#include <sbi/sbi_scratch.h>
#include <sbi/sbi_tlb.h>
+#include <sbi/sbi_hfence.h>
#include <sbi/sbi_string.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_platform.h>
@@ -30,6 +31,38 @@ static void sbi_tlb_flush_all(void)
__asm__ __volatile("sfence.vma");
}
+static void sbi_tlb_fifo_hfence_vvma(struct sbi_tlb_info *tinfo)
+{
+ unsigned long start = tinfo->start;
+ unsigned long size = tinfo->size;
+ unsigned long i;
+
+ if ((start == 0 && size == 0) || (size == SBI_TLB_FLUSH_ALL)) {
+ __sbi_hfence_vvma_all();
+ return;
+ }
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ __sbi_hfence_vvma_va(start+i);
+ }
+}
+
+static void sbi_tlb_fifo_hfence_gvma(struct sbi_tlb_info *tinfo)
+{
+ unsigned long start = tinfo->start;
+ unsigned long size = tinfo->size;
+ unsigned long i;
+
+ if ((start == 0 && size == 0) || (size == SBI_TLB_FLUSH_ALL)) {
+ __sbi_hfence_gvma_all();
+ return;
+ }
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ __sbi_hfence_gvma_gpa(start+i);
+ }
+}
+
static void sbi_tlb_fifo_sfence_vma(struct sbi_tlb_info *tinfo)
{
unsigned long start = tinfo->start;
@@ -49,6 +82,50 @@ static void sbi_tlb_fifo_sfence_vma(struct sbi_tlb_info *tinfo)
}
}
+static void sbi_tlb_fifo_hfence_vvma_asid(struct sbi_tlb_info *tinfo)
+{
+ unsigned long start = tinfo->start;
+ unsigned long size = tinfo->size;
+ unsigned long asid = tinfo->asid;
+ unsigned long i;
+
+ if (start == 0 && size == 0) {
+ __sbi_hfence_vvma_all();
+ return;
+ }
+
+ if (size == SBI_TLB_FLUSH_ALL) {
+ __sbi_hfence_vvma_asid(asid);
+ return;
+ }
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ __sbi_hfence_vvma_asid_va(asid, start + i);
+ }
+}
+
+static void sbi_tlb_fifo_hfence_gvma_vmid(struct sbi_tlb_info *tinfo)
+{
+ unsigned long start = tinfo->start;
+ unsigned long size = tinfo->size;
+ unsigned long vmid = tinfo->asid;
+ unsigned long i;
+
+ if (start == 0 && size == 0) {
+ __sbi_hfence_gvma_all();
+ return;
+ }
+
+ if (size == SBI_TLB_FLUSH_ALL) {
+ __sbi_hfence_gvma_vmid(vmid);
+ return;
+ }
+
+ for (i = 0; i < size; i += PAGE_SIZE) {
+ __sbi_hfence_gvma_vmid_gpa(vmid, start+i);
+ }
+}
+
static void sbi_tlb_fifo_sfence_vma_asid(struct sbi_tlb_info *tinfo)
{
unsigned long start = tinfo->start;
@@ -80,15 +157,32 @@ static void sbi_tlb_fifo_sfence_vma_asid(struct sbi_tlb_info *tinfo)
static void sbi_tlb_local_flush(struct sbi_tlb_info *tinfo)
{
- if (tinfo->type == SBI_TLB_FLUSH_VMA) {
+ switch (tinfo->type) {
+ case SBI_TLB_FLUSH_VMA:
sbi_tlb_fifo_sfence_vma(tinfo);
- } else if (tinfo->type == SBI_TLB_FLUSH_VMA_ASID) {
+ break;
+ case SBI_TLB_FLUSH_VMA_ASID:
sbi_tlb_fifo_sfence_vma_asid(tinfo);
- } else if (tinfo->type == SBI_ITLB_FLUSH)
+ break;
+ case SBI_TLB_FLUSH_GVMA:
+ sbi_tlb_fifo_hfence_gvma(tinfo);
+ break;
+ case SBI_TLB_FLUSH_GVMA_VMID:
+ sbi_tlb_fifo_hfence_gvma_vmid(tinfo);
+ break;
+ case SBI_TLB_FLUSH_VVMA:
+ sbi_tlb_fifo_hfence_vvma(tinfo);
+ break;
+ case SBI_TLB_FLUSH_VVMA_ASID:
+ sbi_tlb_fifo_hfence_vvma_asid(tinfo);
+ break;
+ case SBI_ITLB_FLUSH:
__asm__ __volatile("fence.i");
- else
+ break;
+ default:
sbi_printf("Invalid tlb flush request type [%lu]\n",
tinfo->type);
+ }
return;
}