[PATCH 1/4] RISC-V: Implement sfence & hfence correctly.

4 views
Skip to first unread message

Atish Patra

unread,
May 22, 2019, 5:54:59 AM5/22/19
to xvisor...@googlegroups.com, Atish Patra
Currently, Xvisor is only doing local tlb flush for both host & stage 2
tlb.

Issue remote tlb flush calls via IPIs to all the online cpus. It can
be optimized further by keeping track of relevant cpus using a separate
cpumask.

Signed-off-by: Atish Patra <atish...@wdc.com>
---
arch/riscv/cpu/generic/cpu_mmu.c | 47 +++++++++++++++++++-----
arch/riscv/cpu/generic/include/cpu_tlb.h | 39 ++++++++++++++++++++
2 files changed, 76 insertions(+), 10 deletions(-)

diff --git a/arch/riscv/cpu/generic/cpu_mmu.c b/arch/riscv/cpu/generic/cpu_mmu.c
index 549e71abfb26..b660097179d2 100644
--- a/arch/riscv/cpu/generic/cpu_mmu.c
+++ b/arch/riscv/cpu/generic/cpu_mmu.c
@@ -70,14 +70,41 @@ static inline void cpu_mmu_sync_pte(cpu_pte_t *pte)
arch_smp_mb();
}

-static inline void cpu_invalid_gpa_guest_tlb(physical_addr_t gpa)
+static inline void cpu_local_va_hyp_tlbflush(virtual_addr_t va)
{
- __hfence_gvma_gpa(gpa);
+ __sfence_vma_va(va);
}

-static inline void cpu_invalid_va_hypervisor_tlb(virtual_addr_t va)
+static void cpu_tlbflush_ipi_handler(void *tinfo, void *a2, void *a3)
{
- __asm__ __volatile__ ("sfence.vma %0" : : "r" (va) : "memory");
+ struct tlbinfo *info = tinfo;
+
+ if (info->type == TLBFLUSH_SFENCE_VMA)
+ __sfence_vma_va(info->addr);
+ else if (info->type == TLBFLUSH_HFENCE_GVMA)
+ __hfence_gvma_gpa(info->addr);
+}
+
+static inline void cpu_remote_gpa_guest_tlbflush(physical_addr_t gpa)
+{
+ struct tlbinfo info;
+
+ info.addr = gpa;
+ info.type = TLBFLUSH_HFENCE_GVMA;
+ vmm_smp_ipi_sync_call(cpu_online_mask, 1000,
+ cpu_tlbflush_ipi_handler,
+ &info, NULL, NULL);
+}
+
+static inline void cpu_remote_va_hyp_tlb_flush(virtual_addr_t va)
+{
+ struct tlbinfo info;
+
+ info.addr = va;
+ info.type = TLBFLUSH_SFENCE_VMA;
+ vmm_smp_ipi_sync_call(cpu_online_mask, 1000,
+ cpu_tlbflush_ipi_handler,
+ &info, NULL, NULL);
}

static struct cpu_pgtbl *cpu_mmu_pgtbl_find(physical_addr_t tbl_pa)
@@ -562,10 +589,10 @@ int cpu_mmu_unmap_page(struct cpu_pgtbl *pgtbl, struct cpu_page *pg)
cpu_mmu_sync_pte(&pte[index]);

if (pgtbl->stage == PGTBL_STAGE2) {
- cpu_invalid_gpa_guest_tlb((pg->ia));
+ cpu_remote_gpa_guest_tlbflush(pg->ia);
start_level = mmuctrl.stage2_start_level;
} else {
- cpu_invalid_va_hypervisor_tlb(((virtual_addr_t)pg->ia));
+ cpu_remote_va_hyp_tlb_flush((virtual_addr_t)pg->ia);
start_level = mmuctrl.stage1_start_level;
}

@@ -647,9 +674,9 @@ int cpu_mmu_map_page(struct cpu_pgtbl *pgtbl, struct cpu_page *pg)
cpu_mmu_sync_pte(&pte[index]);

if (pgtbl->stage == PGTBL_STAGE2) {
- cpu_invalid_gpa_guest_tlb((pg->ia));
+ cpu_remote_gpa_guest_tlbflush(pg->ia);
} else {
- cpu_invalid_va_hypervisor_tlb(((virtual_addr_t)pg->ia));
+ cpu_remote_va_hyp_tlb_flush((virtual_addr_t)pg->ia);
}

pgtbl->pte_cnt++;
@@ -720,7 +747,7 @@ int arch_cpu_aspace_memory_read(virtual_addr_t tmp_va,
*pte |= PHYS_RW_PTE;

cpu_mmu_sync_pte(pte);
- cpu_invalid_va_hypervisor_tlb(tmp_va);
+ cpu_local_va_hyp_tlbflush(tmp_va);

switch (len) {
case 1:
@@ -763,7 +790,7 @@ int arch_cpu_aspace_memory_write(virtual_addr_t tmp_va,
*pte |= PHYS_RW_PTE;

cpu_mmu_sync_pte(pte);
- cpu_invalid_va_hypervisor_tlb(tmp_va);
+ cpu_local_va_hyp_tlbflush(tmp_va);

switch (len) {
case 1:
diff --git a/arch/riscv/cpu/generic/include/cpu_tlb.h b/arch/riscv/cpu/generic/include/cpu_tlb.h
index af150a261ed4..aebadc4775da 100644
--- a/arch/riscv/cpu/generic/include/cpu_tlb.h
+++ b/arch/riscv/cpu/generic/include/cpu_tlb.h
@@ -26,6 +26,19 @@

#include <vmm_types.h>

+#define TLBFLUSH_SFENCE_VMA 1
+#define TLBFLUSH_HFENCE_GVMA 2
+#define TLBFLUSH_HFENCE_BVMA 3
+
+struct tlbinfo {
+ unsigned long addr;
+ u32 type;
+ /* Only valid if type is TLBFLUSH_HFENCE_GVMA */
+ u32 vmid;
+ /* Only valid if type is TLBFLUSH_HFENCE_BVMA or SFENCE_VMA*/
+ u32 asid;
+};
+
/** Invalidate Stage2 TLBs for given VMID and guest physical address */
void __hfence_gvma_vmid_gpa(unsigned long vmid, unsigned long gpa);

@@ -38,4 +51,30 @@ void __hfence_gvma_gpa(unsigned long gpa);
/** Invalidate all possible Stage2 TLBs */
void __hfence_gvma_all(void);

+inline void __sfence_vma_asid_va(unsigned long asid, unsigned long va)
+{
+ __asm__ __volatile__("sfence.vma %0 %1"
+ :
+ : "r"(va),"r"(asid)
+ : "memory");
+}
+
+inline void __sfence_vma_asid(unsigned long asid)
+{
+ __asm__ __volatile__("sfence.vma x0 %1"
+ :
+ : "r"(asid)
+ : "memory");
+
+}
+
+inline void __sfence_vma_all(void)
+{
+ __asm__ __volatile("sfence.vma");
+}
+
+inline void __sfence_vma_va(virtual_addr_t va)
+{
+ __asm__ __volatile__ ("sfence.vma %0" : : "r" (va) : "memory");
+}
#endif
--
2.21.0

Atish Patra

unread,
May 22, 2019, 5:55:00 AM5/22/19
to xvisor...@googlegroups.com, Atish Patra
sfence.bvma should be used to for guest virtual to physical page
mapping tlb flush.

Signed-off-by: Atish Patra <atish...@wdc.com>
---
arch/riscv/cpu/generic/cpu_vcpu_sbi.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/cpu/generic/cpu_vcpu_sbi.c b/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
index a7e1d94da49d..add15360a29a 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
@@ -28,6 +28,7 @@
#include <cpu_vcpu_helper.h>
#include <cpu_vcpu_timer.h>
#include <cpu_vcpu_sbi.h>
+#include <cpu_tlb.h>
#include <vmm_timer.h>
#include <vmm_vcpu_irq.h>
#include <vio/vmm_vserial.h>
@@ -108,10 +109,12 @@ int cpu_vcpu_sbi_ecall(struct vmm_vcpu *vcpu, ulong mcause,
__asm__ __volatile("fence.i");
break;
case SBI_REMOTE_SFENCE_VMA:
- __asm__ __volatile("sfence.vma");
+ /*TODO: Parse vma range */
+ __hfence_bvma_all();
break;
case SBI_REMOTE_SFENCE_VMA_ASID:
- __asm__ __volatile("sfence.vma");
+ /*TODO: Parse vma range for given ASID */
+ __hfence_bvma_asid(regs->a3);
break;
default:
regs->a0 = VMM_ENOTSUPP;
--
2.21.0

Atish Patra

unread,
May 22, 2019, 5:55:00 AM5/22/19
to xvisor...@googlegroups.com, Atish Patra
Signed-off-by: Atish Patra <atish...@wdc.com>
---
tests/riscv/virt32/linux/README | 2 +-
tests/riscv/virt64/linux/README | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/riscv/virt32/linux/README b/tests/riscv/virt32/linux/README
index 8a9187784f53..112342689b99 100644
--- a/tests/riscv/virt32/linux/README
+++ b/tests/riscv/virt32/linux/README
@@ -66,7 +66,7 @@ on QEMU model (v3.1.50 or higher):
# cp -f ./tests/riscv/virt32/linux/cmdlist ./build/disk/images/riscv/virt32/cmdlist
# cp -f ./tests/riscv/virt32/xscript/one_guest_virt32.xscript ./build/disk/boot.xscript
# cp -f <linux_build_directory>/arch/riscv/boot/Image ./build/disk/images/riscv/virt32/Image
- # dtc -q -I dts -O dtb -o ./build/disk/images/riscv/virt32/virt32.dtb ./tests/riscv/virt32/linux/virt.dts
+ # dtc -q -I dts -O dtb -o ./build/disk/images/riscv/virt32/virt32.dtb ./tests/riscv/virt32/linux/virt32.dts
# cp -f <busybox_rootfs_directory>/rootfs.img ./build/disk/images/riscv/virt32/rootfs.img
# genext2fs -B 1024 -b 32768 -d ./build/disk ./build/disk.img

diff --git a/tests/riscv/virt64/linux/README b/tests/riscv/virt64/linux/README
index a1954f58af27..856d6f3c4863 100644
--- a/tests/riscv/virt64/linux/README
+++ b/tests/riscv/virt64/linux/README
@@ -66,7 +66,7 @@ on QEMU model (v3.1.50 or higher):
# cp -f ./tests/riscv/virt64/linux/cmdlist ./build/disk/images/riscv/virt64/cmdlist
# cp -f ./tests/riscv/virt64/xscript/one_guest_virt64.xscript ./build/disk/boot.xscript
# cp -f <linux_build_directory>/arch/riscv/boot/Image ./build/disk/images/riscv/virt64/Image
- # dtc -q -I dts -O dtb -o ./build/disk/images/riscv/virt64/virt64.dtb ./tests/riscv/virt64/linux/virt.dts
+ # dtc -q -I dts -O dtb -o ./build/disk/images/riscv/virt64/virt64.dtb ./tests/riscv/virt64/linux/virt64.dts
# cp -f <busybox_rootfs_directory>/rootfs.img ./build/disk/images/riscv/virt64/rootfs.img
# genext2fs -B 1024 -b 32768 -d ./build/disk ./build/disk.img

--
2.21.0

Atish Patra

unread,
May 22, 2019, 5:55:00 AM5/22/19
to xvisor...@googlegroups.com, Atish Patra
The toolchain doesn's support the hfence.bvma yet.
Handcode the instruction for now.

Signed-off-by: Atish Patra <atish...@wdc.com>
---
arch/riscv/cpu/generic/cpu_tlb.S | 33 ++++++++++++++++++++++++
arch/riscv/cpu/generic/include/cpu_tlb.h | 13 ++++++++++
2 files changed, 46 insertions(+)

diff --git a/arch/riscv/cpu/generic/cpu_tlb.S b/arch/riscv/cpu/generic/cpu_tlb.S
index ba788c3aa760..758cda4ce38f 100644
--- a/arch/riscv/cpu/generic/cpu_tlb.S
+++ b/arch/riscv/cpu/generic/cpu_tlb.S
@@ -55,3 +55,36 @@ __hfence_gvma_all:
/* hfence.gvma */
.word 0xa2000073
ret
+
+ /*
+ * Instruction encoding of hfence.bvma is:
+ * 0010001 rs2(5) rs1(5) 000 00000 1110011
+ */
+
+ .align 3
+ .global __hfence_bvma_asid_va
+__hfence_bvma_asid_va:
+ /* hfence.bvma a1, a0 */
+ .word 0x22a60073
+ ret
+
+ .align 3
+ .global __hfence_bvma_asid
+__hfence_bvma_asid:
+ /* hfence.bvma zero, a0 */
+ .word 0x22a00073
+ ret
+
+ .align 3
+ .global __hfence_bvma_va
+__hfence_bvma_va:
+ /* hfence.bvma a0 */
+ .word 0x22050073
+ ret
+
+ .align 3
+ .global __hfence_bvma_all
+__hfence_bvma_all:
+ /* hfence.bvma */
+ .word 0x22000073
+ ret
diff --git a/arch/riscv/cpu/generic/include/cpu_tlb.h b/arch/riscv/cpu/generic/include/cpu_tlb.h
index aebadc4775da..6fb33e129871 100644
--- a/arch/riscv/cpu/generic/include/cpu_tlb.h
+++ b/arch/riscv/cpu/generic/include/cpu_tlb.h
@@ -51,6 +51,19 @@ void __hfence_gvma_gpa(unsigned long gpa);
/** Invalidate all possible Stage2 TLBs */
void __hfence_gvma_all(void);

+/** Invalidate unified TLB entries for given asid and guest virtual address */
+void __hfence_bvma_asid_va(unsigned long asid, unsigned long va);
+
+/** Invalidate unified TLB entries for given ASID for a guest*/
+void __hfence_bvma_asid(unsigned long asid);
+
+/** Invalidate unified TLB entries for a given guest virtual address */
+void __hfence_bvma_va(unsigned long va);
+
+/** Invalidate all possible Stage2 TLBs */
+void __hfence_bvma_all(void);
+
+
inline void __sfence_vma_asid_va(unsigned long asid, unsigned long va)
{
__asm__ __volatile__("sfence.vma %0 %1"
--
2.21.0

Anup Patel

unread,
May 22, 2019, 1:11:20 PM5/22/19
to Xvisor Devel, Atish Patra
> --
> You received this message because you are subscribed to the Google Groups "Xvisor Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to xvisor-devel...@googlegroups.com.
> Visit this group at https://groups.google.com/group/xvisor-devel.
> To view this discussion on the web visit https://groups.google.com/d/msgid/xvisor-devel/20190522095450.23027-1-atish.patra%40wdc.com.
> For more options, visit https://groups.google.com/d/optout.

Acked-by: Anup Patel <an...@brainfault.org>

Regards,
Anup

Anup Patel

unread,
May 22, 2019, 1:12:00 PM5/22/19
to Xvisor Devel, Atish Patra
On Wed, May 22, 2019 at 3:25 PM Atish Patra <atish...@wdc.com> wrote:
>
Extra empty line here. Otherwise looks good.

> inline void __sfence_vma_asid_va(unsigned long asid, unsigned long va)
> {
> __asm__ __volatile__("sfence.vma %0 %1"
> --
> 2.21.0
>
> --
> You received this message because you are subscribed to the Google Groups "Xvisor Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to xvisor-devel...@googlegroups.com.
> Visit this group at https://groups.google.com/group/xvisor-devel.
> To view this discussion on the web visit https://groups.google.com/d/msgid/xvisor-devel/20190522095450.23027-2-atish.patra%40wdc.com.

Anup Patel

unread,
May 22, 2019, 1:12:56 PM5/22/19
to Xvisor Devel, Atish Patra
On Wed, May 22, 2019 at 3:25 PM Atish Patra <atish...@wdc.com> wrote:
>
> sfence.bvma should be used to for guest virtual to physical page
> mapping tlb flush.

Replace sfence.bvma with hfence.bvma here and in patch subject.
> --
> You received this message because you are subscribed to the Google Groups "Xvisor Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to xvisor-devel...@googlegroups.com.
> Visit this group at https://groups.google.com/group/xvisor-devel.
> To view this discussion on the web visit https://groups.google.com/d/msgid/xvisor-devel/20190522095450.23027-3-atish.patra%40wdc.com.

Anup Patel

unread,
May 22, 2019, 1:13:11 PM5/22/19
to Xvisor Devel, Atish Patra
On Wed, May 22, 2019 at 3:25 PM Atish Patra <atish...@wdc.com> wrote:
>
> --
> You received this message because you are subscribed to the Google Groups "Xvisor Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to xvisor-devel...@googlegroups.com.
> Visit this group at https://groups.google.com/group/xvisor-devel.
> To view this discussion on the web visit https://groups.google.com/d/msgid/xvisor-devel/20190522095450.23027-4-atish.patra%40wdc.com.

Atish Patra

unread,
May 22, 2019, 2:24:25 PM5/22/19
to xvisor...@googlegroups.com, Atish Patra, Anup Patel
Currently, Xvisor is only doing local tlb flush for both host & stage 2
tlb.

Issue remote tlb flush calls via IPIs to all the online cpus. It can
be optimized further by keeping track of relevant cpus using a separate
cpumask.

Signed-off-by: Atish Patra <atish...@wdc.com>
Acked-by: Anup Patel <an...@brainfault.org>
diff --git a/arch/riscv/cpu/generic/include/cpu_tlb.h b/arch/riscv/cpu/generic/include/cpu_tlb.h
index af150a261ed4..aebadc4775da 100644
--- a/arch/riscv/cpu/generic/include/cpu_tlb.h
+++ b/arch/riscv/cpu/generic/include/cpu_tlb.h
@@ -26,6 +26,19 @@

#include <vmm_types.h>

+#define TLBFLUSH_SFENCE_VMA 1
+#define TLBFLUSH_HFENCE_GVMA 2
+#define TLBFLUSH_HFENCE_BVMA 3
+
+struct tlbinfo {
+ unsigned long addr;
+ u32 type;
+ /* Only valid if type is TLBFLUSH_HFENCE_GVMA */
+ u32 vmid;
+ /* Only valid if type is TLBFLUSH_HFENCE_BVMA or SFENCE_VMA*/
+ u32 asid;
+};
+
/** Invalidate Stage2 TLBs for given VMID and guest physical address */
void __hfence_gvma_vmid_gpa(unsigned long vmid, unsigned long gpa);

@@ -38,4 +51,30 @@ void __hfence_gvma_gpa(unsigned long gpa);
/** Invalidate all possible Stage2 TLBs */
void __hfence_gvma_all(void);

+inline void __sfence_vma_asid_va(unsigned long asid, unsigned long va)
+{
+ __asm__ __volatile__("sfence.vma %0 %1"
+ :
+ : "r"(va),"r"(asid)
+ : "memory");
+}
+
+inline void __sfence_vma_asid(unsigned long asid)
+{
+ __asm__ __volatile__("sfence.vma x0 %1"
+ :
+ : "r"(asid)
+ : "memory");
+
+}
+
+inline void __sfence_vma_all(void)
+{
+ __asm__ __volatile("sfence.vma");
+}

Atish Patra

unread,
May 22, 2019, 2:24:26 PM5/22/19
to xvisor...@googlegroups.com, Atish Patra, Anup Patel
hfence.bvma should be used to for guest virtual to physical page
mapping tlb flush.

Signed-off-by: Atish Patra <atish...@wdc.com>
Acked-by: Anup Patel <an...@brainfault.org>
---

Atish Patra

unread,
May 22, 2019, 2:24:26 PM5/22/19
to xvisor...@googlegroups.com, Atish Patra, Anup Patel
The toolchain doesn's support the hfence.bvma yet.
Handcode the instruction for now.

Signed-off-by: Atish Patra <atish...@wdc.com>
Acked-by: Anup Patel <an...@brainfault.org>
---
arch/riscv/cpu/generic/cpu_tlb.S | 33 ++++++++++++++++++++++++
arch/riscv/cpu/generic/include/cpu_tlb.h | 12 +++++++++
2 files changed, 45 insertions(+)
diff --git a/arch/riscv/cpu/generic/include/cpu_tlb.h b/arch/riscv/cpu/generic/include/cpu_tlb.h
index aebadc4775da..3a77324352e0 100644
--- a/arch/riscv/cpu/generic/include/cpu_tlb.h
+++ b/arch/riscv/cpu/generic/include/cpu_tlb.h
@@ -51,6 +51,18 @@ void __hfence_gvma_gpa(unsigned long gpa);
/** Invalidate all possible Stage2 TLBs */
void __hfence_gvma_all(void);

+/** Invalidate unified TLB entries for given asid and guest virtual address */
+void __hfence_bvma_asid_va(unsigned long asid, unsigned long va);
+
+/** Invalidate unified TLB entries for given ASID for a guest*/
+void __hfence_bvma_asid(unsigned long asid);
+
+/** Invalidate unified TLB entries for a given guest virtual address */
+void __hfence_bvma_va(unsigned long va);
+
+/** Invalidate all possible Stage2 TLBs */
+void __hfence_bvma_all(void);
+
inline void __sfence_vma_asid_va(unsigned long asid, unsigned long va)
{
__asm__ __volatile__("sfence.vma %0 %1"
--
2.21.0

Atish Patra

unread,
May 22, 2019, 2:24:27 PM5/22/19
to xvisor...@googlegroups.com, Atish Patra, Anup Patel
Signed-off-by: Atish Patra <atish...@wdc.com>
Acked-by: Anup Patel <an...@brainfault.org>
---

Anup Patel

unread,
May 23, 2019, 10:09:56 AM5/23/19
to Atish Patra, Xvisor Devel
Applied this patch on xvisor-next tree.

Regards,
Anup

Anup Patel

unread,
May 23, 2019, 10:10:36 AM5/23/19
to Atish Patra, Xvisor Devel

Anup Patel

unread,
May 23, 2019, 10:10:48 AM5/23/19
to Atish Patra, Xvisor Devel

Anup Patel

unread,
May 23, 2019, 10:11:22 AM5/23/19
to Atish Patra, Xvisor Devel
Reply all
Reply to author
Forward
0 new messages