summaryrefslogtreecommitdiff
path: root/arch/riscv
diff options
context:
space:
mode:
authorDylan.Wu <fredwudi0305@gmail.com>2026-07-01 03:52:39 -0400
committerAnup Patel <anup@brainfault.org>2026-07-13 18:17:01 +0530
commit1cc935ec2d87673e3c52ba04f943ab1276c0635b (patch)
tree1dec1809bbbb6d8cfd404133ed8882cc116e129f /arch/riscv
parent0cc15f2c7a55820bc0a1c7713222d1d7ee46cab4 (diff)
downloadlinux-next-1cc935ec2d87673e3c52ba04f943ab1276c0635b.tar.gz
linux-next-1cc935ec2d87673e3c52ba04f943ab1276c0635b.zip
riscv: kvm: Skip TLB flush when G-stage PTE becomes valid with Svvptc
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>
Diffstat (limited to 'arch/riscv')
-rw-r--r--arch/riscv/kvm/gstage.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/arch/riscv/kvm/gstage.c b/arch/riscv/kvm/gstage.c
index c4c3b79567f1..b0474fcf065a 100644
--- a/arch/riscv/kvm/gstage.c
+++ b/arch/riscv/kvm/gstage.c
@@ -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);
}