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 #include #include +#include #include #include #include @@ -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; }