MMU related improvements for KVM RISC-V
Subsystems (3)
v2 cover MMU related improvements for KVM RISC-V
This series primarily has various MMU improvements for KVM RISC-V and it also serves as a preparatory series for the upcoming nested virtualization support.
PATCH1 to PATCH2: SBI spec related fixes in SBI RFENCE extension PATCH3 to PATCH6: Few cosmetic improvements
PATCH7 to PATCH8: TLB maintenance related improvements
PATCH9 to PATCH13: MMU related preparatory work for nested virtualization
These patches can also be found in the riscv_kvm_mmu_imp_v2 branch
at: https://github.com/avpatel/linux.git
Changes since v1:
- Rebased upon Linux-6.16-rc1
- Dropped PATCH1 and PATCH2 of v1 series since these are queued as fixes for Linux-6.16
- Addressed Atish's comment on PATCH1 in this series
- Added new PATCH7 in this series
Anup Patel (12):
RISC-V: KVM: Check kvm_riscv_vcpu_alloc_vector_context() return value
RISC-V: KVM: Drop the return value of kvm_riscv_vcpu_aia_init()
RISC-V: KVM: Rename and move kvm_riscv_local_tlb_sanitize()
RISC-V: KVM: Replace KVM_REQ_HFENCE_GVMA_VMID_ALL with
KVM_REQ_TLB_FLUSH
RISC-V: KVM: Don't flush TLB when PTE is unchanged
RISC-V: KVM: Implement kvm_arch_flush_remote_tlbs_range()
RISC-V: KVM: Use ncsr_xyz() in kvm_riscv_vcpu_trap_redirect()
RISC-V: KVM: Factor-out MMU related declarations into separate headers
RISC-V: KVM: Introduce struct kvm_gstage_mapping
RISC-V: KVM: Add vmid field to struct kvm_riscv_hfence
RISC-V: KVM: Factor-out g-stage page table management
RISC-V: KVM: Pass VMID as parameter to kvm_riscv_hfence_xyz() APIs
arch/riscv/include/asm/kvm_aia.h | 2 +- arch/riscv/include/asm/kvm_gstage.h | 72 ++++ arch/riscv/include/asm/kvm_host.h | 103 +----- arch/riscv/include/asm/kvm_mmu.h | 21 ++ arch/riscv/include/asm/kvm_tlb.h | 84 +++++ arch/riscv/include/asm/kvm_vmid.h | 27 ++ arch/riscv/kvm/Makefile | 1 + arch/riscv/kvm/aia_device.c | 6 +- arch/riscv/kvm/aia_imsic.c | 12 +- arch/riscv/kvm/gstage.c | 338 +++++++++++++++++++ arch/riscv/kvm/main.c | 3 +- arch/riscv/kvm/mmu.c | 499 ++++++---------------------- arch/riscv/kvm/tlb.c | 110 +++--- arch/riscv/kvm/vcpu.c | 26 +- arch/riscv/kvm/vcpu_exit.c | 20 +- arch/riscv/kvm/vcpu_sbi_replace.c | 17 +- arch/riscv/kvm/vcpu_sbi_v01.c | 25 +- arch/riscv/kvm/vm.c | 7 +- arch/riscv/kvm/vmid.c | 25 ++ 19 files changed, 795 insertions(+), 603 deletions(-) create mode 100644 arch/riscv/include/asm/kvm_gstage.h create mode 100644 arch/riscv/include/asm/kvm_mmu.h create mode 100644 arch/riscv/include/asm/kvm_tlb.h create mode 100644 arch/riscv/include/asm/kvm_vmid.h create mode 100644 arch/riscv/kvm/gstage.c
Signature · 1 line
2.43.0
PATCH v2 1/12 RISC-V: KVM: Check kvm_riscv_vcpu_alloc_vector_context() return value
The kvm_riscv_vcpu_alloc_vector_context() does return an error code upon failure so don't ignore this in kvm_arch_vcpu_create().
--- arch/riscv/kvm/vcpu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/riscv/kvm/vcpu.c +3 -2
@@ -148,8 +148,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)spin_lock_init (&vcpu->arch.reset_state.lock); -if (kvm_riscv_vcpu_alloc_vector_context (vcpu)) -return -ENOMEM ; + rc =kvm_riscv_vcpu_alloc_vector_context (vcpu); +if (rc) +return rc;/* Setup VCPU timer */ kvm_riscv_vcpu_timer_init (vcpu);
Signature · 1 line
2.43.0
PATCH v2 2/12 RISC-V: KVM: Drop the return value of kvm_riscv_vcpu_aia_init()
In reply to Anup PatelThe kvm_riscv_vcpu_aia_init() does not return any failure so drop the return value which is always zero.
--- arch/riscv/include/asm/kvm_aia.h | 2 +- arch/riscv/kvm/aia_device.c | 6 ++---- arch/riscv/kvm/vcpu.c | 4 +--- 3 files changed, 4 insertions(+), 8 deletions(-)
arch/riscv/include/asm/kvm_aia.h +1 -1
@@ -147,7 +147,7 @@ int kvm_riscv_vcpu_aia_rmw_ireg(struct kvm_vcpu *vcpu, unsigned int csr_num,int kvm_riscv_vcpu_aia_update (struct kvm_vcpu *vcpu);void kvm_riscv_vcpu_aia_reset (struct kvm_vcpu *vcpu); -int kvm_riscv_vcpu_aia_init (struct kvm_vcpu *vcpu); +void kvm_riscv_vcpu_aia_init (struct kvm_vcpu *vcpu);void kvm_riscv_vcpu_aia_deinit (struct kvm_vcpu *vcpu); int kvm_riscv_aia_inject_msi_by_id(struct kvm *kvm, u32 hart_index,
arch/riscv/kvm/aia_device.c +2 -4
@@ -509,12 +509,12 @@ void kvm_riscv_vcpu_aia_reset(struct kvm_vcpu *vcpu)kvm_riscv_vcpu_aia_imsic_reset (vcpu); } -int kvm_riscv_vcpu_aia_init (struct kvm_vcpu *vcpu) +void kvm_riscv_vcpu_aia_init (struct kvm_vcpu *vcpu) {struct kvm_vcpu_aia *vaia = &vcpu->arch.aia_context;if (!kvm_riscv_aia_available ()) -return 0 ; +return ;/* * We don't do any memory allocations over here because these
@@ -526,8 +526,6 @@ int kvm_riscv_vcpu_aia_init(struct kvm_vcpu *vcpu)/* Initialize default values in AIA vcpu context */ vaia->imsic_addr =KVM_RISCV_AIA_UNDEF_ADDR ; vaia->hart_index = vcpu->vcpu_idx; - -return 0 ; }void kvm_riscv_vcpu_aia_deinit (struct kvm_vcpu *vcpu)
arch/riscv/kvm/vcpu.c +1 -3
@@ -159,9 +159,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)kvm_riscv_vcpu_pmu_init (vcpu);/* Setup VCPU AIA */ - rc =kvm_riscv_vcpu_aia_init (vcpu); -if (rc) -return rc; +kvm_riscv_vcpu_aia_init (vcpu);/* * Setup SBI extensions
Signature · 1 line
2.43.0
PATCH v2 3/12 RISC-V: KVM: Rename and move kvm_riscv_local_tlb_sanitize()
In reply to Anup PatelThe kvm_riscv_local_tlb_sanitize() deals with sanitizing current VMID related TLB mappings when a VCPU is moved from one host CPU to another.
Let's move kvm_riscv_local_tlb_sanitize() to VMID management sources and rename it to kvm_riscv_gstage_vmid_sanitize().
--- arch/riscv/include/asm/kvm_host.h | 3 +-- arch/riscv/kvm/tlb.c | 23 ----------------------- arch/riscv/kvm/vcpu.c | 4 ++-- arch/riscv/kvm/vmid.c | 23 +++++++++++++++++++++++ 4 files changed, 26 insertions(+), 27 deletions(-)
arch/riscv/include/asm/kvm_host.h +1 -2
@@ -331,8 +331,6 @@ void kvm_riscv_local_hfence_vvma_gva(unsigned long vmid, unsigned long order);void kvm_riscv_local_hfence_vvma_all (unsigned long vmid); -void kvm_riscv_local_tlb_sanitize (struct kvm_vcpu *vcpu); -void kvm_riscv_fence_i_process (struct kvm_vcpu *vcpu);void kvm_riscv_hfence_gvma_vmid_all_process (struct kvm_vcpu *vcpu);void kvm_riscv_hfence_vvma_all_process (struct kvm_vcpu *vcpu);
@@ -380,6 +378,7 @@ unsigned long kvm_riscv_gstage_vmid_bits(void);int kvm_riscv_gstage_vmid_init (struct kvm *kvm);bool kvm_riscv_gstage_vmid_ver_changed (struct kvm_vmid *vmid);void kvm_riscv_gstage_vmid_update (struct kvm_vcpu *vcpu); +void kvm_riscv_gstage_vmid_sanitize (struct kvm_vcpu *vcpu);int kvm_riscv_setup_default_irq_routing (struct kvm *kvm,u32 lines);
arch/riscv/kvm/tlb.c +0 -23
@@ -156,29 +156,6 @@ void kvm_riscv_local_hfence_vvma_all(unsigned long vmid)csr_write (CSR_HGATP , hgatp); } -void kvm_riscv_local_tlb_sanitize (struct kvm_vcpu *vcpu) -{ -unsigned long vmid; - -if (!kvm_riscv_gstage_vmid_bits () || - vcpu->arch.last_exit_cpu == vcpu->cpu) -return ; - -/* -* On RISC-V platforms with hardware VMID support, we share same -* VMID for all VCPUs of a particular Guest/VM. This means we might -* have stale G-stage TLB entries on the current Host CPU due to -* some other VCPU of the same Guest which ran previously on the -* current Host CPU. -* -* To cleanup stale TLB entries, we simply flush all G-stage TLB -* entries by VMID whenever underlying Host CPU changes for a VCPU. -*/ - - vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid); -kvm_riscv_local_hfence_gvma_vmid_all (vmid); -} -void kvm_riscv_fence_i_process (struct kvm_vcpu *vcpu) {kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_FENCE_I_RCVD );
arch/riscv/kvm/vcpu.c +2 -2
@@ -962,12 +962,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) }/* -* Cleanup stale TLB enteries +* Sanitize VMID mappings cached (TLB) on current CPU * * Note: This should be done after G-stage VMID has been * updated using kvm_riscv_gstage_vmid_ver_changed() */ -kvm_riscv_local_tlb_sanitize (vcpu); +kvm_riscv_gstage_vmid_sanitize (vcpu);trace_kvm_entry (vcpu);
arch/riscv/kvm/vmid.c +23 -0
@@ -122,3 +122,26 @@ void kvm_riscv_gstage_vmid_update(struct kvm_vcpu *vcpu)kvm_for_each_vcpu (i, v, vcpu->kvm)kvm_make_request (KVM_REQ_UPDATE_HGATP , v); } + +void kvm_riscv_gstage_vmid_sanitize (struct kvm_vcpu *vcpu) +{ +unsigned long vmid; + +if (!kvm_riscv_gstage_vmid_bits () || + vcpu->arch.last_exit_cpu == vcpu->cpu) +return ; + +/* +* On RISC-V platforms with hardware VMID support, we share same +* VMID for all VCPUs of a particular Guest/VM. This means we might +* have stale G-stage TLB entries on the current Host CPU due to +* some other VCPU of the same Guest which ran previously on the +* current Host CPU. +* +* To cleanup stale TLB entries, we simply flush all G-stage TLB +* entries by VMID whenever underlying Host CPU changes for a VCPU. +*/ + + vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid); +kvm_riscv_local_hfence_gvma_vmid_all (vmid); +}
Signature · 1 line
2.43.0
PATCH v2 4/12 RISC-V: KVM: Replace KVM_REQ_HFENCE_GVMA_VMID_ALL with KVM_REQ_TLB_FLUSH
In reply to Anup PatelThe KVM_REQ_HFENCE_GVMA_VMID_ALL is same as KVM_REQ_TLB_FLUSH so to avoid confusion let's replace KVM_REQ_HFENCE_GVMA_VMID_ALL with KVM_REQ_TLB_FLUSH. Also, rename kvm_riscv_hfence_gvma_vmid_all_process() to kvm_riscv_tlb_flush_process().
--- arch/riscv/include/asm/kvm_host.h | 4 ++-- arch/riscv/kvm/tlb.c | 8 ++++---- arch/riscv/kvm/vcpu.c | 8 ++------ 3 files changed, 8 insertions(+), 12 deletions(-)
arch/riscv/include/asm/kvm_host.h +2 -2
@@ -37,7 +37,6 @@#define KVM_REQ_UPDATE_HGATP KVM_ARCH_REQ(2)#define KVM_REQ_FENCE_I \ KVM_ARCH_REQ_FLAGS(3, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) -#define KVM_REQ_HFENCE_GVMA_VMID_ALL KVM_REQ_TLB_FLUSH#define KVM_REQ_HFENCE_VVMA_ALL \ KVM_ARCH_REQ_FLAGS(4, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)#define KVM_REQ_HFENCE \
@@ -331,8 +330,9 @@ void kvm_riscv_local_hfence_vvma_gva(unsigned long vmid, unsigned long order);void kvm_riscv_local_hfence_vvma_all (unsigned long vmid); +void kvm_riscv_tlb_flush_process (struct kvm_vcpu *vcpu); +void kvm_riscv_fence_i_process (struct kvm_vcpu *vcpu); -void kvm_riscv_hfence_gvma_vmid_all_process (struct kvm_vcpu *vcpu);void kvm_riscv_hfence_vvma_all_process (struct kvm_vcpu *vcpu);void kvm_riscv_hfence_process (struct kvm_vcpu *vcpu);
arch/riscv/kvm/tlb.c +4 -4
@@ -162,7 +162,7 @@ void kvm_riscv_fence_i_process(struct kvm_vcpu *vcpu)local_flush_icache_all (); } -void kvm_riscv_hfence_gvma_vmid_all_process (struct kvm_vcpu *vcpu) +void kvm_riscv_tlb_flush_process (struct kvm_vcpu *vcpu) {struct kvm_vmid *v = &vcpu->kvm->arch.vmid;unsigned long vmid =READ_ONCE (v->vmid);
@@ -342,14 +342,14 @@ void kvm_riscv_hfence_gvma_vmid_gpa(struct kvm *kvm, data.size = gpsz; data.order = order;make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE , -KVM_REQ_HFENCE_GVMA_VMID_ALL , &data); +KVM_REQ_TLB_FLUSH , &data); }void kvm_riscv_hfence_gvma_vmid_all (struct kvm *kvm,unsigned long hbase,unsigned long hmask) { -make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE_GVMA_VMID_ALL , -KVM_REQ_HFENCE_GVMA_VMID_ALL ,NULL ); +make_xfence_request (kvm, hbase, hmask,KVM_REQ_TLB_FLUSH , +KVM_REQ_TLB_FLUSH ,NULL ); } void kvm_riscv_hfence_vvma_asid_gva(struct kvm *kvm,
arch/riscv/kvm/vcpu.c +2 -6
@@ -721,12 +721,8 @@ static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu)if (kvm_check_request (KVM_REQ_FENCE_I , vcpu))kvm_riscv_fence_i_process (vcpu); -/* -* The generic KVM_REQ_TLB_FLUSH is same as -* KVM_REQ_HFENCE_GVMA_VMID_ALL -*/ -if (kvm_check_request (KVM_REQ_HFENCE_GVMA_VMID_ALL , vcpu)) -kvm_riscv_hfence_gvma_vmid_all_process (vcpu); +if (kvm_check_request (KVM_REQ_TLB_FLUSH , vcpu)) +kvm_riscv_tlb_flush_process (vcpu);if (kvm_check_request (KVM_REQ_HFENCE_VVMA_ALL , vcpu))kvm_riscv_hfence_vvma_all_process (vcpu);
Signature · 1 line
2.43.0
PATCH v2 5/12 RISC-V: KVM: Don't flush TLB when PTE is unchanged
In reply to Anup PatelThe gstage_set_pte() and gstage_op_pte() should flush TLB only when a leaf PTE changes so that unnecessary TLB flushes can be avoided.
--- arch/riscv/kvm/mmu.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
arch/riscv/kvm/mmu.c +9 -5
@@ -167,9 +167,11 @@ static int gstage_set_pte(struct kvm *kvm, u32 level, ptep = &next_ptep[gstage_pte_index (addr, current_level)]; } -set_pte (ptep, *new_pte); -if (gstage_pte_leaf (ptep)) -gstage_remote_tlb_flush (kvm, current_level, addr); +if (pte_val (*ptep) !=pte_val (*new_pte)) { +set_pte (ptep, *new_pte); +if (gstage_pte_leaf (ptep)) +gstage_remote_tlb_flush (kvm, current_level, addr); + }return 0 ; }
@@ -229,7 +231,7 @@ static void gstage_op_pte(struct kvm *kvm, gpa_t addr, pte_t *ptep, u32 ptep_level, enum gstage_op op) { int i, ret; -pte_t *next_ptep; +pte_t old_pte, *next_ptep;u32 next_ptep_level;unsigned long next_page_size, page_size;
@@ -258,11 +260,13 @@ static void gstage_op_pte(struct kvm *kvm, gpa_t addr,if (op ==GSTAGE_OP_CLEAR )put_page (virt_to_page (next_ptep)); }else { + old_pte = *ptep;if (op ==GSTAGE_OP_CLEAR )set_pte (ptep,__pte (0 ));else if (op ==GSTAGE_OP_WP )set_pte (ptep,__pte (pte_val (ptep_get (ptep)) & ~_PAGE_WRITE)); -gstage_remote_tlb_flush (kvm, ptep_level, addr); +if (pte_val (*ptep) !=pte_val (old_pte)) +gstage_remote_tlb_flush (kvm, ptep_level, addr); } }
Signature · 1 line
2.43.0
Re: [PATCH v2 05/12] RISC-V: KVM: Don't flush TLB when PTE is unchanged
Quoted 41 lines · Anup Patel
The
gstage_set_pte()andgstage_op_pte()should flush TLB only when a leaf PTE changes so that unnecessary TLB flushes can be avoided.Signed-off-by Anup Patel <[email protected]>--- arch/riscv/kvm/mmu.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)arch/riscv/kvm/mmu.c +7
-4@@ -167,9 +167,11 @@ static int gstage_set_pte(struct kvm *kvm, u32 level, ptep = &next_ptep[gstage_pte_index (addr, current_level)]; } -set_pte (ptep, *new_pte); -if (gstage_pte_leaf (ptep)) -gstage_remote_tlb_flush (kvm, current_level, addr); +if (pte_val (*ptep) !=pte_val (*new_pte)) { +set_pte (ptep, *new_pte); +if (gstage_pte_leaf (ptep)) +gstage_remote_tlb_flush (kvm, current_level, addr); + }return 0 ; }@@ -229,7 +231,7 @@ static void gstage_op_pte(struct kvm *kvm, gpa_t addr, pte_t *ptep, u32 ptep_level, enum gstage_op op) { int i, ret; -pte_t *next_ptep; +pte_t old_pte, *next_ptep;u32 next_ptep_level;unsigned long next_page_size, page_size;@@ -258,11 +260,13 @@ static void gstage_op_pte(struct kvm *kvm, gpa_t addr,if (op ==GSTAGE_OP_CLEAR )put_page (virt_to_page (next_ptep)); }else { + old_pte = *ptep;
arch/riscv/kvm/mmu.c static void gstage_op_pte(struct kvm *kvm, gpa_t addr, · line 272
Quoted 10 lines
arch/riscv/kvm/mmu.c +2
-1if (op ==GSTAGE_OP_CLEAR )set_pte (ptep,__pte (0 ));else if (op ==GSTAGE_OP_WP )set_pte (ptep,__pte (pte_val (ptep_get (ptep)) & ~_PAGE_WRITE)); -gstage_remote_tlb_flush (kvm, ptep_level, addr); +if (pte_val (*ptep) !=pte_val (old_pte)) +gstage_remote_tlb_flush (kvm, ptep_level, addr); } }
PATCH v2 6/12 RISC-V: KVM: Implement kvm_arch_flush_remote_tlbs_range()
In reply to Anup PatelThe kvm_arch_flush_remote_tlbs_range() expected by KVM core can be easily implemented for RISC-V using kvm_riscv_hfence_gvma_vmid_gpa() hence provide it.
Also with kvm_arch_flush_remote_tlbs_range() available for RISC-V, the mmu_wp_memory_region() can happily use kvm_flush_remote_tlbs_memslot() instead of kvm_flush_remote_tlbs().
--- arch/riscv/include/asm/kvm_host.h | 2 ++ arch/riscv/kvm/mmu.c | 2 +- arch/riscv/kvm/tlb.c | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-)
arch/riscv/include/asm/kvm_host.h +2 -0
@@ -43,6 +43,8 @@ KVM_ARCH_REQ_FLAGS(5, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)#define KVM_REQ_STEAL_UPDATE KVM_ARCH_REQ(6) +#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS_RANGE +#define KVM_HEDELEG_DEFAULT (BIT(EXC_INST_MISALIGNED) | \ BIT(EXC_BREAKPOINT) | \ BIT(EXC_SYSCALL) | \
arch/riscv/kvm/mmu.c +1 -1
@@ -344,7 +344,7 @@ static void gstage_wp_memory_region(struct kvm *kvm, int slot)spin_lock (&kvm->mmu_lock);gstage_wp_range (kvm, start, end);spin_unlock (&kvm->mmu_lock); -kvm_flush_remote_tlbs (kvm); +kvm_flush_remote_tlbs_memslot (kvm, memslot); } int kvm_riscv_gstage_ioremap(struct kvm *kvm, gpa_t gpa,
arch/riscv/kvm/tlb.c +8 -0
@@ -403,3 +403,11 @@ void kvm_riscv_hfence_vvma_all(struct kvm *kvm,make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE_VVMA_ALL ,KVM_REQ_HFENCE_VVMA_ALL ,NULL ); } + +int kvm_arch_flush_remote_tlbs_range (struct kvm *kvm,gfn_t gfn,u64 nr_pages) +{ +kvm_riscv_hfence_gvma_vmid_gpa (kvm,-1UL ,0 , + gfn <<PAGE_SHIFT , nr_pages <<PAGE_SHIFT , +PAGE_SHIFT ); +return 0 ; +}
Signature · 1 line
2.43.0
Re: [PATCH v2 06/12] RISC-V: KVM: Implement kvm_arch_flush_remote_tlbs_range()
Quoted 47 lines · Anup Patel
The
kvm_arch_flush_remote_tlbs_range()expected by KVM core can be easily implemented for RISC-V usingkvm_riscv_hfence_gvma_vmid_gpa()hence provide it.Also with
kvm_arch_flush_remote_tlbs_range()available for RISC-V, themmu_wp_memory_region()can happily usekvm_flush_remote_tlbs_memslot()instead ofkvm_flush_remote_tlbs().Signed-off-by Anup Patel <[email protected]>--- arch/riscv/include/asm/kvm_host.h | 2 ++ arch/riscv/kvm/mmu.c | 2 +- arch/riscv/kvm/tlb.c | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-)arch/riscv/include/asm/kvm_host.h +2
-0@@ -43,6 +43,8 @@ KVM_ARCH_REQ_FLAGS(5, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)#define KVM_REQ_STEAL_UPDATE KVM_ARCH_REQ(6) +#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS_RANGE +#define KVM_HEDELEG_DEFAULT (BIT(EXC_INST_MISALIGNED) | \ BIT(EXC_BREAKPOINT) | \ BIT(EXC_SYSCALL) | \arch/riscv/kvm/mmu.c +1
-1@@ -344,7 +344,7 @@ static void gstage_wp_memory_region(struct kvm *kvm, int slot)spin_lock (&kvm->mmu_lock);gstage_wp_range (kvm, start, end);spin_unlock (&kvm->mmu_lock); -kvm_flush_remote_tlbs (kvm); +kvm_flush_remote_tlbs_memslot (kvm, memslot); } int kvm_riscv_gstage_ioremap(struct kvm *kvm, gpa_t gpa,arch/riscv/kvm/tlb.c +0
-0@@ -403,3 +403,11 @@ void kvm_riscv_hfence_vvma_all(struct kvm *kvm, make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE_VVMA_ALL,
arch/riscv/kvm/tlb.c void kvm_riscv_hfence_vvma_all(struct kvm *kvm, · line 413
Quoted 10 lines
arch/riscv/kvm/tlb.c +8
-0KVM_REQ_HFENCE_VVMA_ALL, NULL); } + +int kvm_arch_flush_remote_tlbs_range (struct kvm *kvm,gfn_t gfn,u64 nr_pages) +{ +kvm_riscv_hfence_gvma_vmid_gpa (kvm,-1UL ,0 , + gfn <<PAGE_SHIFT , nr_pages <<PAGE_SHIFT , +PAGE_SHIFT ); +return 0 ; +}
LGTM. However, I noticed that kvm_flush_remote_tlbs_range doesn't increment remote_tlb_flush_requests/remote_tlb_flush stat counter.
So we would be losing those stats here. Do you know if there is a specific reason behind not supporting the stat counters in the *tlbs_range function ?
Otherwise,
Re: [PATCH v2 06/12] RISC-V: KVM: Implement kvm_arch_flush_remote_tlbs_range()
Quoted 64 lines · Atish Patra
Quoted 47 lines · Anup Patel
The
kvm_arch_flush_remote_tlbs_range()expected by KVM core can be easily implemented for RISC-V usingkvm_riscv_hfence_gvma_vmid_gpa()hence provide it.Also with
kvm_arch_flush_remote_tlbs_range()available for RISC-V, themmu_wp_memory_region()can happily usekvm_flush_remote_tlbs_memslot()instead ofkvm_flush_remote_tlbs().Signed-off-by Anup Patel <[email protected]>--- arch/riscv/include/asm/kvm_host.h | 2 ++ arch/riscv/kvm/mmu.c | 2 +- arch/riscv/kvm/tlb.c | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-)arch/riscv/include/asm/kvm_host.h +2
-0@@ -43,6 +43,8 @@ KVM_ARCH_REQ_FLAGS(5, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)#define KVM_REQ_STEAL_UPDATE KVM_ARCH_REQ(6) +#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS_RANGE +#define KVM_HEDELEG_DEFAULT (BIT(EXC_INST_MISALIGNED) | \ BIT(EXC_BREAKPOINT) | \ BIT(EXC_SYSCALL) | \arch/riscv/kvm/mmu.c +1
-1@@ -344,7 +344,7 @@ static void gstage_wp_memory_region(struct kvm *kvm, int slot)spin_lock (&kvm->mmu_lock);gstage_wp_range (kvm, start, end);spin_unlock (&kvm->mmu_lock); -kvm_flush_remote_tlbs (kvm); +kvm_flush_remote_tlbs_memslot (kvm, memslot); } int kvm_riscv_gstage_ioremap(struct kvm *kvm, gpa_t gpa,arch/riscv/kvm/tlb.c +0
-0@@ -403,3 +403,11 @@ void kvm_riscv_hfence_vvma_all(struct kvm *kvm, make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE_VVMA_ALL,arch/riscv/kvm/tlb.c void kvm_riscv_hfence_vvma_all(struct kvm *kvm, · line 413
Quoted 10 lines
arch/riscv/kvm/tlb.c +8
-0KVM_REQ_HFENCE_VVMA_ALL, NULL); } + +int kvm_arch_flush_remote_tlbs_range (struct kvm *kvm,gfn_t gfn,u64 nr_pages) +{ +kvm_riscv_hfence_gvma_vmid_gpa (kvm,-1UL ,0 , + gfn <<PAGE_SHIFT , nr_pages <<PAGE_SHIFT , +PAGE_SHIFT ); +return 0 ; +}LGTM. However, I noticed that
kvm_flush_remote_tlbs_rangedoesn't increment remote_tlb_flush_requests/remote_tlb_flush stat counter.
Quoted 3 lines
So we would be losing those stats here. Do you know if there is a specific reason behind not supporting the stat counters in the
*tlbs_rangefunction ?
Looks like this was missed out in generic kvm_flush_remote_tlbs_range().
Regards,
Anup
PATCH v2 7/12 RISC-V: KVM: Use ncsr_xyz() in kvm_riscv_vcpu_trap_redirect()
In reply to Anup PatelThe H-extension CSRs accessed by kvm_riscv_vcpu_trap_redirect() will trap when KVM RISC-V is running as Guest/VM hence remove these traps by using ncsr_xyz() instead of csr_xyz().
--- arch/riscv/kvm/vcpu_exit.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
arch/riscv/kvm/vcpu_exit.c +7 -6
@@ -9,6 +9,7 @@#include <linux/kvm_host.h> #include <asm/csr.h> #include <asm/insn-def.h> +#include <asm/kvm_nacl.h> static int gstage_page_fault (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_cpu_trap *trap)
@@ -135,7 +136,7 @@ unsigned long kvm_riscv_vcpu_unpriv_read(struct kvm_vcpu *vcpu,void kvm_riscv_vcpu_trap_redirect (struct kvm_vcpu *vcpu,struct kvm_cpu_trap *trap) { -unsigned long vsstatus =csr_read (CSR_VSSTATUS ); +unsigned long vsstatus =ncsr_read (CSR_VSSTATUS );/* Change Guest SSTATUS.SPP bit */ vsstatus &= ~SR_SPP ;
@@ -151,15 +152,15 @@ void kvm_riscv_vcpu_trap_redirect(struct kvm_vcpu *vcpu, vsstatus &= ~SR_SIE ;/* Update Guest SSTATUS */ -csr_write (CSR_VSSTATUS , vsstatus); +ncsr_write (CSR_VSSTATUS , vsstatus);/* Update Guest SCAUSE, STVAL, and SEPC */ -csr_write (CSR_VSCAUSE , trap->scause); -csr_write (CSR_VSTVAL , trap->stval); -csr_write (CSR_VSEPC , trap->sepc); +ncsr_write (CSR_VSCAUSE , trap->scause); +ncsr_write (CSR_VSTVAL , trap->stval); +ncsr_write (CSR_VSEPC , trap->sepc);/* Set Guest PC to Guest exception vector */ - vcpu->arch.guest_context.sepc =csr_read (CSR_VSTVEC ); + vcpu->arch.guest_context.sepc =ncsr_read (CSR_VSTVEC );/* Set Guest privilege mode to supervisor */ vcpu->arch.guest_context.sstatus |=SR_SPP ;
Signature · 1 line
2.43.0
Re: [PATCH v2 07/12] RISC-V: KVM: Use ncsr_xyz() in kvm_riscv_vcpu_trap_redirect()
Quoted 41 lines · Anup Patel
The H-extension CSRs accessed by
kvm_riscv_vcpu_trap_redirect()will trap when KVM RISC-V is running as Guest/VM hence remove these traps by usingncsr_xyz()instead ofcsr_xyz().Signed-off-by Anup Patel <[email protected]>--- arch/riscv/kvm/vcpu_exit.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)arch/riscv/kvm/vcpu_exit.c +3
-5@@ -9,6 +9,7 @@#include <linux/kvm_host.h> #include <asm/csr.h> #include <asm/insn-def.h> +#include <asm/kvm_nacl.h> static int gstage_page_fault (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_cpu_trap *trap)@@ -135,7 +136,7 @@ unsigned long kvm_riscv_vcpu_unpriv_read(struct kvm_vcpu *vcpu,void kvm_riscv_vcpu_trap_redirect (struct kvm_vcpu *vcpu,struct kvm_cpu_trap *trap) { -unsigned long vsstatus =csr_read (CSR_VSSTATUS ); +unsigned long vsstatus =ncsr_read (CSR_VSSTATUS );/* Change Guest SSTATUS.SPP bit */ vsstatus &= ~SR_SPP ;@@ -151,15 +152,15 @@ void kvm_riscv_vcpu_trap_redirect(struct kvm_vcpu *vcpu, vsstatus &= ~SR_SIE ;/* Update Guest SSTATUS */ -csr_write (CSR_VSSTATUS , vsstatus); +ncsr_write (CSR_VSSTATUS , vsstatus);/* Update Guest SCAUSE, STVAL, and SEPC */ -csr_write (CSR_VSCAUSE , trap->scause); -csr_write (CSR_VSTVAL , trap->stval); -csr_write (CSR_VSEPC , trap->sepc);
arch/riscv/kvm/vcpu_exit.c void kvm_riscv_vcpu_trap_redirect(struct kvm_vcpu *vcpu, · line 166
Quoted 10 lines
arch/riscv/kvm/vcpu_exit.c +4
-1+ncsr_write (CSR_VSCAUSE , trap->scause); +ncsr_write (CSR_VSTVAL , trap->stval); +ncsr_write (CSR_VSEPC , trap->sepc);/* Set Guest PC to Guest exception vector */ - vcpu->arch.guest_context.sepc =csr_read (CSR_VSTVEC ); + vcpu->arch.guest_context.sepc =ncsr_read (CSR_VSTVEC );/* Set Guest privilege mode to supervisor */ vcpu->arch.guest_context.sstatus |=SR_SPP ;
PATCH v2 8/12 RISC-V: KVM: Factor-out MMU related declarations into separate headers
In reply to Anup PatelThe MMU, TLB, and VMID management for KVM RISC-V already exists as seprate sources so create separate headers along these lines. This further simplifies asm/kvm_host.h header.
--- arch/riscv/include/asm/kvm_host.h | 100 +----------------------------- arch/riscv/include/asm/kvm_mmu.h | 26 ++++++++ arch/riscv/include/asm/kvm_tlb.h | 78 +++++++++++++++++++++++ arch/riscv/include/asm/kvm_vmid.h | 27 ++++++++ arch/riscv/kvm/aia_imsic.c | 1 + arch/riscv/kvm/main.c | 1 + arch/riscv/kvm/mmu.c | 1 + arch/riscv/kvm/tlb.c | 2 + arch/riscv/kvm/vcpu.c | 1 + arch/riscv/kvm/vcpu_exit.c | 1 + arch/riscv/kvm/vm.c | 1 + arch/riscv/kvm/vmid.c | 2 + 12 files changed, 143 insertions(+), 98 deletions(-) create mode 100644 arch/riscv/include/asm/kvm_mmu.h create mode 100644 arch/riscv/include/asm/kvm_tlb.h create mode 100644 arch/riscv/include/asm/kvm_vmid.h
arch/riscv/include/asm/kvm_host.h +2 -98
@@ -16,6 +16,8 @@#include <asm/hwcap.h> #include <asm/kvm_aia.h> #include <asm/ptrace.h> +#include <asm/kvm_tlb.h> +#include <asm/kvm_vmid.h> #include <asm/kvm_vcpu_fp.h> #include <asm/kvm_vcpu_insn.h> #include <asm/kvm_vcpu_sbi.h>
@@ -56,24 +58,6 @@ BIT(IRQ_VS_TIMER) | \ BIT(IRQ_VS_EXT)) -enum kvm_riscv_hfence_type { -KVM_RISCV_HFENCE_UNKNOWN =0 , -KVM_RISCV_HFENCE_GVMA_VMID_GPA , -KVM_RISCV_HFENCE_VVMA_ASID_GVA , -KVM_RISCV_HFENCE_VVMA_ASID_ALL , -KVM_RISCV_HFENCE_VVMA_GVA , -}; - -struct kvm_riscv_hfence { -enum kvm_riscv_hfence_type type; -unsigned long asid; -unsigned long order; -gpa_t addr; -gpa_t size; -}; - -#define KVM_RISCV_VCPU_MAX_HFENCE 64 -struct kvm_vm_stat {struct kvm_vm_stat_generic generic; };
@@ -99,15 +83,6 @@ struct kvm_vcpu_stat {struct kvm_arch_memory_slot { }; -struct kvm_vmid { -/* -* Writes to vmid_version and vmid happen with vmid_lock held -* whereas reads happen without any lock held. -*/ -unsigned long vmid_version; -unsigned long vmid; -}; -struct kvm_arch {/* G-stage vmid */ struct kvm_vmid vmid;
@@ -311,77 +286,6 @@ static inline bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu)return IS_ENABLED (CONFIG_GUEST_PERF_EVENTS ) && !!vcpu; } -#define KVM_RISCV_GSTAGE_TLB_MIN_ORDER 12 - -void kvm_riscv_local_hfence_gvma_vmid_gpa (unsigned long vmid, -gpa_t gpa,gpa_t gpsz, -unsigned long order); -void kvm_riscv_local_hfence_gvma_vmid_all (unsigned long vmid); -void kvm_riscv_local_hfence_gvma_gpa (gpa_t gpa,gpa_t gpsz, -unsigned long order); -void kvm_riscv_local_hfence_gvma_all (void ); -void kvm_riscv_local_hfence_vvma_asid_gva (unsigned long vmid, -unsigned long asid, -unsigned long gva, -unsigned long gvsz, -unsigned long order); -void kvm_riscv_local_hfence_vvma_asid_all (unsigned long vmid, -unsigned long asid); -void kvm_riscv_local_hfence_vvma_gva (unsigned long vmid, -unsigned long gva,unsigned long gvsz, -unsigned long order); -void kvm_riscv_local_hfence_vvma_all (unsigned long vmid); - -void kvm_riscv_tlb_flush_process (struct kvm_vcpu *vcpu); - -void kvm_riscv_fence_i_process (struct kvm_vcpu *vcpu); -void kvm_riscv_hfence_vvma_all_process (struct kvm_vcpu *vcpu); -void kvm_riscv_hfence_process (struct kvm_vcpu *vcpu); - -void kvm_riscv_fence_i (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); -void kvm_riscv_hfence_gvma_vmid_gpa (struct kvm *kvm, -unsigned long hbase,unsigned long hmask, -gpa_t gpa,gpa_t gpsz, -unsigned long order); -void kvm_riscv_hfence_gvma_vmid_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); -void kvm_riscv_hfence_vvma_asid_gva (struct kvm *kvm, -unsigned long hbase,unsigned long hmask, -unsigned long gva,unsigned long gvsz, -unsigned long order,unsigned long asid); -void kvm_riscv_hfence_vvma_asid_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask, -unsigned long asid); -void kvm_riscv_hfence_vvma_gva (struct kvm *kvm, -unsigned long hbase,unsigned long hmask, -unsigned long gva,unsigned long gvsz, -unsigned long order); -void kvm_riscv_hfence_vvma_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); - -int kvm_riscv_gstage_ioremap (struct kvm *kvm,gpa_t gpa, -phys_addr_t hpa,unsigned long size, -bool writable,bool in_atomic); -void kvm_riscv_gstage_iounmap (struct kvm *kvm,gpa_t gpa, -unsigned long size); -int kvm_riscv_gstage_map (struct kvm_vcpu *vcpu, -struct kvm_memory_slot *memslot, -gpa_t gpa,unsigned long hva,bool is_write); -int kvm_riscv_gstage_alloc_pgd (struct kvm *kvm); -void kvm_riscv_gstage_free_pgd (struct kvm *kvm); -void kvm_riscv_gstage_update_hgatp (struct kvm_vcpu *vcpu); -void __init kvm_riscv_gstage_mode_detect (void ); -unsigned long __init kvm_riscv_gstage_mode (void ); -int kvm_riscv_gstage_gpa_bits (void ); - -void __init kvm_riscv_gstage_vmid_detect (void ); -unsigned long kvm_riscv_gstage_vmid_bits (void ); -int kvm_riscv_gstage_vmid_init (struct kvm *kvm); -bool kvm_riscv_gstage_vmid_ver_changed (struct kvm_vmid *vmid); -void kvm_riscv_gstage_vmid_update (struct kvm_vcpu *vcpu); -void kvm_riscv_gstage_vmid_sanitize (struct kvm_vcpu *vcpu); -int kvm_riscv_setup_default_irq_routing (struct kvm *kvm,u32 lines);void __kvm_riscv_unpriv_trap (void );
arch/riscv/include/asm/kvm_mmu.h new file +26 -0
@@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (c) 2025 Ventana Micro Systems Inc. +*/ + +#ifndef __RISCV_KVM_MMU_H_ +#define __RISCV_KVM_MMU_H_ + +#include <linux/kvm_types.h> + +int kvm_riscv_gstage_ioremap (struct kvm *kvm,gpa_t gpa, +phys_addr_t hpa,unsigned long size, +bool writable,bool in_atomic); +void kvm_riscv_gstage_iounmap (struct kvm *kvm,gpa_t gpa, +unsigned long size); +int kvm_riscv_gstage_map (struct kvm_vcpu *vcpu, +struct kvm_memory_slot *memslot, +gpa_t gpa,unsigned long hva,bool is_write); +int kvm_riscv_gstage_alloc_pgd (struct kvm *kvm); +void kvm_riscv_gstage_free_pgd (struct kvm *kvm); +void kvm_riscv_gstage_update_hgatp (struct kvm_vcpu *vcpu); +void kvm_riscv_gstage_mode_detect (void ); +unsigned long kvm_riscv_gstage_mode (void ); +int kvm_riscv_gstage_gpa_bits (void ); + +#endif
arch/riscv/include/asm/kvm_tlb.h new file +78 -0
78 lines not on this page · raw message
arch/riscv/include/asm/kvm_vmid.h new file +27 -0
@@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (c) 2025 Ventana Micro Systems Inc. +*/ + +#ifndef __RISCV_KVM_VMID_H_ +#define __RISCV_KVM_VMID_H_ + +#include <linux/kvm_types.h> + +struct kvm_vmid { +/* +* Writes to vmid_version and vmid happen with vmid_lock held +* whereas reads happen without any lock held. +*/ +unsigned long vmid_version; +unsigned long vmid; +}; + +void __init kvm_riscv_gstage_vmid_detect (void ); +unsigned long kvm_riscv_gstage_vmid_bits (void ); +int kvm_riscv_gstage_vmid_init (struct kvm *kvm); +bool kvm_riscv_gstage_vmid_ver_changed (struct kvm_vmid *vmid); +void kvm_riscv_gstage_vmid_update (struct kvm_vcpu *vcpu); +void kvm_riscv_gstage_vmid_sanitize (struct kvm_vcpu *vcpu); + +#endif
arch/riscv/kvm/aia_imsic.c +1 -0
@@ -16,6 +16,7 @@#include <linux/swab.h> #include <kvm/iodev.h> #include <asm/csr.h> +#include <asm/kvm_mmu.h> #define IMSIC_MAX_EIX (IMSIC_MAX_ID / BITS_PER_TYPE(u64))
arch/riscv/kvm/main.c +1 -0
@@ -11,6 +11,7 @@#include <linux/module.h> #include <linux/kvm_host.h> #include <asm/cpufeature.h> +#include <asm/kvm_mmu.h> #include <asm/kvm_nacl.h> #include <asm/sbi.h>
arch/riscv/kvm/mmu.c +1 -0
@@ -15,6 +15,7 @@#include <linux/vmalloc.h> #include <linux/kvm_host.h> #include <linux/sched/signal.h> +#include <asm/kvm_mmu.h> #include <asm/kvm_nacl.h> #include <asm/page.h> #include <asm/pgtable.h>
arch/riscv/kvm/tlb.c +2 -0
@@ -15,6 +15,8 @@#include <asm/cpufeature.h> #include <asm/insn-def.h> #include <asm/kvm_nacl.h> +#include <asm/kvm_tlb.h> +#include <asm/kvm_vmid.h> #define has_svinval () riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)
arch/riscv/kvm/vcpu.c +1 -0
@@ -18,6 +18,7 @@#include <linux/fs.h> #include <linux/kvm_host.h> #include <asm/cacheflush.h> +#include <asm/kvm_mmu.h> #include <asm/kvm_nacl.h> #include <asm/kvm_vcpu_vector.h>
arch/riscv/kvm/vcpu_exit.c +1 -0
@@ -9,6 +9,7 @@#include <linux/kvm_host.h> #include <asm/csr.h> #include <asm/insn-def.h> +#include <asm/kvm_mmu.h> #include <asm/kvm_nacl.h> static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
arch/riscv/kvm/vm.c +1 -0
@@ -11,6 +11,7 @@#include <linux/module.h> #include <linux/uaccess.h> #include <linux/kvm_host.h> +#include <asm/kvm_mmu.h> const struct _kvm_stats_desc kvm_vm_stats_desc[] = {KVM_GENERIC_VM_STATS ()
arch/riscv/kvm/vmid.c +2 -0
@@ -14,6 +14,8 @@#include <linux/smp.h> #include <linux/kvm_host.h> #include <asm/csr.h> +#include <asm/kvm_tlb.h> +#include <asm/kvm_vmid.h> static unsigned long vmid_version =1 ;static unsigned long vmid_next;
Signature · 1 line
2.43.0
Re: [PATCH v2 08/12] RISC-V: KVM: Factor-out MMU related declarations into separate headers
Quoted 394 lines · Anup Patel
The MMU, TLB, and VMID management for KVM RISC-V already exists as seprate sources so create separate headers along these lines. This further simplifies
asm/kvm_host.hheader.Signed-off-by Anup Patel <[email protected]>--- arch/riscv/include/asm/kvm_host.h | 100 +----------------------------- arch/riscv/include/asm/kvm_mmu.h | 26 ++++++++ arch/riscv/include/asm/kvm_tlb.h | 78 +++++++++++++++++++++++ arch/riscv/include/asm/kvm_vmid.h | 27 ++++++++ arch/riscv/kvm/aia_imsic.c | 1 + arch/riscv/kvm/main.c | 1 + arch/riscv/kvm/mmu.c | 1 + arch/riscv/kvm/tlb.c | 2 + arch/riscv/kvm/vcpu.c | 1 + arch/riscv/kvm/vcpu_exit.c | 1 + arch/riscv/kvm/vm.c | 1 + arch/riscv/kvm/vmid.c | 2 + 12 files changed, 143 insertions(+), 98 deletions(-)create mode 100644
arch/riscv/include/asm/kvm_mmu.hcreate mode 100644arch/riscv/include/asm/kvm_tlb.hcreate mode 100644arch/riscv/include/asm/kvm_vmid.harch/riscv/include/asm/kvm_host.h +2
-98@@ -16,6 +16,8 @@#include <asm/hwcap.h> #include <asm/kvm_aia.h> #include <asm/ptrace.h> +#include <asm/kvm_tlb.h> +#include <asm/kvm_vmid.h> #include <asm/kvm_vcpu_fp.h> #include <asm/kvm_vcpu_insn.h> #include <asm/kvm_vcpu_sbi.h> @@ -56,24 +58,6 @@ BIT(IRQ_VS_TIMER) | \ BIT(IRQ_VS_EXT)) -enum kvm_riscv_hfence_type { -KVM_RISCV_HFENCE_UNKNOWN =0 , -KVM_RISCV_HFENCE_GVMA_VMID_GPA , -KVM_RISCV_HFENCE_VVMA_ASID_GVA , -KVM_RISCV_HFENCE_VVMA_ASID_ALL , -KVM_RISCV_HFENCE_VVMA_GVA , -}; - -struct kvm_riscv_hfence { -enum kvm_riscv_hfence_type type; -unsigned long asid; -unsigned long order; -gpa_t addr; -gpa_t size; -}; - -#define KVM_RISCV_VCPU_MAX_HFENCE 64 -struct kvm_vm_stat {struct kvm_vm_stat_generic generic; };@@ -99,15 +83,6 @@ struct kvm_vcpu_stat {struct kvm_arch_memory_slot { }; -struct kvm_vmid { -/* -* Writes to vmid_version and vmid happen with vmid_lock held -* whereas reads happen without any lock held. -*/ -unsigned long vmid_version; -unsigned long vmid; -}; -struct kvm_arch {/* G-stage vmid */ struct kvm_vmid vmid;@@ -311,77 +286,6 @@ static inline bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu)return IS_ENABLED (CONFIG_GUEST_PERF_EVENTS ) && !!vcpu; } -#define KVM_RISCV_GSTAGE_TLB_MIN_ORDER 12 - -void kvm_riscv_local_hfence_gvma_vmid_gpa (unsigned long vmid, -gpa_t gpa,gpa_t gpsz, -unsigned long order); -void kvm_riscv_local_hfence_gvma_vmid_all (unsigned long vmid); -void kvm_riscv_local_hfence_gvma_gpa (gpa_t gpa,gpa_t gpsz, -unsigned long order); -void kvm_riscv_local_hfence_gvma_all (void ); -void kvm_riscv_local_hfence_vvma_asid_gva (unsigned long vmid, -unsigned long asid, -unsigned long gva, -unsigned long gvsz, -unsigned long order); -void kvm_riscv_local_hfence_vvma_asid_all (unsigned long vmid, -unsigned long asid); -void kvm_riscv_local_hfence_vvma_gva (unsigned long vmid, -unsigned long gva,unsigned long gvsz, -unsigned long order); -void kvm_riscv_local_hfence_vvma_all (unsigned long vmid); - -void kvm_riscv_tlb_flush_process (struct kvm_vcpu *vcpu); - -void kvm_riscv_fence_i_process (struct kvm_vcpu *vcpu); -void kvm_riscv_hfence_vvma_all_process (struct kvm_vcpu *vcpu); -void kvm_riscv_hfence_process (struct kvm_vcpu *vcpu); - -void kvm_riscv_fence_i (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); -void kvm_riscv_hfence_gvma_vmid_gpa (struct kvm *kvm, -unsigned long hbase,unsigned long hmask, -gpa_t gpa,gpa_t gpsz, -unsigned long order); -void kvm_riscv_hfence_gvma_vmid_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); -void kvm_riscv_hfence_vvma_asid_gva (struct kvm *kvm, -unsigned long hbase,unsigned long hmask, -unsigned long gva,unsigned long gvsz, -unsigned long order,unsigned long asid); -void kvm_riscv_hfence_vvma_asid_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask, -unsigned long asid); -void kvm_riscv_hfence_vvma_gva (struct kvm *kvm, -unsigned long hbase,unsigned long hmask, -unsigned long gva,unsigned long gvsz, -unsigned long order); -void kvm_riscv_hfence_vvma_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); - -int kvm_riscv_gstage_ioremap (struct kvm *kvm,gpa_t gpa, -phys_addr_t hpa,unsigned long size, -bool writable,bool in_atomic); -void kvm_riscv_gstage_iounmap (struct kvm *kvm,gpa_t gpa, -unsigned long size); -int kvm_riscv_gstage_map (struct kvm_vcpu *vcpu, -struct kvm_memory_slot *memslot, -gpa_t gpa,unsigned long hva,bool is_write); -int kvm_riscv_gstage_alloc_pgd (struct kvm *kvm); -void kvm_riscv_gstage_free_pgd (struct kvm *kvm); -void kvm_riscv_gstage_update_hgatp (struct kvm_vcpu *vcpu); -void __init kvm_riscv_gstage_mode_detect (void ); -unsigned long __init kvm_riscv_gstage_mode (void ); -int kvm_riscv_gstage_gpa_bits (void ); - -void __init kvm_riscv_gstage_vmid_detect (void ); -unsigned long kvm_riscv_gstage_vmid_bits (void ); -int kvm_riscv_gstage_vmid_init (struct kvm *kvm); -bool kvm_riscv_gstage_vmid_ver_changed (struct kvm_vmid *vmid); -void kvm_riscv_gstage_vmid_update (struct kvm_vcpu *vcpu); -void kvm_riscv_gstage_vmid_sanitize (struct kvm_vcpu *vcpu); -int kvm_riscv_setup_default_irq_routing (struct kvm *kvm,u32 lines);void __kvm_riscv_unpriv_trap (void );arch/riscv/include/asm/kvm_mmu.h new file +26
-0@@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (c) 2025 Ventana Micro Systems Inc. +*/ + +#ifndef __RISCV_KVM_MMU_H_ +#define __RISCV_KVM_MMU_H_ + +#include <linux/kvm_types.h> + +int kvm_riscv_gstage_ioremap (struct kvm *kvm,gpa_t gpa, +phys_addr_t hpa,unsigned long size, +bool writable,bool in_atomic); +void kvm_riscv_gstage_iounmap (struct kvm *kvm,gpa_t gpa, +unsigned long size); +int kvm_riscv_gstage_map (struct kvm_vcpu *vcpu, +struct kvm_memory_slot *memslot, +gpa_t gpa,unsigned long hva,bool is_write); +int kvm_riscv_gstage_alloc_pgd (struct kvm *kvm); +void kvm_riscv_gstage_free_pgd (struct kvm *kvm); +void kvm_riscv_gstage_update_hgatp (struct kvm_vcpu *vcpu); +void kvm_riscv_gstage_mode_detect (void ); +unsigned long kvm_riscv_gstage_mode (void ); +int kvm_riscv_gstage_gpa_bits (void ); + +#endif arch/riscv/include/asm/kvm_tlb.h new file +78
-0@@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (c) 2025 Ventana Micro Systems Inc. +*/ + +#ifndef __RISCV_KVM_TLB_H_ +#define __RISCV_KVM_TLB_H_ + +#include <linux/kvm_types.h> + +enum kvm_riscv_hfence_type { +KVM_RISCV_HFENCE_UNKNOWN =0 , +KVM_RISCV_HFENCE_GVMA_VMID_GPA , +KVM_RISCV_HFENCE_VVMA_ASID_GVA , +KVM_RISCV_HFENCE_VVMA_ASID_ALL , +KVM_RISCV_HFENCE_VVMA_GVA , +}; + +struct kvm_riscv_hfence { +enum kvm_riscv_hfence_type type; +unsigned long asid; +unsigned long order; +gpa_t addr; +gpa_t size; +}; + +#define KVM_RISCV_VCPU_MAX_HFENCE 64 + +#define KVM_RISCV_GSTAGE_TLB_MIN_ORDER 12 + +void kvm_riscv_local_hfence_gvma_vmid_gpa (unsigned long vmid, +gpa_t gpa,gpa_t gpsz, +unsigned long order); +void kvm_riscv_local_hfence_gvma_vmid_all (unsigned long vmid); +void kvm_riscv_local_hfence_gvma_gpa (gpa_t gpa,gpa_t gpsz, +unsigned long order); +void kvm_riscv_local_hfence_gvma_all (void ); +void kvm_riscv_local_hfence_vvma_asid_gva (unsigned long vmid, +unsigned long asid, +unsigned long gva, +unsigned long gvsz, +unsigned long order); +void kvm_riscv_local_hfence_vvma_asid_all (unsigned long vmid, +unsigned long asid); +void kvm_riscv_local_hfence_vvma_gva (unsigned long vmid, +unsigned long gva,unsigned long gvsz, +unsigned long order); +void kvm_riscv_local_hfence_vvma_all (unsigned long vmid); + +void kvm_riscv_tlb_flush_process (struct kvm_vcpu *vcpu); + +void kvm_riscv_fence_i_process (struct kvm_vcpu *vcpu); +void kvm_riscv_hfence_vvma_all_process (struct kvm_vcpu *vcpu); +void kvm_riscv_hfence_process (struct kvm_vcpu *vcpu); + +void kvm_riscv_fence_i (struct kvm *kvm, +unsigned long hbase,unsigned long hmask); +void kvm_riscv_hfence_gvma_vmid_gpa (struct kvm *kvm, +unsigned long hbase,unsigned long hmask, +gpa_t gpa,gpa_t gpsz, +unsigned long order); +void kvm_riscv_hfence_gvma_vmid_all (struct kvm *kvm, +unsigned long hbase,unsigned long hmask); +void kvm_riscv_hfence_vvma_asid_gva (struct kvm *kvm, +unsigned long hbase,unsigned long hmask, +unsigned long gva,unsigned long gvsz, +unsigned long order,unsigned long asid); +void kvm_riscv_hfence_vvma_asid_all (struct kvm *kvm, +unsigned long hbase,unsigned long hmask, +unsigned long asid); +void kvm_riscv_hfence_vvma_gva (struct kvm *kvm, +unsigned long hbase,unsigned long hmask, +unsigned long gva,unsigned long gvsz, +unsigned long order); +void kvm_riscv_hfence_vvma_all (struct kvm *kvm, +unsigned long hbase,unsigned long hmask); + +#endif arch/riscv/include/asm/kvm_vmid.h new file +27
-0@@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (c) 2025 Ventana Micro Systems Inc. +*/ + +#ifndef __RISCV_KVM_VMID_H_ +#define __RISCV_KVM_VMID_H_ + +#include <linux/kvm_types.h> + +struct kvm_vmid { +/* +* Writes to vmid_version and vmid happen with vmid_lock held +* whereas reads happen without any lock held. +*/ +unsigned long vmid_version; +unsigned long vmid; +}; + +void __init kvm_riscv_gstage_vmid_detect (void ); +unsigned long kvm_riscv_gstage_vmid_bits (void ); +int kvm_riscv_gstage_vmid_init (struct kvm *kvm); +bool kvm_riscv_gstage_vmid_ver_changed (struct kvm_vmid *vmid); +void kvm_riscv_gstage_vmid_update (struct kvm_vcpu *vcpu); +void kvm_riscv_gstage_vmid_sanitize (struct kvm_vcpu *vcpu); + +#endif arch/riscv/kvm/aia_imsic.c +1
-0@@ -16,6 +16,7 @@#include <linux/swab.h> #include <kvm/iodev.h> #include <asm/csr.h> +#include <asm/kvm_mmu.h> #define IMSIC_MAX_EIX (IMSIC_MAX_ID / BITS_PER_TYPE(u64))arch/riscv/kvm/main.c +1
-0@@ -11,6 +11,7 @@#include <linux/module.h> #include <linux/kvm_host.h> #include <asm/cpufeature.h> +#include <asm/kvm_mmu.h> #include <asm/kvm_nacl.h> #include <asm/sbi.h> arch/riscv/kvm/mmu.c +1
-0@@ -15,6 +15,7 @@#include <linux/vmalloc.h> #include <linux/kvm_host.h> #include <linux/sched/signal.h> +#include <asm/kvm_mmu.h> #include <asm/kvm_nacl.h> #include <asm/page.h> #include <asm/pgtable.h> arch/riscv/kvm/tlb.c +2
-0@@ -15,6 +15,8 @@#include <asm/cpufeature.h> #include <asm/insn-def.h> #include <asm/kvm_nacl.h> +#include <asm/kvm_tlb.h> +#include <asm/kvm_vmid.h> #define has_svinval () riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)arch/riscv/kvm/vcpu.c +1
-0@@ -18,6 +18,7 @@#include <linux/fs.h> #include <linux/kvm_host.h> #include <asm/cacheflush.h> +#include <asm/kvm_mmu.h> #include <asm/kvm_nacl.h> #include <asm/kvm_vcpu_vector.h> arch/riscv/kvm/vcpu_exit.c +1
-0@@ -9,6 +9,7 @@#include <linux/kvm_host.h> #include <asm/csr.h> #include <asm/insn-def.h> +#include <asm/kvm_mmu.h> #include <asm/kvm_nacl.h> static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,arch/riscv/kvm/vm.c +1
-0@@ -11,6 +11,7 @@#include <linux/module.h> #include <linux/uaccess.h> #include <linux/kvm_host.h> +#include <asm/kvm_mmu.h> const struct _kvm_stats_desc kvm_vm_stats_desc[] = {KVM_GENERIC_VM_STATS ()arch/riscv/kvm/vmid.c +0
-0
arch/riscv/kvm/vmid.c line 21
Quoted 8 lines
arch/riscv/kvm/vmid.c +2
-0@@ -14,6 +14,8 @@#include <linux/smp.h> #include <linux/kvm_host.h> #include <asm/csr.h> +#include <asm/kvm_tlb.h> +#include <asm/kvm_vmid.h> static unsigned long vmid_version =1 ;static unsigned long vmid_next;
LGTM.
PATCH v2 9/12 RISC-V: KVM: Introduce struct kvm_gstage_mapping
In reply to Anup PatelIntroduce struct kvm_gstage_mapping which represents a g-stage mapping at a particular g-stage page table level. Also, update the kvm_riscv_gstage_map() to return the g-stage mapping upon success.
--- arch/riscv/include/asm/kvm_mmu.h | 9 ++++- arch/riscv/kvm/mmu.c | 58 ++++++++++++++++++-------------- arch/riscv/kvm/vcpu_exit.c | 3 +- 3 files changed, 43 insertions(+), 27 deletions(-)
arch/riscv/include/asm/kvm_mmu.h +8 -1
@@ -8,6 +8,12 @@#include <linux/kvm_types.h> +struct kvm_gstage_mapping { +gpa_t addr; +pte_t pte; +u32 level; +}; +int kvm_riscv_gstage_ioremap (struct kvm *kvm,gpa_t gpa,phys_addr_t hpa,unsigned long size,bool writable,bool in_atomic);
@@ -15,7 +21,8 @@ void kvm_riscv_gstage_iounmap(struct kvm *kvm, gpa_t gpa, unsigned long size);int kvm_riscv_gstage_map (struct kvm_vcpu *vcpu,struct kvm_memory_slot *memslot, -gpa_t gpa,unsigned long hva,bool is_write); +gpa_t gpa,unsigned long hva,bool is_write, +struct kvm_gstage_mapping *out_map);int kvm_riscv_gstage_alloc_pgd (struct kvm *kvm);void kvm_riscv_gstage_free_pgd (struct kvm *kvm);void kvm_riscv_gstage_update_hgatp (struct kvm_vcpu *vcpu);
arch/riscv/kvm/mmu.c +33 -25
140 lines not on this page · raw message
arch/riscv/kvm/vcpu_exit.c +2 -1
@@ -15,6 +15,7 @@static int gstage_page_fault (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_cpu_trap *trap) { +struct kvm_gstage_mapping host_map;struct kvm_memory_slot *memslot;unsigned long hva, fault_addr;bool writable;
@@ -43,7 +44,7 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run, } ret =kvm_riscv_gstage_map (vcpu, memslot, fault_addr, hva, - (trap->scause ==EXC_STORE_GUEST_PAGE_FAULT ) ? true : false); + (trap->scause ==EXC_STORE_GUEST_PAGE_FAULT ) ? true : false, &host_map);if (ret <0 )return ret;
Signature · 1 line
2.43.0
Re: [PATCH v2 09/12] RISC-V: KVM: Introduce struct kvm_gstage_mapping
Quoted 205 lines · Anup Patel
Introduce struct
kvm_gstage_mappingwhich represents a g-stage mapping at a particular g-stage page table level. Also, update thekvm_riscv_gstage_map()to return the g-stage mapping upon success.Signed-off-by Anup Patel <[email protected]>--- arch/riscv/include/asm/kvm_mmu.h | 9 ++++- arch/riscv/kvm/mmu.c | 58 ++++++++++++++++++-------------- arch/riscv/kvm/vcpu_exit.c | 3 +- 3 files changed, 43 insertions(+), 27 deletions(-)arch/riscv/include/asm/kvm_mmu.h +8
-1@@ -8,6 +8,12 @@#include <linux/kvm_types.h> +struct kvm_gstage_mapping { +gpa_t addr; +pte_t pte; +u32 level; +}; +int kvm_riscv_gstage_ioremap (struct kvm *kvm,gpa_t gpa,phys_addr_t hpa,unsigned long size,bool writable,bool in_atomic);@@ -15,7 +21,8 @@ void kvm_riscv_gstage_iounmap(struct kvm *kvm, gpa_t gpa, unsigned long size);int kvm_riscv_gstage_map (struct kvm_vcpu *vcpu,struct kvm_memory_slot *memslot, -gpa_t gpa,unsigned long hva,bool is_write); +gpa_t gpa,unsigned long hva,bool is_write, +struct kvm_gstage_mapping *out_map);int kvm_riscv_gstage_alloc_pgd (struct kvm *kvm);void kvm_riscv_gstage_free_pgd (struct kvm *kvm);void kvm_riscv_gstage_update_hgatp (struct kvm_vcpu *vcpu);arch/riscv/kvm/mmu.c +33
-25@@ -135,18 +135,18 @@ static void gstage_remote_tlb_flush(struct kvm *kvm, u32 level, gpa_t addr)kvm_riscv_hfence_gvma_vmid_gpa (kvm,-1UL ,0 , addr,BIT (order), order); } -static int gstage_set_pte (struct kvm *kvm,u32 level, -struct kvm_mmu_memory_cache *pcache, -gpa_t addr,const pte_t *new_pte) +static int gstage_set_pte (struct kvm *kvm, +struct kvm_mmu_memory_cache *pcache, +const struct kvm_gstage_mapping *map) {u32 current_level = gstage_pgd_levels -1 ;pte_t *next_ptep = (pte_t *)kvm->arch.pgd; -pte_t *ptep = &next_ptep[gstage_pte_index (addr, current_level)]; +pte_t *ptep = &next_ptep[gstage_pte_index (map->addr, current_level)]; -if (current_level < level) +if (current_level < map->level)return -EINVAL ; -while (current_level != level) { +while (current_level != map->level) {if (gstage_pte_leaf (ptep))return -EEXIST ;@@ -165,13 +165,13 @@ static int gstage_set_pte(struct kvm *kvm, u32 level, } current_level--; - ptep = &next_ptep[gstage_pte_index (addr, current_level)]; + ptep = &next_ptep[gstage_pte_index (map->addr, current_level)]; } -if (pte_val (*ptep) !=pte_val (*new_pte)) { -set_pte (ptep, *new_pte); +if (pte_val (*ptep) !=pte_val (map->pte)) { +set_pte (ptep, map->pte);if (gstage_pte_leaf (ptep)) -gstage_remote_tlb_flush (kvm, current_level, addr); +gstage_remote_tlb_flush (kvm, current_level, map->addr); }return 0 ;@@ -181,14 +181,16 @@ static int gstage_map_page(struct kvm *kvm,struct kvm_mmu_memory_cache *pcache, gpa_t gpa, phys_addr_t hpa, unsigned long page_size, - bool page_rdonly, bool page_exec) + bool page_rdonly, bool page_exec, + struct kvm_gstage_mapping *out_map) { - int ret; -u32 level =0 ; -pte_t new_pte; pgprot_t prot; +int ret; - ret =gstage_page_size_to_level (page_size, &level); + out_map->addr = gpa; + out_map->level =0 ; + + ret =gstage_page_size_to_level (page_size, &out_map->level);if (ret)return ret;@@ -216,10 +218,10 @@ static int gstage_map_page(struct kvm *kvm, else prot =PAGE_WRITE ; } - new_pte =pfn_pte (PFN_DOWN (hpa), prot); - new_pte =pte_mkdirty (new_pte); + out_map->pte =pfn_pte (PFN_DOWN (hpa), prot); + out_map->pte =pte_mkdirty (out_map->pte); -return gstage_set_pte (kvm, level, pcache, gpa, &new_pte); +return gstage_set_pte (kvm, pcache, out_map); }enum gstage_op {@@ -352,7 +354,6 @@ int kvm_riscv_gstage_ioremap(struct kvm *kvm, gpa_t gpa, phys_addr_t hpa, unsigned long size, bool writable, bool in_atomic) { - pte_t pte; int ret = 0;unsigned long pfn;phys_addr_t addr, end;@@ -360,22 +361,25 @@ int kvm_riscv_gstage_ioremap(struct kvm *kvm, gpa_t gpa, .gfp_custom = (in_atomic) ? GFP_ATOMIC | __GFP_ACCOUNT : 0, .gfp_zero = __GFP_ZERO, }; +struct kvm_gstage_mapping map; end = (gpa + size +PAGE_SIZE -1 ) &PAGE_MASK ; pfn =__phys_to_pfn (hpa);for (addr = gpa; addr < end; addr +=PAGE_SIZE ) { - pte =pfn_pte (pfn,PAGE_KERNEL_IO ); + map.addr = addr; + map.pte =pfn_pte (pfn,PAGE_KERNEL_IO ); + map.level =0 ;if (!writable) - pte =pte_wrprotect (pte); + map.pte =pte_wrprotect (map.pte); ret =kvm_mmu_topup_memory_cache (&pcache, gstage_pgd_levels);if (ret) goto out;spin_lock (&kvm->mmu_lock); - ret =gstage_set_pte (kvm,0 , &pcache, addr, &pte); + ret =gstage_set_pte (kvm, &pcache, &map);spin_unlock (&kvm->mmu_lock);if (ret) goto out;@@ -593,7 +597,8 @@ bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)int kvm_riscv_gstage_map (struct kvm_vcpu *vcpu,struct kvm_memory_slot *memslot, -gpa_t gpa,unsigned long hva,bool is_write) +gpa_t gpa,unsigned long hva,bool is_write, +struct kvm_gstage_mapping *out_map) {int ret;kvm_pfn_t hfn;@@ -608,6 +613,9 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu,unsigned long vma_pagesize, mmu_seq;struct page *page; +/* Setup initial state of output mapping */ +memset (out_map,0 ,sizeof (*out_map)); +/* We need minimum second+third level pages */ ret =kvm_mmu_topup_memory_cache (pcache, gstage_pgd_levels);if (ret) {@@ -677,10 +685,10 @@ int kvm_riscv_gstage_map(struct kvm_vcpu *vcpu,if (writable) {mark_page_dirty (kvm, gfn); ret =gstage_map_page (kvm, pcache, gpa, hfn <<PAGE_SHIFT , - vma_pagesize, false, true); + vma_pagesize, false, true, out_map); }else { ret =gstage_map_page (kvm, pcache, gpa, hfn <<PAGE_SHIFT , - vma_pagesize, true, true); + vma_pagesize, true, true, out_map); }if (ret)arch/riscv/kvm/vcpu_exit.c +1
-0@@ -15,6 +15,7 @@static int gstage_page_fault (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_cpu_trap *trap) { +struct kvm_gstage_mapping host_map;struct kvm_memory_slot *memslot;unsigned long hva, fault_addr;bool writable;
arch/riscv/kvm/vcpu_exit.c static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run, · line 50
Quoted 8 lines
arch/riscv/kvm/vcpu_exit.c +1
-1@@ -43,7 +44,7 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run, } ret =kvm_riscv_gstage_map (vcpu, memslot, fault_addr, hva, - (trap->scause ==EXC_STORE_GUEST_PAGE_FAULT ) ? true : false); + (trap->scause ==EXC_STORE_GUEST_PAGE_FAULT ) ? true : false, &host_map);if (ret <0 )return ret;
PATCH v2 10/12 RISC-V: KVM: Add vmid field to struct kvm_riscv_hfence
In reply to Anup PatelCurrently, the struct kvm_riscv_hfence does not have vmid field and various hfence processing functions always pick vmid assigned to the guest/VM. This prevents us from doing hfence operation on arbitrary vmid hence add vmid field to struct kvm_riscv_hfence and use it wherever applicable.
--- arch/riscv/include/asm/kvm_tlb.h | 1 + arch/riscv/kvm/tlb.c | 30 ++++++++++++++++-------------- 2 files changed, 17 insertions(+), 14 deletions(-)
arch/riscv/include/asm/kvm_tlb.h +1 -0
@@ -19,6 +19,7 @@ enum kvm_riscv_hfence_type {struct kvm_riscv_hfence {enum kvm_riscv_hfence_type type;unsigned long asid; +unsigned long vmid;unsigned long order;gpa_t addr;gpa_t size;
arch/riscv/kvm/tlb.c +16 -14
@@ -237,49 +237,43 @@ static bool vcpu_hfence_enqueue(struct kvm_vcpu *vcpu,void kvm_riscv_hfence_process (struct kvm_vcpu *vcpu) { -unsigned long vmid;struct kvm_riscv_hfence d = {0 }; -struct kvm_vmid *v = &vcpu->kvm->arch.vmid;while (vcpu_hfence_dequeue (vcpu, &d)) {switch (d.type) {case KVM_RISCV_HFENCE_UNKNOWN :break ;case KVM_RISCV_HFENCE_GVMA_VMID_GPA : - vmid =READ_ONCE (v->vmid);if (kvm_riscv_nacl_available ()) -nacl_hfence_gvma_vmid (nacl_shmem (), vmid, +nacl_hfence_gvma_vmid (nacl_shmem (), d.vmid, d.addr, d.size, d.order);else -kvm_riscv_local_hfence_gvma_vmid_gpa (vmid, d.addr, +kvm_riscv_local_hfence_gvma_vmid_gpa (d.vmid, d.addr, d.size, d.order);break ;case KVM_RISCV_HFENCE_VVMA_ASID_GVA :kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD ); - vmid =READ_ONCE (v->vmid);if (kvm_riscv_nacl_available ()) -nacl_hfence_vvma_asid (nacl_shmem (), vmid, d.asid, +nacl_hfence_vvma_asid (nacl_shmem (), d.vmid, d.asid, d.addr, d.size, d.order);else -kvm_riscv_local_hfence_vvma_asid_gva (vmid, d.asid, d.addr, +kvm_riscv_local_hfence_vvma_asid_gva (d.vmid, d.asid, d.addr, d.size, d.order);break ;case KVM_RISCV_HFENCE_VVMA_ASID_ALL :kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD ); - vmid =READ_ONCE (v->vmid);if (kvm_riscv_nacl_available ()) -nacl_hfence_vvma_asid_all (nacl_shmem (), vmid, d.asid); +nacl_hfence_vvma_asid_all (nacl_shmem (), d.vmid, d.asid);else -kvm_riscv_local_hfence_vvma_asid_all (vmid, d.asid); +kvm_riscv_local_hfence_vvma_asid_all (d.vmid, d.asid);break ;case KVM_RISCV_HFENCE_VVMA_GVA :kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_RCVD ); - vmid =READ_ONCE (v->vmid);if (kvm_riscv_nacl_available ()) -nacl_hfence_vvma (nacl_shmem (), vmid, +nacl_hfence_vvma (nacl_shmem (), d.vmid, d.addr, d.size, d.order);else -kvm_riscv_local_hfence_vvma_gva (vmid, d.addr, +kvm_riscv_local_hfence_vvma_gva (d.vmid, d.addr, d.size, d.order);break ;default :
@@ -336,10 +330,12 @@ void kvm_riscv_hfence_gvma_vmid_gpa(struct kvm *kvm, gpa_t gpa, gpa_t gpsz, unsigned long order) { + struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_GVMA_VMID_GPA ; data.asid =0 ; + data.vmid =READ_ONCE (v->vmid); data.addr = gpa; data.size = gpsz; data.order = order;
@@ -359,10 +355,12 @@ void kvm_riscv_hfence_vvma_asid_gva(struct kvm *kvm, unsigned long gva, unsigned long gvsz, unsigned long order, unsigned long asid) { + struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_ASID_GVA ; data.asid = asid; + data.vmid =READ_ONCE (v->vmid); data.addr = gva; data.size = gvsz; data.order = order;
@@ -374,10 +372,12 @@ void kvm_riscv_hfence_vvma_asid_all(struct kvm *kvm, unsigned long hbase, unsigned long hmask, unsigned long asid) { + struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_ASID_ALL ; data.asid = asid; + data.vmid =READ_ONCE (v->vmid); data.addr = data.size = data.order =0 ;make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE ,KVM_REQ_HFENCE_VVMA_ALL , &data);
@@ -388,10 +388,12 @@ void kvm_riscv_hfence_vvma_gva(struct kvm *kvm, unsigned long gva, unsigned long gvsz, unsigned long order) { + struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_GVA ; data.asid =0 ; + data.vmid =READ_ONCE (v->vmid); data.addr = gva; data.size = gvsz; data.order = order;
Signature · 1 line
2.43.0
Re: [PATCH v2 10/12] RISC-V: KVM: Add vmid field to struct kvm_riscv_hfence
Quoted 128 lines · Anup Patel
Currently, the struct
kvm_riscv_hfencedoes not have vmid field and various hfence processing functions always pick vmid assigned to the guest/VM. This prevents us from doing hfence operation on arbitrary vmid hence add vmid field to structkvm_riscv_hfenceand use it wherever applicable.Signed-off-by Anup Patel <[email protected]>--- arch/riscv/include/asm/kvm_tlb.h | 1 + arch/riscv/kvm/tlb.c | 30 ++++++++++++++++-------------- 2 files changed, 17 insertions(+), 14 deletions(-)arch/riscv/include/asm/kvm_tlb.h +1
-0@@ -19,6 +19,7 @@ enum kvm_riscv_hfence_type {struct kvm_riscv_hfence {enum kvm_riscv_hfence_type type;unsigned long asid; +unsigned long vmid;unsigned long order;gpa_t addr;gpa_t size;arch/riscv/kvm/tlb.c +14
-14@@ -237,49 +237,43 @@ static bool vcpu_hfence_enqueue(struct kvm_vcpu *vcpu,void kvm_riscv_hfence_process (struct kvm_vcpu *vcpu) { -unsigned long vmid;struct kvm_riscv_hfence d = {0 }; -struct kvm_vmid *v = &vcpu->kvm->arch.vmid;while (vcpu_hfence_dequeue (vcpu, &d)) {switch (d.type) {case KVM_RISCV_HFENCE_UNKNOWN :break ;case KVM_RISCV_HFENCE_GVMA_VMID_GPA : - vmid =READ_ONCE (v->vmid);if (kvm_riscv_nacl_available ()) -nacl_hfence_gvma_vmid (nacl_shmem (), vmid, +nacl_hfence_gvma_vmid (nacl_shmem (), d.vmid, d.addr, d.size, d.order);else -kvm_riscv_local_hfence_gvma_vmid_gpa (vmid, d.addr, +kvm_riscv_local_hfence_gvma_vmid_gpa (d.vmid, d.addr, d.size, d.order);break ;case KVM_RISCV_HFENCE_VVMA_ASID_GVA :kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD ); - vmid =READ_ONCE (v->vmid);if (kvm_riscv_nacl_available ()) -nacl_hfence_vvma_asid (nacl_shmem (), vmid, d.asid, +nacl_hfence_vvma_asid (nacl_shmem (), d.vmid, d.asid, d.addr, d.size, d.order);else -kvm_riscv_local_hfence_vvma_asid_gva (vmid, d.asid, d.addr, +kvm_riscv_local_hfence_vvma_asid_gva (d.vmid, d.asid, d.addr, d.size, d.order);break ;case KVM_RISCV_HFENCE_VVMA_ASID_ALL :kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD ); - vmid =READ_ONCE (v->vmid);if (kvm_riscv_nacl_available ()) -nacl_hfence_vvma_asid_all (nacl_shmem (), vmid, d.asid); +nacl_hfence_vvma_asid_all (nacl_shmem (), d.vmid, d.asid);else -kvm_riscv_local_hfence_vvma_asid_all (vmid, d.asid); +kvm_riscv_local_hfence_vvma_asid_all (d.vmid, d.asid);break ;case KVM_RISCV_HFENCE_VVMA_GVA :kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_RCVD ); - vmid =READ_ONCE (v->vmid);if (kvm_riscv_nacl_available ()) -nacl_hfence_vvma (nacl_shmem (), vmid, +nacl_hfence_vvma (nacl_shmem (), d.vmid, d.addr, d.size, d.order);else -kvm_riscv_local_hfence_vvma_gva (vmid, d.addr, +kvm_riscv_local_hfence_vvma_gva (d.vmid, d.addr, d.size, d.order);break ;default :@@ -336,10 +330,12 @@ void kvm_riscv_hfence_gvma_vmid_gpa(struct kvm *kvm, gpa_t gpa, gpa_t gpsz, unsigned long order) { + struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_GVMA_VMID_GPA ; data.asid =0 ; + data.vmid =READ_ONCE (v->vmid); data.addr = gpa; data.size = gpsz; data.order = order;@@ -359,10 +355,12 @@ void kvm_riscv_hfence_vvma_asid_gva(struct kvm *kvm, unsigned long gva, unsigned long gvsz, unsigned long order, unsigned long asid) { + struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_ASID_GVA ; data.asid = asid; + data.vmid =READ_ONCE (v->vmid); data.addr = gva; data.size = gvsz; data.order = order;@@ -374,10 +372,12 @@ void kvm_riscv_hfence_vvma_asid_all(struct kvm *kvm, unsigned long hbase, unsigned long hmask, unsigned long asid) { + struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_ASID_ALL ; data.asid = asid; + data.vmid =READ_ONCE (v->vmid); data.addr = data.size = data.order =0 ;make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE ,KVM_REQ_HFENCE_VVMA_ALL , &data);@@ -388,10 +388,12 @@ void kvm_riscv_hfence_vvma_gva(struct kvm *kvm, unsigned long gva, unsigned long gvsz, unsigned long order)
arch/riscv/kvm/tlb.c void kvm_riscv_hfence_vvma_gva(struct kvm *kvm, · line 399
Quoted 10 lines
arch/riscv/kvm/tlb.c +2
-0{ +struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_GVA ; data.asid =0 ; + data.vmid =READ_ONCE (v->vmid); data.addr = gva; data.size = gvsz; data.order = order;
PATCH v2 11/12 RISC-V: KVM: Factor-out g-stage page table management
In reply to Anup PatelThe upcoming nested virtualization can share g-stage page table management with the current host g-stage implementation hence factor-out g-stage page table management as separate sources and also use "kvm_riscv_mmu_" prefix for host g-stage functions.
--- arch/riscv/include/asm/kvm_gstage.h | 72 ++++ arch/riscv/include/asm/kvm_mmu.h | 32 +- arch/riscv/kvm/Makefile | 1 + arch/riscv/kvm/aia_imsic.c | 11 +- arch/riscv/kvm/gstage.c | 337 +++++++++++++++++++ arch/riscv/kvm/main.c | 2 +- arch/riscv/kvm/mmu.c | 492 ++++++---------------------- arch/riscv/kvm/vcpu.c | 4 +- arch/riscv/kvm/vcpu_exit.c | 5 +- arch/riscv/kvm/vm.c | 6 +- 10 files changed, 530 insertions(+), 432 deletions(-) create mode 100644 arch/riscv/include/asm/kvm_gstage.h create mode 100644 arch/riscv/kvm/gstage.c
arch/riscv/include/asm/kvm_gstage.h new file +72 -0
@@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (C) 2019 Western Digital Corporation or its affiliates. +* Copyright (c) 2025 Ventana Micro Systems Inc. +*/ + +#ifndef __RISCV_KVM_GSTAGE_H_ +#define __RISCV_KVM_GSTAGE_H_ + +#include <linux/kvm_types.h> + +struct kvm_gstage { +struct kvm *kvm; +unsigned long flags; +#define KVM_GSTAGE_FLAGS_LOCAL BIT(0) +unsigned long vmid; +pgd_t *pgd; +}; + +struct kvm_gstage_mapping { +gpa_t addr; +pte_t pte; +u32 level; +}; + +#ifdef CONFIG_64BIT +#define kvm_riscv_gstage_index_bits 9 +#else +#define kvm_riscv_gstage_index_bits 10 +#endif + +extern unsigned long kvm_riscv_gstage_mode; +extern unsigned long kvm_riscv_gstage_pgd_levels; + +#define kvm_riscv_gstage_pgd_xbits 2 +#define kvm_riscv_gstage_pgd_size (1UL << (HGATP_PAGE_SHIFT + kvm_riscv_gstage_pgd_xbits)) +#define kvm_riscv_gstage_gpa_bits (HGATP_PAGE_SHIFT + \ + (kvm_riscv_gstage_pgd_levels * \ + kvm_riscv_gstage_index_bits) + \ + kvm_riscv_gstage_pgd_xbits) +#define kvm_riscv_gstage_gpa_size ((gpa_t)(1ULL << kvm_riscv_gstage_gpa_bits)) + +bool kvm_riscv_gstage_get_leaf (struct kvm_gstage *gstage,gpa_t addr, +pte_t **ptepp,u32 *ptep_level); + +int kvm_riscv_gstage_set_pte (struct kvm_gstage *gstage, +struct kvm_mmu_memory_cache *pcache, +const struct kvm_gstage_mapping *map); + +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, +bool page_rdonly,bool page_exec, +struct kvm_gstage_mapping *out_map); + +enum kvm_riscv_gstage_op { +GSTAGE_OP_NOP =0 ,/* Nothing */ +GSTAGE_OP_CLEAR ,/* Clear/Unmap */ +GSTAGE_OP_WP ,/* Write-protect */ +}; + +void kvm_riscv_gstage_op_pte (struct kvm_gstage *gstage,gpa_t addr, +pte_t *ptep,u32 ptep_level,enum kvm_riscv_gstage_op op); + +void kvm_riscv_gstage_unmap_range (struct kvm_gstage *gstage, +gpa_t start,gpa_t size,bool may_block); + +void kvm_riscv_gstage_wp_range (struct kvm_gstage *gstage,gpa_t start,gpa_t end); + +void kvm_riscv_gstage_mode_detect (void ); + +#endif
arch/riscv/include/asm/kvm_mmu.h +10 -22
@@ -6,28 +6,16 @@#ifndef __RISCV_KVM_MMU_H_#define __RISCV_KVM_MMU_H_ -#include <linux/kvm_types.h> +#include <asm/kvm_gstage.h> -struct kvm_gstage_mapping { -gpa_t addr; -pte_t pte; -u32 level; -}; - -int kvm_riscv_gstage_ioremap (struct kvm *kvm,gpa_t gpa, -phys_addr_t hpa,unsigned long size, -bool writable,bool in_atomic); -void kvm_riscv_gstage_iounmap (struct kvm *kvm,gpa_t gpa, -unsigned long size); -int kvm_riscv_gstage_map (struct kvm_vcpu *vcpu, -struct kvm_memory_slot *memslot, -gpa_t gpa,unsigned long hva,bool is_write, -struct kvm_gstage_mapping *out_map); -int kvm_riscv_gstage_alloc_pgd (struct kvm *kvm); -void kvm_riscv_gstage_free_pgd (struct kvm *kvm); -void kvm_riscv_gstage_update_hgatp (struct kvm_vcpu *vcpu); -void kvm_riscv_gstage_mode_detect (void ); -unsigned long kvm_riscv_gstage_mode (void ); -int kvm_riscv_gstage_gpa_bits (void ); +int kvm_riscv_mmu_ioremap (struct kvm *kvm,gpa_t gpa,phys_addr_t hpa, +unsigned long size,bool writable,bool in_atomic); +void kvm_riscv_mmu_iounmap (struct kvm *kvm,gpa_t gpa,unsigned long size); +int kvm_riscv_mmu_map (struct kvm_vcpu *vcpu,struct kvm_memory_slot *memslot, +gpa_t gpa,unsigned long hva,bool is_write, +struct kvm_gstage_mapping *out_map); +int kvm_riscv_mmu_alloc_pgd (struct kvm *kvm); +void kvm_riscv_mmu_free_pgd (struct kvm *kvm); +void kvm_riscv_mmu_update_hgatp (struct kvm_vcpu *vcpu);#endif
arch/riscv/kvm/Makefile +1 -0
@@ -14,6 +14,7 @@ kvm-y += aia.o kvm-y += aia_aplic.o kvm-y += aia_device.o kvm-y += aia_imsic.o +kvm-y += gstage.o kvm-y += main.o kvm-y += mmu.o kvm-y += nacl.o
arch/riscv/kvm/aia_imsic.c +5 -6
@@ -704,9 +704,8 @@ void kvm_riscv_vcpu_aia_imsic_release(struct kvm_vcpu *vcpu)*/ /* Purge the G-stage mapping */ -kvm_riscv_gstage_iounmap (vcpu->kvm, - vcpu->arch.aia_context.imsic_addr, -IMSIC_MMIO_PAGE_SZ ); +kvm_riscv_mmu_iounmap (vcpu->kvm, vcpu->arch.aia_context.imsic_addr, +IMSIC_MMIO_PAGE_SZ );/* TODO: Purge the IOMMU mapping ??? */
@@ -786,9 +785,9 @@ int kvm_riscv_vcpu_aia_imsic_update(struct kvm_vcpu *vcpu)imsic_vsfile_local_clear (new_vsfile_hgei, imsic->nr_hw_eix);/* Update G-stage mapping for the new IMSIC VS-file */ - ret =kvm_riscv_gstage_ioremap (kvm, vcpu->arch.aia_context.imsic_addr, - new_vsfile_pa,IMSIC_MMIO_PAGE_SZ , - true, true); + ret =kvm_riscv_mmu_ioremap (kvm, vcpu->arch.aia_context.imsic_addr, + new_vsfile_pa,IMSIC_MMIO_PAGE_SZ , + true, true);if (ret) goto fail_free_vsfile_hgei;
arch/riscv/kvm/gstage.c new file +337 -0
337 lines not on this page · raw message
arch/riscv/kvm/main.c +1 -1
@@ -135,7 +135,7 @@ static int __init riscv_kvm_init(void) (rc) ? slist : "no features"); } -switch (kvm_riscv_gstage_mode ()) { +switch (kvm_riscv_gstage_mode) {case HGATP_MODE_SV32X4 : str ="Sv32x4" ;break ;
arch/riscv/kvm/mmu.c +96 -396
678 lines not on this page · raw message
arch/riscv/kvm/vcpu.c +2 -2
@@ -632,7 +632,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) } } -kvm_riscv_gstage_update_hgatp (vcpu); +kvm_riscv_mmu_update_hgatp (vcpu);kvm_riscv_vcpu_timer_restore (vcpu);
@@ -717,7 +717,7 @@ static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu)kvm_riscv_reset_vcpu (vcpu, true);if (kvm_check_request (KVM_REQ_UPDATE_HGATP , vcpu)) -kvm_riscv_gstage_update_hgatp (vcpu); +kvm_riscv_mmu_update_hgatp (vcpu);if (kvm_check_request (KVM_REQ_FENCE_I , vcpu))kvm_riscv_fence_i_process (vcpu);
arch/riscv/kvm/vcpu_exit.c +3 -2
@@ -43,8 +43,9 @@ static int gstage_page_fault(struct kvm_vcpu *vcpu, struct kvm_run *run, }; } - ret =kvm_riscv_gstage_map (vcpu, memslot, fault_addr, hva, - (trap->scause ==EXC_STORE_GUEST_PAGE_FAULT ) ? true : false, &host_map); + ret =kvm_riscv_mmu_map (vcpu, memslot, fault_addr, hva, + (trap->scause ==EXC_STORE_GUEST_PAGE_FAULT ) ? true : false, + &host_map);if (ret <0 )return ret;
arch/riscv/kvm/vm.c +3 -3
@@ -32,13 +32,13 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) {int r; - r =kvm_riscv_gstage_alloc_pgd (kvm); + r =kvm_riscv_mmu_alloc_pgd (kvm);if (r)return r; r =kvm_riscv_gstage_vmid_init (kvm);if (r) { -kvm_riscv_gstage_free_pgd (kvm); +kvm_riscv_mmu_free_pgd (kvm);return r; }
@@ -200,7 +200,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r =KVM_USER_MEM_SLOTS ;break ;case KVM_CAP_VM_GPA_BITS : - r =kvm_riscv_gstage_gpa_bits (); + r = kvm_riscv_gstage_gpa_bits;break ;default : r =0 ;
Signature · 1 line
2.43.0
PATCH v2 12/12 RISC-V: KVM: Pass VMID as parameter to kvm_riscv_hfence_xyz() APIs
In reply to Anup PatelCurrently, all kvm_riscv_hfence_xyz() APIs assume VMID to be the host VMID of the Guest/VM which resticts use of these APIs only for host TLB maintenance. Let's allow passing VMID as a parameter to all kvm_riscv_hfence_xyz() APIs so that they can be re-used for nested virtualization related TLB maintenance.
--- arch/riscv/include/asm/kvm_tlb.h | 17 ++++++--- arch/riscv/kvm/gstage.c | 3 +- arch/riscv/kvm/tlb.c | 61 ++++++++++++++++++++----------- arch/riscv/kvm/vcpu_sbi_replace.c | 17 +++++---- arch/riscv/kvm/vcpu_sbi_v01.c | 25 ++++++------- 5 files changed, 73 insertions(+), 50 deletions(-)
arch/riscv/include/asm/kvm_tlb.h +11 -6
@@ -11,9 +11,11 @@enum kvm_riscv_hfence_type {KVM_RISCV_HFENCE_UNKNOWN =0 ,KVM_RISCV_HFENCE_GVMA_VMID_GPA , +KVM_RISCV_HFENCE_GVMA_VMID_ALL ,KVM_RISCV_HFENCE_VVMA_ASID_GVA ,KVM_RISCV_HFENCE_VVMA_ASID_ALL ,KVM_RISCV_HFENCE_VVMA_GVA , +KVM_RISCV_HFENCE_VVMA_ALL };struct kvm_riscv_hfence {
@@ -59,21 +61,24 @@ void kvm_riscv_fence_i(struct kvm *kvm,void kvm_riscv_hfence_gvma_vmid_gpa (struct kvm *kvm,unsigned long hbase,unsigned long hmask,gpa_t gpa,gpa_t gpsz, -unsigned long order); +unsigned long order,unsigned long vmid);void kvm_riscv_hfence_gvma_vmid_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); +unsigned long hbase,unsigned long hmask, +unsigned long vmid);void kvm_riscv_hfence_vvma_asid_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order,unsigned long asid); +unsigned long order,unsigned long asid, +unsigned long vmid);void kvm_riscv_hfence_vvma_asid_all (struct kvm *kvm,unsigned long hbase,unsigned long hmask, -unsigned long asid); +unsigned long asid,unsigned long vmid);void kvm_riscv_hfence_vvma_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order); +unsigned long order,unsigned long vmid);void kvm_riscv_hfence_vvma_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); +unsigned long hbase,unsigned long hmask, +unsigned long vmid);#endif
arch/riscv/kvm/gstage.c +2 -1
@@ -117,7 +117,8 @@ static void gstage_tlb_flush(struct kvm_gstage *gstage, u32 level, gpa_t addr)if (gstage->flags &KVM_GSTAGE_FLAGS_LOCAL )kvm_riscv_local_hfence_gvma_vmid_gpa (gstage->vmid, addr,BIT (order), order);else -kvm_riscv_hfence_gvma_vmid_gpa (gstage->kvm,-1UL ,0 , addr,BIT (order), order); +kvm_riscv_hfence_gvma_vmid_gpa (gstage->kvm,-1UL ,0 , addr,BIT (order), order, + gstage->vmid); } int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,
arch/riscv/kvm/tlb.c +40 -21
134 lines not on this page · raw message
arch/riscv/kvm/vcpu_sbi_replace.c +9 -8
@@ -96,6 +96,7 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *rununsigned long hmask = cp->a0;unsigned long hbase = cp->a1;unsigned long funcid = cp->a6; +unsigned long vmid;switch (funcid) {case SBI_EXT_RFENCE_REMOTE_FENCE_I :
@@ -103,22 +104,22 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *runkvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_FENCE_I_SENT );break ;case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA : + vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid);if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL ) -kvm_riscv_hfence_vvma_all (vcpu->kvm, hbase, hmask); +kvm_riscv_hfence_vvma_all (vcpu->kvm, hbase, hmask, vmid);else kvm_riscv_hfence_vvma_gva (vcpu->kvm, hbase, hmask, - cp->a2, cp->a3,PAGE_SHIFT ); + cp->a2, cp->a3,PAGE_SHIFT , vmid);kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_SENT );break ;case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID : + vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid);if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL ) -kvm_riscv_hfence_vvma_asid_all (vcpu->kvm, - hbase, hmask, cp->a4); +kvm_riscv_hfence_vvma_asid_all (vcpu->kvm, hbase, hmask, + cp->a4, vmid);else -kvm_riscv_hfence_vvma_asid_gva (vcpu->kvm, - hbase, hmask, - cp->a2, cp->a3, -PAGE_SHIFT , cp->a4); +kvm_riscv_hfence_vvma_asid_gva (vcpu->kvm, hbase, hmask, cp->a2, + cp->a3,PAGE_SHIFT , cp->a4, vmid);kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_ASID_SENT );break ;case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA :
arch/riscv/kvm/vcpu_sbi_v01.c +11 -14
@@ -23,6 +23,7 @@ static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,struct kvm *kvm = vcpu->kvm;struct kvm_cpu_context *cp = &vcpu->arch.guest_context;struct kvm_cpu_trap *utrap = retdata->utrap; +unsigned long vmid;switch (cp->a7) {case SBI_EXT_0_1_CONSOLE_GETCHAR :
@@ -78,25 +79,21 @@ static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,if (cp->a7 ==SBI_EXT_0_1_REMOTE_FENCE_I )kvm_riscv_fence_i (vcpu->kvm,0 , hmask);else if (cp->a7 ==SBI_EXT_0_1_REMOTE_SFENCE_VMA ) { + vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid);if (cp->a1 ==0 && cp->a2 ==0 ) -kvm_riscv_hfence_vvma_all (vcpu->kvm, -0 , hmask); +kvm_riscv_hfence_vvma_all (vcpu->kvm,0 , hmask, vmid);else -kvm_riscv_hfence_vvma_gva (vcpu->kvm, -0 , hmask, - cp->a1, cp->a2, -PAGE_SHIFT ); +kvm_riscv_hfence_vvma_gva (vcpu->kvm,0 , hmask, cp->a1, + cp->a2,PAGE_SHIFT , vmid); }else { + vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid);if (cp->a1 ==0 && cp->a2 ==0 ) -kvm_riscv_hfence_vvma_asid_all (vcpu->kvm, -0 , hmask, - cp->a3); +kvm_riscv_hfence_vvma_asid_all (vcpu->kvm,0 , hmask, + cp->a3, vmid);else -kvm_riscv_hfence_vvma_asid_gva (vcpu->kvm, -0 , hmask, - cp->a1, cp->a2, -PAGE_SHIFT , - cp->a3); +kvm_riscv_hfence_vvma_asid_gva (vcpu->kvm,0 , hmask, + cp->a1, cp->a2,PAGE_SHIFT , + cp->a3, vmid); }break ;default :
Signature · 1 line
2.43.0
Atish Patra
reviewerRe: [PATCH v2 12/12] RISC-V: KVM: Pass VMID as parameter to kvm_riscv_hfence_xyz() APIs
Quoted 234 lines · Anup Patel
Currently, all
kvm_riscv_hfence_xyz()APIs assume VMID to be the host VMID of the Guest/VM which resticts use of these APIs only for host TLB maintenance. Let's allow passing VMID as a parameter to allkvm_riscv_hfence_xyz()APIs so that they can be re-used for nested virtualization related TLB maintenance.Signed-off-by Anup Patel <[email protected]>--- arch/riscv/include/asm/kvm_tlb.h | 17 ++++++--- arch/riscv/kvm/gstage.c | 3 +- arch/riscv/kvm/tlb.c | 61 ++++++++++++++++++++----------- arch/riscv/kvm/vcpu_sbi_replace.c | 17 +++++---- arch/riscv/kvm/vcpu_sbi_v01.c | 25 ++++++------- 5 files changed, 73 insertions(+), 50 deletions(-)arch/riscv/include/asm/kvm_tlb.h +11
-6@@ -11,9 +11,11 @@enum kvm_riscv_hfence_type {KVM_RISCV_HFENCE_UNKNOWN =0 ,KVM_RISCV_HFENCE_GVMA_VMID_GPA , +KVM_RISCV_HFENCE_GVMA_VMID_ALL ,KVM_RISCV_HFENCE_VVMA_ASID_GVA ,KVM_RISCV_HFENCE_VVMA_ASID_ALL ,KVM_RISCV_HFENCE_VVMA_GVA , +KVM_RISCV_HFENCE_VVMA_ALL };struct kvm_riscv_hfence {@@ -59,21 +61,24 @@ void kvm_riscv_fence_i(struct kvm *kvm,void kvm_riscv_hfence_gvma_vmid_gpa (struct kvm *kvm,unsigned long hbase,unsigned long hmask,gpa_t gpa,gpa_t gpsz, -unsigned long order); +unsigned long order,unsigned long vmid);void kvm_riscv_hfence_gvma_vmid_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); +unsigned long hbase,unsigned long hmask, +unsigned long vmid);void kvm_riscv_hfence_vvma_asid_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order,unsigned long asid); +unsigned long order,unsigned long asid, +unsigned long vmid);void kvm_riscv_hfence_vvma_asid_all (struct kvm *kvm,unsigned long hbase,unsigned long hmask, -unsigned long asid); +unsigned long asid,unsigned long vmid);void kvm_riscv_hfence_vvma_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order); +unsigned long order,unsigned long vmid);void kvm_riscv_hfence_vvma_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); +unsigned long hbase,unsigned long hmask, +unsigned long vmid);#endif arch/riscv/kvm/gstage.c +2
-1@@ -117,7 +117,8 @@ static void gstage_tlb_flush(struct kvm_gstage *gstage, u32 level, gpa_t addr)if (gstage->flags &KVM_GSTAGE_FLAGS_LOCAL )kvm_riscv_local_hfence_gvma_vmid_gpa (gstage->vmid, addr,BIT (order), order);else -kvm_riscv_hfence_gvma_vmid_gpa (gstage->kvm,-1UL ,0 , addr,BIT (order), order); +kvm_riscv_hfence_gvma_vmid_gpa (gstage->kvm,-1UL ,0 , addr,BIT (order), order, + gstage->vmid); } int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,arch/riscv/kvm/tlb.c +40
-21@@ -251,6 +251,12 @@ void kvm_riscv_hfence_process(struct kvm_vcpu *vcpu)kvm_riscv_local_hfence_gvma_vmid_gpa (d.vmid, d.addr, d.size, d.order);break ; +case KVM_RISCV_HFENCE_GVMA_VMID_ALL : +if (kvm_riscv_nacl_available ()) +nacl_hfence_gvma_vmid_all (nacl_shmem (), d.vmid); +else +kvm_riscv_local_hfence_gvma_vmid_all (d.vmid); +break ;case KVM_RISCV_HFENCE_VVMA_ASID_GVA :kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD );if (kvm_riscv_nacl_available ())@@ -276,6 +282,13 @@ void kvm_riscv_hfence_process(struct kvm_vcpu *vcpu)kvm_riscv_local_hfence_vvma_gva (d.vmid, d.addr, d.size, d.order);break ; +case KVM_RISCV_HFENCE_VVMA_ALL : +kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_RCVD ); +if (kvm_riscv_nacl_available ()) +nacl_hfence_vvma_all (nacl_shmem (), d.vmid); +else +kvm_riscv_local_hfence_vvma_all (d.vmid); +break ;default :break ; }@@ -328,14 +341,13 @@ void kvm_riscv_fence_i(struct kvm *kvm,void kvm_riscv_hfence_gvma_vmid_gpa (struct kvm *kvm,unsigned long hbase,unsigned long hmask,gpa_t gpa,gpa_t gpsz, -unsigned long order) +unsigned long order,unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_GVMA_VMID_GPA ; data.asid =0 ; - data.vmid =READ_ONCE (v->vmid); + data.vmid = vmid; data.addr = gpa; data.size = gpsz; data.order = order;@@ -344,23 +356,28 @@ void kvm_riscv_hfence_gvma_vmid_gpa(struct kvm *kvm, }void kvm_riscv_hfence_gvma_vmid_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask) +unsigned long hbase,unsigned long hmask, +unsigned long vmid) { -make_xfence_request (kvm, hbase, hmask,KVM_REQ_TLB_FLUSH , -KVM_REQ_TLB_FLUSH ,NULL ); +struct kvm_riscv_hfence data = {0 }; + + data.type =KVM_RISCV_HFENCE_GVMA_VMID_ALL ; + data.vmid = vmid; +make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE , +KVM_REQ_TLB_FLUSH , &data); }void kvm_riscv_hfence_vvma_asid_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order,unsigned long asid) +unsigned long order,unsigned long asid, +unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_ASID_GVA ; data.asid = asid; - data.vmid =READ_ONCE (v->vmid); + data.vmid = vmid; data.addr = gva; data.size = gvsz; data.order = order;@@ -370,15 +387,13 @@ void kvm_riscv_hfence_vvma_asid_gva(struct kvm *kvm,void kvm_riscv_hfence_vvma_asid_all (struct kvm *kvm,unsigned long hbase,unsigned long hmask, -unsigned long asid) +unsigned long asid,unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid; -struct kvm_riscv_hfence data; +struct kvm_riscv_hfence data = {0 }; data.type =KVM_RISCV_HFENCE_VVMA_ASID_ALL ; data.asid = asid; - data.vmid =READ_ONCE (v->vmid); - data.addr = data.size = data.order =0 ; + data.vmid = vmid;make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE ,KVM_REQ_HFENCE_VVMA_ALL , &data); }@@ -386,14 +401,13 @@ void kvm_riscv_hfence_vvma_asid_all(struct kvm *kvm,void kvm_riscv_hfence_vvma_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order) +unsigned long order,unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_GVA ; data.asid =0 ; - data.vmid =READ_ONCE (v->vmid); + data.vmid = vmid; data.addr = gva; data.size = gvsz; data.order = order;@@ -402,16 +416,21 @@ void kvm_riscv_hfence_vvma_gva(struct kvm *kvm, }void kvm_riscv_hfence_vvma_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask) +unsigned long hbase,unsigned long hmask, +unsigned long vmid) { -make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE_VVMA_ALL , -KVM_REQ_HFENCE_VVMA_ALL ,NULL ); +struct kvm_riscv_hfence data = {0 }; + + data.type =KVM_RISCV_HFENCE_VVMA_ALL ; + data.vmid = vmid; +make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE , +KVM_REQ_HFENCE_VVMA_ALL , &data); }int kvm_arch_flush_remote_tlbs_range (struct kvm *kvm,gfn_t gfn,u64 nr_pages) {kvm_riscv_hfence_gvma_vmid_gpa (kvm,-1UL ,0 , gfn <<PAGE_SHIFT , nr_pages <<PAGE_SHIFT , -PAGE_SHIFT ); +PAGE_SHIFT ,READ_ONCE (kvm->arch.vmid.vmid));return 0 ; }arch/riscv/kvm/vcpu_sbi_replace.c +1
-0@@ -96,6 +96,7 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *rununsigned long hmask = cp->a0;unsigned long hbase = cp->a1;unsigned long funcid = cp->a6; +unsigned long vmid;switch (funcid) {case SBI_EXT_RFENCE_REMOTE_FENCE_I :
arch/riscv/kvm/vcpu_sbi_replace.c static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run · line 109
Quoted 7 lines
arch/riscv/kvm/vcpu_sbi_replace.c +2
-1@@ -103,22 +104,22 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *runkvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_FENCE_I_SENT );break ;case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA : + vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid);if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL ) -kvm_riscv_hfence_vvma_all (vcpu->kvm, hbase, hmask); +kvm_riscv_hfence_vvma_all (vcpu->kvm, hbase, hmask, vmid);
This patch doesn't apply cleanly on 6.16-rc1.
<<<<<<< HEAD
if (cp->a2 == 0 && cp->a3 == 0) kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase, hmask);
=======
vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid);
if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL) kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase, hmask, vmid);
arch/riscv/kvm/vcpu_sbi_replace.c static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run · line 110
Quoted 1 line
arch/riscv/kvm/vcpu_sbi_replace.c +0
-0>>>>>> 57ec61198cc1 (RISC-V: KVM: Pass VMID as parameter to kvm_riscv_hfence_xyz() APIs)
else
kvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask, cp->a2, cp->a3, PAGE_SHIFT, vmid); kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_SENT); break;
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
<<<<<<< HEAD
if (cp->a2 == 0 && cp->a3 == 0) kvm_riscv_hfence_vvma_asid_all(vcpu->kvm,
hbase, hmask, cp->a4);
=======
vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid);
if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL) kvm_riscv_hfence_vvma_asid_all(vcpu->kvm, hbase, hmask,
cp->a4, vmid);
Quoted 74 lines
arch/riscv/kvm/vcpu_sbi_replace.c +6
-7>>>>>> 57ec61198cc1 (RISC-V: KVM: Pass VMID as parameter to kvm_riscv_hfence_xyz() APIs) elsekvm_riscv_hfence_vvma_gva (vcpu->kvm, hbase, hmask, - cp->a2, cp->a3,PAGE_SHIFT ); + cp->a2, cp->a3,PAGE_SHIFT , vmid);kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_SENT );break ;case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID : + vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid);if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL ) -kvm_riscv_hfence_vvma_asid_all (vcpu->kvm, - hbase, hmask, cp->a4); +kvm_riscv_hfence_vvma_asid_all (vcpu->kvm, hbase, hmask, + cp->a4, vmid);else -kvm_riscv_hfence_vvma_asid_gva (vcpu->kvm, - hbase, hmask, - cp->a2, cp->a3, -PAGE_SHIFT , cp->a4); +kvm_riscv_hfence_vvma_asid_gva (vcpu->kvm, hbase, hmask, cp->a2, + cp->a3,PAGE_SHIFT , cp->a4, vmid);kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_ASID_SENT );break ;case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA :arch/riscv/kvm/vcpu_sbi_v01.c +11
-14@@ -23,6 +23,7 @@ static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,struct kvm *kvm = vcpu->kvm;struct kvm_cpu_context *cp = &vcpu->arch.guest_context;struct kvm_cpu_trap *utrap = retdata->utrap; +unsigned long vmid;switch (cp->a7) {case SBI_EXT_0_1_CONSOLE_GETCHAR :@@ -78,25 +79,21 @@ static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,if (cp->a7 ==SBI_EXT_0_1_REMOTE_FENCE_I )kvm_riscv_fence_i (vcpu->kvm,0 , hmask);else if (cp->a7 ==SBI_EXT_0_1_REMOTE_SFENCE_VMA ) { + vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid);if (cp->a1 ==0 && cp->a2 ==0 ) -kvm_riscv_hfence_vvma_all (vcpu->kvm, -0 , hmask); +kvm_riscv_hfence_vvma_all (vcpu->kvm,0 , hmask, vmid);else -kvm_riscv_hfence_vvma_gva (vcpu->kvm, -0 , hmask, - cp->a1, cp->a2, -PAGE_SHIFT ); +kvm_riscv_hfence_vvma_gva (vcpu->kvm,0 , hmask, cp->a1, + cp->a2,PAGE_SHIFT , vmid); }else { + vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid);if (cp->a1 ==0 && cp->a2 ==0 ) -kvm_riscv_hfence_vvma_asid_all (vcpu->kvm, -0 , hmask, - cp->a3); +kvm_riscv_hfence_vvma_asid_all (vcpu->kvm,0 , hmask, + cp->a3, vmid);else -kvm_riscv_hfence_vvma_asid_gva (vcpu->kvm, -0 , hmask, - cp->a1, cp->a2, -PAGE_SHIFT , - cp->a3); +kvm_riscv_hfence_vvma_asid_gva (vcpu->kvm,0 , hmask, + cp->a1, cp->a2,PAGE_SHIFT , + cp->a3, vmid); }break ;default :
Atish Patra
reviewerRe: [PATCH v2 12/12] RISC-V: KVM: Pass VMID as parameter to kvm_riscv_hfence_xyz() APIs
Quoted 271 lines · Atish Patra
Quoted 229 lines · Anup Patel
Currently, all
kvm_riscv_hfence_xyz()APIs assume VMID to be the host VMID of the Guest/VM which resticts use of these APIs only for host TLB maintenance. Let's allow passing VMID as a parameter to allkvm_riscv_hfence_xyz()APIs so that they can be re-used for nested virtualization related TLB maintenance.Signed-off-by Anup Patel <[email protected]>---
arch/riscv/include/asm/kvm_tlb.h | 17 ++++++--- arch/riscv/kvm/gstage.c | 3 +- arch/riscv/kvm/tlb.c | 61 ++++++++++++++++++++-----------arch/riscv/kvm/vcpu_sbi_replace.c| 17 +++++---- arch/riscv/kvm/vcpu_sbi_v01.c | 25 ++++++-------5 files changed, 73 insertions(+), 50 deletions(-)arch/riscv/include/asm/kvm_tlb.h +11
-6@@ -11,9 +11,11 @@ enum kvm_riscv_hfence_type { KVM_RISCV_HFENCE_UNKNOWN = 0, KVM_RISCV_HFENCE_GVMA_VMID_GPA, + KVM_RISCV_HFENCE_GVMA_VMID_ALL, KVM_RISCV_HFENCE_VVMA_ASID_GVA, KVM_RISCV_HFENCE_VVMA_ASID_ALL, KVM_RISCV_HFENCE_VVMA_GVA, + KVM_RISCV_HFENCE_VVMA_ALL }; struct kvm_riscv_hfence {@@ -59,21 +61,24 @@ void kvm_riscv_fence_i(struct kvm *kvm, void kvm_riscv_hfence_gvma_vmid_gpa(struct kvm *kvm, unsigned long hbase, unsigned long hmask, gpa_t gpa, gpa_t gpsz, - unsigned long order); + unsigned long order, unsigned long vmid); void kvm_riscv_hfence_gvma_vmid_all(struct kvm *kvm, - unsigned long hbase, unsigned long hmask); + unsigned long hbase, unsigned long hmask, + unsigned long vmid); void kvm_riscv_hfence_vvma_asid_gva(struct kvm *kvm, unsigned long hbase, unsigned long hmask, unsigned long gva, unsigned long gvsz, - unsigned long order, unsigned long asid); + unsigned long order, unsigned long asid, + unsigned long vmid); void kvm_riscv_hfence_vvma_asid_all(struct kvm *kvm, unsigned long hbase, unsigned long hmask, - unsigned long asid); + unsigned long asid, unsigned long vmid); void kvm_riscv_hfence_vvma_gva(struct kvm *kvm, unsigned long hbase, unsigned long hmask, unsigned long gva, unsigned long gvsz, - unsigned long order); + unsigned long order, unsigned long vmid); void kvm_riscv_hfence_vvma_all(struct kvm *kvm, - unsigned long hbase, unsigned long hmask); + unsigned long hbase, unsigned long hmask, + unsigned long vmid); #endifarch/riscv/kvm/gstage.c +0
-0@@ -117,7 +117,8 @@ static void gstage_tlb_flush(struct kvm_gstage *gstage, u32 level, gpa_t addr) if (gstage->flags & KVM_GSTAGE_FLAGS_LOCAL) kvm_riscv_local_hfence_gvma_vmid_gpa(gstage->vmid, addr, BIT(order), order);else
-kvm_riscv_hfence_gvma_vmid_gpa(gstage->kvm, -1UL, 0, addr, BIT(order), order);
+ kvm_riscv_hfence_gvma_vmid_gpa(gstage->kvm, -1UL, 0, addr, BIT(order), order,
+gstage->vmid);
}
int kvm_riscv_gstage_set_pte(structkvm_gstage*gstage,arch/riscv/kvm/tlb.c +6
-0@@ -251,6 +251,12 @@ void kvm_riscv_hfence_process(struct kvm_vcpu *vcpu) kvm_riscv_local_hfence_gvma_vmid_gpa(d.vmid, d.addr, d.size, d.order); break; + case KVM_RISCV_HFENCE_GVMA_VMID_ALL: + if (kvm_riscv_nacl_available()) + nacl_hfence_gvma_vmid_all(nacl_shmem(), d.vmid); + else + kvm_riscv_local_hfence_gvma_vmid_all(d.vmid); + break;case
KVM_RISCV_HFENCE_VVMA_ASID_GVA:
kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD); if (kvm_riscv_nacl_available())arch/riscv/kvm/tlb.c +7
-0@@ -276,6 +282,13 @@ void kvm_riscv_hfence_process(struct kvm_vcpu *vcpu) kvm_riscv_local_hfence_vvma_gva(d.vmid, d.addr, d.size, d.order); break; + case KVM_RISCV_HFENCE_VVMA_ALL: + kvm_riscv_vcpu_pmu_incr_fw(vcpu,SBI_PMU_FW_HFENCE_VVMA_RCVD ); + if (kvm_riscv_nacl_available()) + nacl_hfence_vvma_all(nacl_shmem(), d.vmid); + else + kvm_riscv_local_hfence_vvma_all(d.vmid); + break;default:
break;
}arch/riscv/kvm/tlb.c +27
-21@@ -328,14 +341,13 @@ void kvm_riscv_fence_i(struct kvm *kvm, void kvm_riscv_hfence_gvma_vmid_gpa(struct kvm *kvm, unsigned long hbase, unsigned long hmask, gpa_t gpa, gpa_t gpsz, - unsigned long order) + unsigned long order, unsigned long vmid) { - struct kvm_vmid *v = &kvm->arch.vmid; struct kvm_riscv_hfence data; data.type = KVM_RISCV_HFENCE_GVMA_VMID_GPA; data.asid = 0; - data.vmid = READ_ONCE(v->vmid); + data.vmid = vmid; data.addr = gpa; data.size = gpsz; data.order = order;@@ -344,23 +356,28 @@ void kvm_riscv_hfence_gvma_vmid_gpa(struct kvm *kvm, } void kvm_riscv_hfence_gvma_vmid_all(struct kvm *kvm, - unsigned long hbase, unsigned long hmask) + unsigned long hbase, unsigned long hmask, + unsigned long vmid) { - make_xfence_request(kvm, hbase, hmask, KVM_REQ_TLB_FLUSH, - KVM_REQ_TLB_FLUSH, NULL); + struct kvm_riscv_hfence data = {0}; + + data.type = KVM_RISCV_HFENCE_GVMA_VMID_ALL; + data.vmid = vmid; + make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE, + KVM_REQ_TLB_FLUSH, &data); } void kvm_riscv_hfence_vvma_asid_gva(struct kvm *kvm, unsigned long hbase, unsigned long hmask, unsigned long gva, unsigned long gvsz, - unsigned long order, unsigned long asid) + unsigned long order, unsigned long asid, + unsigned long vmid) { - struct kvm_vmid *v = &kvm->arch.vmid; struct kvm_riscv_hfence data; data.type = KVM_RISCV_HFENCE_VVMA_ASID_GVA; data.asid = asid; - data.vmid = READ_ONCE(v->vmid); + data.vmid = vmid; data.addr = gva; data.size = gvsz; data.order = order;@@ -370,15 +387,13 @@ void kvm_riscv_hfence_vvma_asid_gva(struct kvm *kvm, void kvm_riscv_hfence_vvma_asid_all(struct kvm *kvm, unsigned long hbase, unsigned long hmask, - unsigned long asid) + unsigned long asid, unsigned long vmid) { - struct kvm_vmid *v = &kvm->arch.vmid; - struct kvm_riscv_hfence data; + struct kvm_riscv_hfence data = {0}; data.type = KVM_RISCV_HFENCE_VVMA_ASID_ALL; data.asid = asid; - data.vmid = READ_ONCE(v->vmid); - data.addr = data.size = data.order = 0; + data.vmid = vmid; make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE, KVM_REQ_HFENCE_VVMA_ALL, &data); }@@ -386,14 +401,13 @@ void kvm_riscv_hfence_vvma_asid_all(struct kvm *kvm, void kvm_riscv_hfence_vvma_gva(struct kvm *kvm, unsigned long hbase, unsigned long hmask, unsigned long gva, unsigned long gvsz, - unsigned long order) + unsigned long order, unsigned long vmid) { - struct kvm_vmid *v = &kvm->arch.vmid; struct kvm_riscv_hfence data; data.type = KVM_RISCV_HFENCE_VVMA_GVA; data.asid = 0; - data.vmid = READ_ONCE(v->vmid); + data.vmid = vmid; data.addr = gva; data.size = gvsz; data.order = order;@@ -402,16 +416,21 @@ void kvm_riscv_hfence_vvma_gva(struct kvm *kvm, } void kvm_riscv_hfence_vvma_all(struct kvm *kvm, - unsigned long hbase, unsigned long hmask) + unsigned long hbase, unsigned long hmask, + unsigned long vmid) { - make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE_VVMA_ALL, - KVM_REQ_HFENCE_VVMA_ALL, NULL); + struct kvm_riscv_hfence data = {0}; + + data.type = KVM_RISCV_HFENCE_VVMA_ALL; + data.vmid = vmid; + make_xfence_request(kvm, hbase, hmask, KVM_REQ_HFENCE, + KVM_REQ_HFENCE_VVMA_ALL, &data); } int kvm_arch_flush_remote_tlbs_range(struct kvm *kvm, gfn_t gfn, u64 nr_pages) { kvm_riscv_hfence_gvma_vmid_gpa(kvm, -1UL, 0, gfn << PAGE_SHIFT, nr_pages << PAGE_SHIFT, - PAGE_SHIFT); + PAGE_SHIFT, READ_ONCE(kvm->arch.vmid.vmid)); return 0; }arch/riscv/kvm/vcpu_sbi_replace.c +0
-0@@ -96,6 +96,7 @@ static int kvm_sbi_ext_rfence_handler(struct
kvm_vcpu*vcpu, structkvm_run*run
unsigned long hmask =cp->a0;
unsigned long hbase =cp->a1;
unsigned long funcid =cp->a6;
+ unsigned long vmid;
switch (funcid) {
caseSBI_EXT_RFENCE_REMOTE_FENCE_I:arch/riscv/kvm/vcpu_sbi_replace.c +0
-0@@ -103,22 +104,22 @@ static int kvm_sbi_ext_rfence_handler(structQuoted 8 lines
kvm_vcpu*vcpu, structkvm_run*runkvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_FENCE_I_SENT); break;
caseSBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
+ vmid =READ_ONCE(vcpu->kvm->arch.vmid.vmid);
if ((cp->a2== 0 &&cp->a3== 0) ||cp->a3== -1UL) -kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase, hmask); +kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase, hmask, vmid);This patch doesn't apply cleanly on 6.16-rc1.
<<<<<<< HEAD
if (cp->a2== 0 &&cp->a3== 0) kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase,
hmask);
=======
vmid =READ_ONCE(vcpu->kvm->arch.vmid.vmid); if ((cp->a2== 0 &&cp->a3== 0) ||cp->a3== -1UL) kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase,
hmask, vmid);Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
57ec61198cc1(RISC-V: KVM: Pass VMID as parameter to
kvm_riscv_hfence_xyz()APIs)
else
kvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask,cp->a2,cp->a3,PAGE_SHIFT, vmid);
kvm_riscv_vcpu_pmu_incr_fw(vcpu,SBI_PMU_FW_HFENCE_VVMA_SENT);
break;
caseSBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
<<<<<<< HEAD
if (cp->a2== 0 &&cp->a3== 0)
kvm_riscv_hfence_vvma_asid_all(vcpu->kvm,
hbase, hmask,cp->a4);
=======
vmid =READ_ONCE(vcpu->kvm->arch.vmid.vmid); if ((cp->a2== 0 &&cp->a3== 0) ||cp->a3== -1UL)
kvm_riscv_hfence_vvma_asid_all(vcpu->kvm, hbase, hmask,
cp->a4, vmid);
Quoted 4 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
57ec61198cc1(RISC-V: KVM: Pass VMID as parameter to
kvm_riscv_hfence_xyz()APIs)
ohh you already queued the PATCH1 from v1 of this series. If I try to rebase on top of riscv_kvm_queue, I see the following error in b4 shazam.
---
Patch failed at 0008 RISC-V: KVM: Factor-out MMU related declarations into separate headers.
----
Quoted 73 lines
Quoted 73 lines
else
kvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask, -cp->a2,cp->a3,PAGE_SHIFT);
+cp->a2,cp->a3,PAGE_SHIFT, vmid);kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_SENT); break;
caseSBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
+ vmid =READ_ONCE(vcpu->kvm->arch.vmid.vmid);
if ((cp->a2== 0 &&cp->a3== 0) ||cp->a3== -1UL)
- kvm_riscv_hfence_vvma_asid_all(vcpu->kvm,
- hbase, hmask,cp->a4);
+ kvm_riscv_hfence_vvma_asid_all(vcpu->kvm, hbase, hmask, +cp->a4, vmid);
else
- kvm_riscv_hfence_vvma_asid_gva(vcpu->kvm,
- hbase, hmask,
-cp->a2,cp->a3,
-PAGE_SHIFT,cp->a4);
+ kvm_riscv_hfence_vvma_asid_gva(vcpu->kvm, hbase, hmask,cp->a2,
+cp->a3,PAGE_SHIFT,cp->a4, vmid);kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_ASID_SENT); break;
caseSBI_EXT_RFENCE_REMOTE_HFENCE_GVMA:arch/riscv/kvm/vcpu_sbi_v01.c +1
-0@@ -23,6 +23,7 @@ static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run, struct kvm *kvm = vcpu->kvm; struct kvm_cpu_context *cp = &vcpu->arch.guest_context; struct kvm_cpu_trap *utrap = retdata->utrap; + unsigned long vmid; switch (cp->a7) {case
SBI_EXT_0_1_CONSOLE_GETCHAR:arch/riscv/kvm/vcpu_sbi_v01.c +2
-2@@ -78,25 +79,21 @@ static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run, if (cp->a7 == SBI_EXT_0_1_REMOTE_FENCE_I) kvm_riscv_fence_i(vcpu->kvm, 0, hmask); else if (cp->a7 == SBI_EXT_0_1_REMOTE_SFENCE_VMA) { + vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid); if (cp->a1 == 0 && cp->a2 == 0) - kvm_riscv_hfence_vvma_all(vcpu->kvm, - 0, hmask); + kvm_riscv_hfence_vvma_all(vcpu->kvm, 0, hmask, vmid);else
- kvm_riscv_hfence_vvma_gva(vcpu->kvm,
- 0, hmask,
-cp->a1,cp->a2,
-PAGE_SHIFT);
+ kvm_riscv_hfence_vvma_gva(vcpu->kvm, 0, hmask,cp->a1, +cp->a2,PAGE_SHIFT, vmid);
} else {
+ vmid =READ_ONCE(vcpu->kvm->arch.vmid.vmid);
if (cp->a1== 0 &&cp->a2== 0)
- kvm_riscv_hfence_vvma_asid_all(vcpu->kvm,
- 0, hmask,
-cp->a3);
+ kvm_riscv_hfence_vvma_asid_all(vcpu->kvm, 0, hmask, +cp->a3, vmid);
else
- kvm_riscv_hfence_vvma_asid_gva(vcpu->kvm,
- 0, hmask,
-cp->a1,cp->a2,
-PAGE_SHIFT,
-cp->a3);
+ kvm_riscv_hfence_vvma_asid_gva(vcpu->kvm, 0, hmask, +cp->a1,cp->a2,PAGE_SHIFT, +cp->a3, vmid);
}
break;
default:
Re: [PATCH v2 12/12] RISC-V: KVM: Pass VMID as parameter to kvm_riscv_hfence_xyz() APIs
Quoted 285 lines · Atish Patra
Quoted 272 lines · Atish Patra
Quoted 238 lines · Anup Patel
Currently, all
kvm_riscv_hfence_xyz()APIs assume VMID to be the host VMID of the Guest/VM which resticts use of these APIs only for host TLB maintenance. Let's allow passing VMID as a parameter to allkvm_riscv_hfence_xyz()APIs so that they can be re-used for nested virtualization related TLB maintenance.Signed-off-by Anup Patel <[email protected]>--- arch/riscv/include/asm/kvm_tlb.h | 17 ++++++--- arch/riscv/kvm/gstage.c | 3 +- arch/riscv/kvm/tlb.c | 61 ++++++++++++++++++++----------- arch/riscv/kvm/vcpu_sbi_replace.c | 17 +++++---- arch/riscv/kvm/vcpu_sbi_v01.c | 25 ++++++------- 5 files changed, 73 insertions(+), 50 deletions(-)arch/riscv/include/ renamed from arch/riscv/include/asm/kvm_tlb.h +0
-0
asm/kvm_tlb.h
indexf67e03edeaec..38a2f933ad3a100644arch/riscv/include/asm/kvm_tlb.h +11
-6@@ -11,9 +11,11 @@enum kvm_riscv_hfence_type {KVM_RISCV_HFENCE_UNKNOWN =0 ,KVM_RISCV_HFENCE_GVMA_VMID_GPA , +KVM_RISCV_HFENCE_GVMA_VMID_ALL ,KVM_RISCV_HFENCE_VVMA_ASID_GVA ,KVM_RISCV_HFENCE_VVMA_ASID_ALL ,KVM_RISCV_HFENCE_VVMA_GVA , +KVM_RISCV_HFENCE_VVMA_ALL };struct kvm_riscv_hfence {@@ -59,21 +61,24 @@ void kvm_riscv_fence_i(struct kvm *kvm,void kvm_riscv_hfence_gvma_vmid_gpa (struct kvm *kvm,unsigned long hbase,unsigned long hmask,gpa_t gpa,gpa_t gpsz, -unsigned long order); +unsigned long order,unsigned long vmid);void kvm_riscv_hfence_gvma_vmid_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); +unsigned long hbase,unsigned long hmask, +unsigned long vmid);void kvm_riscv_hfence_vvma_asid_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order,unsigned long asid); +unsigned long order,unsigned long asid, +unsigned long vmid);void kvm_riscv_hfence_vvma_asid_all (struct kvm *kvm,unsigned long hbase,unsigned long hmask, -unsigned long asid); +unsigned long asid,unsigned long vmid);void kvm_riscv_hfence_vvma_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order); +unsigned long order,unsigned long vmid);void kvm_riscv_hfence_vvma_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); +unsigned long hbase,unsigned long hmask, +unsigned long vmid);#endif arch/riscv/kvm/gstage.c +1
-1@@ -117,7 +117,8 @@ static void gstage_tlb_flush(struct kvm_gstage *gstage, u32 level, gpa_t addr)if (gstage->flags &KVM_GSTAGE_FLAGS_LOCAL )kvm_riscv_local_hfence_gvma_vmid_gpa (gstage->vmid, addr,BIT (order), order);else -kvm_riscv_hfence_gvma_vmid_gpa (gstage->kvm,-1UL ,0 , addr, BIT(order), order); + kvm_riscv_hfence_gvma_vmid_gpa(gstage->kvm, -1UL, 0, addr,BIT(order), order,
arch/riscv/kvm/gstage.c +1
-0+ gstage->vmid); } int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,arch/riscv/kvm/tlb.c +6
-0@@ -251,6 +251,12 @@ void kvm_riscv_hfence_process(struct kvm_vcpu *vcpu)kvm_riscv_local_hfence_gvma_vmid_gpa (d.vmid, d.addr, d.size, d.order);break ; +case KVM_RISCV_HFENCE_GVMA_VMID_ALL : +if (kvm_riscv_nacl_available ()) +nacl_hfence_gvma_vmid_all (nacl_shmem (), d.vmid); +else +kvm_riscv_local_hfence_gvma_vmid_all (d.vmid); +break ;case KVM_RISCV_HFENCE_VVMA_ASID_GVA :kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD );if (
kvm_riscv_nacl_available())arch/riscv/kvm/tlb.c +7
-0@@ -276,6 +282,13 @@ void kvm_riscv_hfence_process(struct kvm_vcpu *vcpu)kvm_riscv_local_hfence_vvma_gva (d.vmid, d.addr, d.size, d.order);break ; +case KVM_RISCV_HFENCE_VVMA_ALL : +kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_RCVD ); +if (kvm_riscv_nacl_available ()) +nacl_hfence_vvma_all (nacl_shmem (), d.vmid); +else +kvm_riscv_local_hfence_vvma_all (d.vmid); +break ;default :break ;}arch/riscv/kvm/tlb.c +27
-21@@ -328,14 +341,13 @@ void kvm_riscv_fence_i(struct kvm *kvm,void kvm_riscv_hfence_gvma_vmid_gpa (struct kvm *kvm,unsigned long hbase,unsigned long hmask,gpa_t gpa,gpa_t gpsz, -unsigned long order) +unsigned long order,unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_GVMA_VMID_GPA ; data.asid =0 ; - data.vmid =READ_ONCE (v->vmid); + data.vmid = vmid; data.addr = gpa; data.size = gpsz; data.order = order;@@ -344,23 +356,28 @@ void kvm_riscv_hfence_gvma_vmid_gpa(struct kvm *kvm, }void kvm_riscv_hfence_gvma_vmid_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask) +unsigned long hbase,unsigned long hmask, +unsigned long vmid) { -make_xfence_request (kvm, hbase, hmask,KVM_REQ_TLB_FLUSH , -KVM_REQ_TLB_FLUSH ,NULL ); +struct kvm_riscv_hfence data = {0 }; + + data.type =KVM_RISCV_HFENCE_GVMA_VMID_ALL ; + data.vmid = vmid; +make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE , +KVM_REQ_TLB_FLUSH , &data); }void kvm_riscv_hfence_vvma_asid_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order,unsigned long asid) +unsigned long order,unsigned long asid, +unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_ASID_GVA ; data.asid = asid; - data.vmid =READ_ONCE (v->vmid); + data.vmid = vmid; data.addr = gva; data.size = gvsz; data.order = order;@@ -370,15 +387,13 @@ void kvm_riscv_hfence_vvma_asid_gva(struct kvm *kvm,void kvm_riscv_hfence_vvma_asid_all (struct kvm *kvm,unsigned long hbase,unsigned long hmask, -unsigned long asid) +unsigned long asid,unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid; -struct kvm_riscv_hfence data; +struct kvm_riscv_hfence data = {0 }; data.type =KVM_RISCV_HFENCE_VVMA_ASID_ALL ; data.asid = asid; - data.vmid =READ_ONCE (v->vmid); - data.addr = data.size = data.order =0 ; + data.vmid = vmid;make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE ,KVM_REQ_HFENCE_VVMA_ALL , &data); }@@ -386,14 +401,13 @@ void kvm_riscv_hfence_vvma_asid_all(struct kvm *kvm,void kvm_riscv_hfence_vvma_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order) +unsigned long order,unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_GVA ; data.asid =0 ; - data.vmid =READ_ONCE (v->vmid); + data.vmid = vmid; data.addr = gva; data.size = gvsz; data.order = order;@@ -402,16 +416,21 @@ void kvm_riscv_hfence_vvma_gva(struct kvm *kvm, }void kvm_riscv_hfence_vvma_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask) +unsigned long hbase,unsigned long hmask, +unsigned long vmid) { -make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE_VVMA_ALL , -KVM_REQ_HFENCE_VVMA_ALL ,NULL ); +struct kvm_riscv_hfence data = {0 }; + + data.type =KVM_RISCV_HFENCE_VVMA_ALL ; + data.vmid = vmid; +make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE , +KVM_REQ_HFENCE_VVMA_ALL , &data); }int kvm_arch_flush_remote_tlbs_range (struct kvm *kvm,gfn_t gfn,u64 nr_pages) {kvm_riscv_hfence_gvma_vmid_gpa (kvm,-1UL ,0 , gfn <<PAGE_SHIFT , nr_pages <<PAGE_SHIFT , -PAGE_SHIFT ); +PAGE_SHIFT ,READ_ONCE (kvm->arch.vmid.vmid));return 0 ; }arch/riscv/kvm/ renamed from arch/riscv/kvm/vcpu_sbi_replace.c +0
-0
vcpu_sbi_replace.c
indexb17fad091bab..b490ed1428a6100644arch/riscv/kvm/vcpu_sbi_replace.c +0
-0@@ -96,6 +96,7 @@ static int kvm_sbi_ext_rfence_handler(struct
kvm_vcpu*vcpu, structkvm_run*rununsigned long hmask = cp->a0; unsigned long hbase = cp->a1; unsigned long funcid = cp->a6;arch/riscv/kvm/vcpu_sbi_replace.c +1
-0+unsigned long vmid;switch (funcid) {case SBI_EXT_RFENCE_REMOTE_FENCE_I :@@ -103,22 +104,22 @@ static int kvm_sbi_ext_rfence_handler(struct
kvm_vcpu*vcpu, structkvm_run*runkvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_FENCE_I_SENT); break; case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:arch/riscv/kvm/vcpu_sbi_replace.c static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run · line 109
Quoted 4 lines
arch/riscv/kvm/vcpu_sbi_replace.c +2
-1+ vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid);if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL ) -kvm_riscv_hfence_vvma_all (vcpu->kvm, hbase, hmask); +kvm_riscv_hfence_vvma_all (vcpu->kvm, hbase, hmask, vmid);This patch doesn't apply cleanly on 6.16-rc1.
<<<<<<< HEAD
if (cp->a2 == 0 && cp->a3 == 0) kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase, hmask); ======= vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid); if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL) kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase,hmask, vmid);
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
57ec61198cc1(RISC-V: KVM: Pass VMID as parameter to
kvm_riscv_hfence_xyz()APIs)
elsekvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask, cp->a2, cp->a3,
PAGE_SHIFT, vmid);
kvm_riscv_vcpu_pmu_incr_fw(vcpu,SBI_PMU_FW_HFENCE_VVMA_SENT);
break;
caseSBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
<<<<<<< HEADif (cp->a2 == 0 && cp->a3 == 0)kvm_riscv_hfence_vvma_asid_all(vcpu->kvm,
hbase, hmask,cp->a4);
=======Quoted 8 lines
vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid); if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL) kvm_riscv_hfence_vvma_asid_all(vcpu->kvm, hbase, hmask, cp->a4, vmid);Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
57ec61198cc1(RISC-V: KVM: Pass VMID as parameter to
kvm_riscv_hfence_xyz()APIs)
Quoted 8 lines
ohh you already queued the PATCH1 from v1 of this series. If I try to rebase on top of
riscv_kvm_queue, I see the following error in b4 shazam.---
Patch failed at 0008 RISC-V: KVM: Factor-out MMU related declarations into separate headers.
----
Yes, first two patches are fixes for Linux-6.16
Regards,
Anup
Atish Patra
reviewerRe: [PATCH v2 12/12] RISC-V: KVM: Pass VMID as parameter to kvm_riscv_hfence_xyz() APIs
Quoted 285 lines · Anup Patel
Quoted 284 lines · Atish Patra
Quoted 270 lines · Atish Patra
Quoted 238 lines · Anup Patel
Currently, all
kvm_riscv_hfence_xyz()APIs assume VMID to be the host VMID of the Guest/VM which resticts use of these APIs only for host TLB maintenance. Let's allow passing VMID as a parameter to allkvm_riscv_hfence_xyz()APIs so that they can be re-used for nested virtualization related TLB maintenance.Signed-off-by Anup Patel <[email protected]>--- arch/riscv/include/asm/kvm_tlb.h | 17 ++++++--- arch/riscv/kvm/gstage.c | 3 +- arch/riscv/kvm/tlb.c | 61 ++++++++++++++++++++----------- arch/riscv/kvm/vcpu_sbi_replace.c | 17 +++++---- arch/riscv/kvm/vcpu_sbi_v01.c | 25 ++++++------- 5 files changed, 73 insertions(+), 50 deletions(-)arch/riscv/include/ renamed from arch/riscv/include/asm/kvm_tlb.h +0
-0
asm/kvm_tlb.h
indexf67e03edeaec..38a2f933ad3a100644arch/riscv/include/asm/kvm_tlb.h +11
-6@@ -11,9 +11,11 @@enum kvm_riscv_hfence_type {KVM_RISCV_HFENCE_UNKNOWN =0 ,KVM_RISCV_HFENCE_GVMA_VMID_GPA , +KVM_RISCV_HFENCE_GVMA_VMID_ALL ,KVM_RISCV_HFENCE_VVMA_ASID_GVA ,KVM_RISCV_HFENCE_VVMA_ASID_ALL ,KVM_RISCV_HFENCE_VVMA_GVA , +KVM_RISCV_HFENCE_VVMA_ALL };struct kvm_riscv_hfence {@@ -59,21 +61,24 @@ void kvm_riscv_fence_i(struct kvm *kvm,void kvm_riscv_hfence_gvma_vmid_gpa (struct kvm *kvm,unsigned long hbase,unsigned long hmask,gpa_t gpa,gpa_t gpsz, -unsigned long order); +unsigned long order,unsigned long vmid);void kvm_riscv_hfence_gvma_vmid_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); +unsigned long hbase,unsigned long hmask, +unsigned long vmid);void kvm_riscv_hfence_vvma_asid_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order,unsigned long asid); +unsigned long order,unsigned long asid, +unsigned long vmid);void kvm_riscv_hfence_vvma_asid_all (struct kvm *kvm,unsigned long hbase,unsigned long hmask, -unsigned long asid); +unsigned long asid,unsigned long vmid);void kvm_riscv_hfence_vvma_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order); +unsigned long order,unsigned long vmid);void kvm_riscv_hfence_vvma_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask); +unsigned long hbase,unsigned long hmask, +unsigned long vmid);#endif arch/riscv/kvm/gstage.c +1
-1@@ -117,7 +117,8 @@ static void gstage_tlb_flush(struct kvm_gstage *gstage, u32 level, gpa_t addr)if (gstage->flags &KVM_GSTAGE_FLAGS_LOCAL )kvm_riscv_local_hfence_gvma_vmid_gpa (gstage->vmid, addr,BIT (order), order);else -kvm_riscv_hfence_gvma_vmid_gpa (gstage->kvm,-1UL ,0 , addr, BIT(order), order); + kvm_riscv_hfence_gvma_vmid_gpa(gstage->kvm, -1UL, 0, addr,BIT(order), order,
arch/riscv/kvm/gstage.c +1
-0+ gstage->vmid); } int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,arch/riscv/kvm/tlb.c +6
-0@@ -251,6 +251,12 @@ void kvm_riscv_hfence_process(struct kvm_vcpu *vcpu)kvm_riscv_local_hfence_gvma_vmid_gpa (d.vmid, d.addr, d.size, d.order);break ; +case KVM_RISCV_HFENCE_GVMA_VMID_ALL : +if (kvm_riscv_nacl_available ()) +nacl_hfence_gvma_vmid_all (nacl_shmem (), d.vmid); +else +kvm_riscv_local_hfence_gvma_vmid_all (d.vmid); +break ;case KVM_RISCV_HFENCE_VVMA_ASID_GVA :kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_ASID_RCVD );if (
kvm_riscv_nacl_available())arch/riscv/kvm/tlb.c +7
-0@@ -276,6 +282,13 @@ void kvm_riscv_hfence_process(struct kvm_vcpu *vcpu)kvm_riscv_local_hfence_vvma_gva (d.vmid, d.addr, d.size, d.order);break ; +case KVM_RISCV_HFENCE_VVMA_ALL : +kvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_RCVD ); +if (kvm_riscv_nacl_available ()) +nacl_hfence_vvma_all (nacl_shmem (), d.vmid); +else +kvm_riscv_local_hfence_vvma_all (d.vmid); +break ;default :break ;}arch/riscv/kvm/tlb.c +27
-21@@ -328,14 +341,13 @@ void kvm_riscv_fence_i(struct kvm *kvm,void kvm_riscv_hfence_gvma_vmid_gpa (struct kvm *kvm,unsigned long hbase,unsigned long hmask,gpa_t gpa,gpa_t gpsz, -unsigned long order) +unsigned long order,unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_GVMA_VMID_GPA ; data.asid =0 ; - data.vmid =READ_ONCE (v->vmid); + data.vmid = vmid; data.addr = gpa; data.size = gpsz; data.order = order;@@ -344,23 +356,28 @@ void kvm_riscv_hfence_gvma_vmid_gpa(struct kvm *kvm, }void kvm_riscv_hfence_gvma_vmid_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask) +unsigned long hbase,unsigned long hmask, +unsigned long vmid) { -make_xfence_request (kvm, hbase, hmask,KVM_REQ_TLB_FLUSH , -KVM_REQ_TLB_FLUSH ,NULL ); +struct kvm_riscv_hfence data = {0 }; + + data.type =KVM_RISCV_HFENCE_GVMA_VMID_ALL ; + data.vmid = vmid; +make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE , +KVM_REQ_TLB_FLUSH , &data); }void kvm_riscv_hfence_vvma_asid_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order,unsigned long asid) +unsigned long order,unsigned long asid, +unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_ASID_GVA ; data.asid = asid; - data.vmid =READ_ONCE (v->vmid); + data.vmid = vmid; data.addr = gva; data.size = gvsz; data.order = order;@@ -370,15 +387,13 @@ void kvm_riscv_hfence_vvma_asid_gva(struct kvm *kvm,void kvm_riscv_hfence_vvma_asid_all (struct kvm *kvm,unsigned long hbase,unsigned long hmask, -unsigned long asid) +unsigned long asid,unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid; -struct kvm_riscv_hfence data; +struct kvm_riscv_hfence data = {0 }; data.type =KVM_RISCV_HFENCE_VVMA_ASID_ALL ; data.asid = asid; - data.vmid =READ_ONCE (v->vmid); - data.addr = data.size = data.order =0 ; + data.vmid = vmid;make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE ,KVM_REQ_HFENCE_VVMA_ALL , &data); }@@ -386,14 +401,13 @@ void kvm_riscv_hfence_vvma_asid_all(struct kvm *kvm,void kvm_riscv_hfence_vvma_gva (struct kvm *kvm,unsigned long hbase,unsigned long hmask,unsigned long gva,unsigned long gvsz, -unsigned long order) +unsigned long order,unsigned long vmid) { -struct kvm_vmid *v = &kvm->arch.vmid;struct kvm_riscv_hfence data; data.type =KVM_RISCV_HFENCE_VVMA_GVA ; data.asid =0 ; - data.vmid =READ_ONCE (v->vmid); + data.vmid = vmid; data.addr = gva; data.size = gvsz; data.order = order;@@ -402,16 +416,21 @@ void kvm_riscv_hfence_vvma_gva(struct kvm *kvm, }void kvm_riscv_hfence_vvma_all (struct kvm *kvm, -unsigned long hbase,unsigned long hmask) +unsigned long hbase,unsigned long hmask, +unsigned long vmid) { -make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE_VVMA_ALL , -KVM_REQ_HFENCE_VVMA_ALL ,NULL ); +struct kvm_riscv_hfence data = {0 }; + + data.type =KVM_RISCV_HFENCE_VVMA_ALL ; + data.vmid = vmid; +make_xfence_request (kvm, hbase, hmask,KVM_REQ_HFENCE , +KVM_REQ_HFENCE_VVMA_ALL , &data); }int kvm_arch_flush_remote_tlbs_range (struct kvm *kvm,gfn_t gfn,u64 nr_pages) {kvm_riscv_hfence_gvma_vmid_gpa (kvm,-1UL ,0 , gfn <<PAGE_SHIFT , nr_pages <<PAGE_SHIFT , -PAGE_SHIFT ); +PAGE_SHIFT ,READ_ONCE (kvm->arch.vmid.vmid));return 0 ; }arch/riscv/kvm/ renamed from arch/riscv/kvm/vcpu_sbi_replace.c +0
-0
vcpu_sbi_replace.c
indexb17fad091bab..b490ed1428a6100644arch/riscv/kvm/vcpu_sbi_replace.c +0
-0@@ -96,6 +96,7 @@ static int kvm_sbi_ext_rfence_handler(struct
kvm_vcpu*vcpu, structkvm_run*rununsigned long hmask = cp->a0; unsigned long hbase = cp->a1; unsigned long funcid = cp->a6;arch/riscv/kvm/vcpu_sbi_replace.c +1
-0+unsigned long vmid;switch (funcid) {case SBI_EXT_RFENCE_REMOTE_FENCE_I :@@ -103,22 +104,22 @@ static int kvm_sbi_ext_rfence_handler(struct
kvm_vcpu*vcpu, structkvm_run*runkvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_FENCE_I_SENT); break; case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:arch/riscv/kvm/vcpu_sbi_replace.c static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run · line 109
Quoted 4 lines
arch/riscv/kvm/vcpu_sbi_replace.c +2
-1+ vmid =READ_ONCE (vcpu->kvm->arch.vmid.vmid);if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL ) -kvm_riscv_hfence_vvma_all (vcpu->kvm, hbase, hmask); +kvm_riscv_hfence_vvma_all (vcpu->kvm, hbase, hmask, vmid);This patch doesn't apply cleanly on 6.16-rc1.
<<<<<<< HEAD
if (cp->a2 == 0 && cp->a3 == 0) kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase, hmask); ======= vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid); if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL) kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase,hmask, vmid);
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
57ec61198cc1(RISC-V: KVM: Pass VMID as parameter to
kvm_riscv_hfence_xyz()APIs)
elsekvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask, cp->a2, cp->a3,
PAGE_SHIFT, vmid);
kvm_riscv_vcpu_pmu_incr_fw(vcpu,SBI_PMU_FW_HFENCE_VVMA_SENT);
break;
caseSBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
<<<<<<< HEADif (cp->a2 == 0 && cp->a3 == 0)kvm_riscv_hfence_vvma_asid_all(vcpu->kvm,
hbase, hmask,cp->a4);
=======Quoted 8 lines
vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid); if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL) kvm_riscv_hfence_vvma_asid_all(vcpu->kvm, hbase, hmask, cp->a4, vmid);Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
57ec61198cc1(RISC-V: KVM: Pass VMID as parameter to
kvm_riscv_hfence_xyz()APIs)ohh you already queued the PATCH1 from v1 of this series. If I try to rebase on top of
riscv_kvm_queue, I see the following error in b4 shazam.
Quoted 6 lines
Quoted 5 lines
---
Patch failed at 0008 RISC-V: KVM: Factor-out MMU related declarations into separate headers.
----Yes, first two patches are fixes for Linux-6.16
Ahh I see the fixes branch was updated yesterday. The rebase works cleanly now. Thanks.
Quoted 2 lines
Regards,
Anup