]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
riscv: kvm: Skip TLB flush when G-stage PTE becomes valid with Svvptc
authorDylan.Wu <fredwudi0305@gmail.com>
Wed, 1 Jul 2026 07:52:39 +0000 (03:52 -0400)
committerAnup Patel <anup@brainfault.org>
Mon, 13 Jul 2026 12:47:01 +0000 (18:17 +0530)
The gstage_tlb_flush() in the kvm_riscv_gstage_set_pte() is not needed
when an invalid G-stage PTE becomes valid and Svvptc extension is available
because new valid PTEs become visible to the page-table walker within a
bounded time.

Assisted-by: YuanSheng: deepseek-v4-pro
Co-developed-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Quan Zhou <zhouquan@iscas.ac.cn>
Signed-off-by: Dylan.Wu <fredwudi0305@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260701075239.95542-1-fredwudi0305@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
arch/riscv/kvm/gstage.c

index c4c3b79567f10d09a00cc2947e67dd140c49b30f..b0474fcf065aa2c5bb63e69a01dddf2625ec518d 100644 (file)
@@ -5,11 +5,13 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/cpufeature.h>
 #include <linux/errno.h>
 #include <linux/kvm_host.h>
 #include <linux/module.h>
 #include <linux/pgtable.h>
 #include <asm/kvm_gstage.h>
+#include <asm/hwcap.h>
 
 #ifdef CONFIG_64BIT
 unsigned long kvm_riscv_gstage_max_pgd_levels __ro_after_init = 3;
@@ -171,8 +173,10 @@ int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,
        }
 
        if (pte_val(*ptep) != pte_val(map->pte)) {
+               bool was_invalid = !pte_val(*ptep);
                set_pte(ptep, map->pte);
-               if (gstage_pte_leaf(ptep))
+               if (gstage_pte_leaf(ptep) &&
+                   !(was_invalid && riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC)))
                        gstage_tlb_flush(gstage, current_level, map->addr);
        }