summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/riscv/include/asm/kvm_gstage.h4
-rw-r--r--arch/riscv/kvm/gstage.c14
2 files changed, 18 insertions, 0 deletions
diff --git a/arch/riscv/include/asm/kvm_gstage.h b/arch/riscv/include/asm/kvm_gstage.h
index f820c6783e16..21e2019df0cf 100644
--- a/arch/riscv/include/asm/kvm_gstage.h
+++ b/arch/riscv/include/asm/kvm_gstage.h
@@ -54,6 +54,10 @@ int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,
struct kvm_mmu_memory_cache *pcache,
const struct kvm_gstage_mapping *map);
+bool kvm_riscv_gstage_try_update_pte(struct kvm_gstage *gstage, u32 level,
+ gpa_t addr, pte_t *ptep,
+ pte_t old_pte, pte_t new_pte);
+
int kvm_riscv_gstage_map_page(struct kvm_gstage *gstage,
struct kvm_mmu_memory_cache *pcache,
gpa_t gpa, phys_addr_t hpa, unsigned long page_size,
diff --git a/arch/riscv/kvm/gstage.c b/arch/riscv/kvm/gstage.c
index d4ce5e76989c..d878100aeb35 100644
--- a/arch/riscv/kvm/gstage.c
+++ b/arch/riscv/kvm/gstage.c
@@ -123,6 +123,20 @@ static void gstage_tlb_flush(struct kvm_gstage *gstage, u32 level, gpa_t addr)
gstage->vmid);
}
+bool kvm_riscv_gstage_try_update_pte(struct kvm_gstage *gstage, u32 level,
+ gpa_t addr, pte_t *ptep,
+ pte_t old_pte, pte_t new_pte)
+{
+ if (cmpxchg(&ptep->pte, pte_val(old_pte), pte_val(new_pte)) !=
+ pte_val(old_pte))
+ return false;
+
+ if (pte_val(old_pte) != pte_val(new_pte))
+ gstage_tlb_flush(gstage, level, addr);
+
+ return true;
+}
+
int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,
struct kvm_mmu_memory_cache *pcache,
const struct kvm_gstage_mapping *map)