lib: Support stage1 and stage2 tlb flushing
authorAtish Patra <atish.patra@wdc.com>
Mon, 25 Nov 2019 07:33:49 +0000 (23:33 -0800)
committerAnup Patel <anup@brainfault.org>
Mon, 23 Dec 2019 03:42:19 +0000 (09:12 +0530)
The hypervisor specification support hfence calls which can be used
issue tlb flush requests at both level of address translation. Currently,
these requests are issued only via SBI which are defined in v0.2.

Signed-off-by: Atish Patra <atish.patra@wdc.com>
Reviewed-by: Anup Patel <anup.patel@wdc.com>
include/sbi/sbi_tlb.h
lib/sbi/sbi_tlb.c

index d1d6f22..83f9458 100644 (file)
 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
 };
 
index 5c4c596..d821516 100644 (file)
@@ -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;
 }