diff options
| author | Dylan.Wu <fredwudi0305@gmail.com> | 2026-07-01 03:52:39 -0400 |
|---|---|---|
| committer | Anup Patel <anup@brainfault.org> | 2026-07-13 18:17:01 +0530 |
| commit | 1cc935ec2d87673e3c52ba04f943ab1276c0635b (patch) | |
| tree | 1dec1809bbbb6d8cfd404133ed8882cc116e129f /arch/riscv | |
| parent | 0cc15f2c7a55820bc0a1c7713222d1d7ee46cab4 (diff) | |
| download | linux-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.c | 6 |
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); } |
