From 9f959967beeac09f45662fd2a303142365f278ec Mon Sep 17 00:00:00 2001
From: Aurelien Jarno <aurelien@aurel32.net>
Date: Thu, 8 Mar 2018 22:19:04 +0100
Subject: [PATCH] RISC-V: Add support for per page TLB flush

When rs1 != 0, the content of this register contains the address of the
page to be flushed. It is faster than flushing the whole TLB. We still
ignore the ASID.

Note: it might be wrong if superpages are in used.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
---
 target/riscv/helper.h    | 1 +
 target/riscv/op_helper.c | 7 +++++++
 target/riscv/translate.c | 6 +++++-
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index debb22a480..3997ed1900 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -75,4 +75,5 @@ DEF_HELPER_2(sret, tl, env, tl)
 DEF_HELPER_2(mret, tl, env, tl)
 DEF_HELPER_1(wfi, void, env)
 DEF_HELPER_1(tlb_flush, void, env)
+DEF_HELPER_2(tlb_flush_page, void, env, tl)
 #endif
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index e34715df4e..11d3c70b43 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -666,4 +666,11 @@ void helper_tlb_flush(CPURISCVState *env)
     tlb_flush(cs);
 }
 
+void helper_tlb_flush_page(CPURISCVState *env, target_ulong vaddr)
+{
+    RISCVCPU *cpu = riscv_env_get_cpu(env);
+    CPUState *cs = CPU(cpu);
+    tlb_flush_page(cs, vaddr);
+}
+
 #endif /* !CONFIG_USER_ONLY */
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 808eab7f50..2967d80b4b 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1333,7 +1333,11 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
     if ((opc == OPC_RISC_ECALL) && ((csr >> 5) == 9)) {
         /* sfence.vma */
         /* TODO: handle ASID specific fences */
-        gen_helper_tlb_flush(cpu_env);
+        if (rs1 == 0) {
+            gen_helper_tlb_flush(cpu_env);
+        } else {
+            gen_helper_tlb_flush_page(cpu_env, source1);
+        }
         return;
     }
 #endif
-- 
2.16.1

