MMU related improvements for KVM RISC-V
Subsystems (3)
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_v1 branch
at: https://github.com/avpatel/linux.git
Anup Patel (13):
RISC-V: KVM: Fix the size parameter check in SBI SFENCE calls
RISC-V: KVM: Don't treat SBI HFENCE calls as NOPs
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 in gstage_set_pte() when PTE is unchanged
RISC-V: KVM: Implement kvm_arch_flush_remote_tlbs_range()
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 | 336 +++++++++++++++++++ arch/riscv/kvm/main.c | 3 +- arch/riscv/kvm/mmu.c | 499 ++++++---------------------- arch/riscv/kvm/tlb.c | 110 +++--- arch/riscv/kvm/vcpu.c | 27 +- arch/riscv/kvm/vcpu_exit.c | 7 +- arch/riscv/kvm/vcpu_sbi_replace.c | 25 +- arch/riscv/kvm/vcpu_sbi_v01.c | 25 +- arch/riscv/kvm/vm.c | 7 +- arch/riscv/kvm/vmid.c | 25 ++ 19 files changed, 791 insertions(+), 601 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 1/13 RISC-V: KVM: Fix the size parameter check in SBI SFENCE calls
As-per the SBI specification, an SBI remote fence operation applies to the entire address space if either:
1) start_addr and size are both 0
2) size is equal to 2^XLEN-1
From the above, only #1 is checked by SBI SFENCE calls so fix the size parameter check in SBI SFENCE calls to cover #2 as well.
--- arch/riscv/kvm/vcpu_sbi_replace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/riscv/kvm/vcpu_sbi_replace.c +2 -2
@@ -103,7 +103,7 @@ 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 : -if (cp->a2 ==0 && cp->a3 ==0 ) +if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL )kvm_riscv_hfence_vvma_all (vcpu->kvm, hbase, hmask);else kvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask,
@@ -111,7 +111,7 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *runkvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_SENT );break ;case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID : -if (cp->a2 ==0 && cp->a3 ==0 ) +if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL )kvm_riscv_hfence_vvma_asid_all (vcpu->kvm, hbase, hmask, cp->a4);else
Signature · 1 line
2.43.0
Re: [PATCH 01/13] RISC-V: KVM: Fix the size parameter check in SBI SFENCE calls
Quoted 28 lines · Anup Patel
As-per the SBI specification, an SBI remote fence operation applies to the entire address space if either:
1)start_addrand size are both 0
2) size is equal to 2^XLEN-1From the above, only #1 is checked by SBI SFENCE calls so fix the
size parameter check in SBI SFENCE calls to cover #2 as well.Fixes 13acfec2dbcc ("RISC-V: KVM: Add remote HFENCE functions based on VCPU requests")Signed-off-by Anup Patel <[email protected]>--- arch/riscv/kvm/vcpu_sbi_replace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)arch/riscv/kvm/vcpu_sbi_replace.c +1
-1@@ -103,7 +103,7 @@ 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 : -if (cp->a2 ==0 && cp->a3 ==0 ) +if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL )kvm_riscv_hfence_vvma_all (vcpu->kvm, hbase, hmask);else kvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask,
arch/riscv/kvm/vcpu_sbi_replace.c static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run · line 117
Quoted 8 lines
arch/riscv/kvm/vcpu_sbi_replace.c +1
-1@@ -111,7 +111,7 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *runkvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_SENT );break ;case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID : -if (cp->a2 ==0 && cp->a3 ==0 ) +if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL )kvm_riscv_hfence_vvma_asid_all (vcpu->kvm, hbase, hmask, cp->a4);else
Thanks for the fix.
Anup Patel
maintainerRe: [PATCH 01/13] RISC-V: KVM: Fix the size parameter check in SBI SFENCE calls
In reply to Anup PatelQuoted 11 lines · Anup Patel
As-per the SBI specification, an SBI remote fence operation applies to the entire address space if either:
1)start_addrand size are both 0
2) size is equal to 2^XLEN-1From the above, only #1 is checked by SBI SFENCE calls so fix the size parameter check in SBI SFENCE calls to cover #2 as well.
Fixes 13acfec2dbcc ("RISC-V: KVM: Add remote HFENCE functions based on VCPU requests")Signed-off-by Anup Patel <[email protected]>
Queued as a fix for Linux-6.16
Regards,
Anup
Quoted 29 lines
--- arch/riscv/kvm/vcpu_sbi_replace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)arch/riscv/kvm/vcpu_sbi_replace.c +2
-3@@ -103,7 +103,7 @@ 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 : -if (cp->a2 ==0 && cp->a3 ==0 ) +if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL )kvm_riscv_hfence_vvma_all (vcpu->kvm, hbase, hmask);else kvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask,@@ -111,7 +111,7 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *runkvm_riscv_vcpu_pmu_incr_fw (vcpu,SBI_PMU_FW_HFENCE_VVMA_SENT );break ;case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID : -if (cp->a2 ==0 && cp->a3 ==0 ) +if ((cp->a2 ==0 && cp->a3 ==0 ) || cp->a3 ==-1UL )kvm_riscv_hfence_vvma_asid_all (vcpu->kvm, hbase, hmask, cp->a4);else --2.43.0
PATCH 2/13 RISC-V: KVM: Don't treat SBI HFENCE calls as NOPs
In reply to Anup PatelThe SBI specification clearly states that SBI HFENCE calls should return SBI_ERR_NOT_SUPPORTED when one of the target hart doesn’t support hypervisor extension (aka nested virtualization in-case of KVM RISC-V).
--- arch/riscv/kvm/vcpu_sbi_replace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/riscv/kvm/vcpu_sbi_replace.c +2 -2
@@ -127,9 +127,9 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *runcase SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID :/* * Until nested virtualization is implemented, the -* SBI HFENCE calls should be treated as NOPs +* SBI HFENCE calls should return not supported +* hence fallthrough. */ -break ;default : retdata->err_val =SBI_ERR_NOT_SUPPORTED ; }
Signature · 1 line
2.43.0
Re: [PATCH 02/13] RISC-V: KVM: Don't treat SBI HFENCE calls as NOPs
Quoted 17 lines · Anup Patel
The SBI specification clearly states that SBI HFENCE calls should return
SBI_ERR_NOT_SUPPORTEDwhen one of the target hart doesn’t support hypervisor extension (aka nested virtualization in-case of KVM RISC-V).Fixes c7fa3c48de86 ("RISC-V: KVM: Treat SBI HFENCE calls as NOPs")Signed-off-by Anup Patel <[email protected]>--- arch/riscv/kvm/vcpu_sbi_replace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)arch/riscv/kvm/vcpu_sbi_replace.c +0
-0@@ -127,9 +127,9 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *runcase SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID :
arch/riscv/kvm/vcpu_sbi_replace.c static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run · line 135
Quoted 10 lines
arch/riscv/kvm/vcpu_sbi_replace.c +2
-2/* * Until nested virtualization is implemented, the -* SBI HFENCE calls should be treated as NOPs +* SBI HFENCE calls should return not supported +* hence fallthrough. */ -break ;default : retdata->err_val =SBI_ERR_NOT_SUPPORTED ; }
Anup Patel
maintainerRe: [PATCH 02/13] RISC-V: KVM: Don't treat SBI HFENCE calls as NOPs
In reply to Anup PatelQuoted 8 lines · Anup Patel
The SBI specification clearly states that SBI HFENCE calls should return
SBI_ERR_NOT_SUPPORTEDwhen one of the target hart doesn’t support hypervisor extension (aka nested virtualization in-case of KVM RISC-V).Fixes c7fa3c48de86 ("RISC-V: KVM: Treat SBI HFENCE calls as NOPs")Signed-off-by Anup Patel <[email protected]>
Queued as a fix for Linux-6.16
Regards,
Anup
Quoted 23 lines
--- arch/riscv/kvm/vcpu_sbi_replace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)arch/riscv/kvm/vcpu_sbi_replace.c +2
-3@@ -127,9 +127,9 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *runcase SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID :/* * Until nested virtualization is implemented, the -* SBI HFENCE calls should be treated as NOPs +* SBI HFENCE calls should return not supported +* hence fallthrough. */ -break ;default : retdata->err_val =SBI_ERR_NOT_SUPPORTED ; } --2.43.0
PATCH 3/13 RISC-V: KVM: Check kvm_riscv_vcpu_alloc_vector_context() return value
In reply to Anup PatelThe 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 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/riscv/kvm/vcpu.c +4 -2
@@ -148,8 +148,10 @@ 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 ; +/* Setup VCPU vector context */ + 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
Atish Patra
reviewerRe: [PATCH 03/13] RISC-V: KVM: Check kvm_riscv_vcpu_alloc_vector_context() return value
Quoted 2 lines · Anup Patel
The
kvm_riscv_vcpu_alloc_vector_context()does return an error code upon failure so don't ignore this inkvm_arch_vcpu_create().
currently, kvm_riscv_vcpu_alloc_vector_context returns -ENOMEM only.
Do you have some plans to return different errors in the future ?
Otherwise, the code remains same before and after.
Quoted 10 lines
Signed-off-by Anup Patel <[email protected]>--- arch/riscv/kvm/vcpu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)arch/riscv/kvm/vcpu.c +0
-0
arch/riscv/kvm/vcpu.c int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) · line 151
Quoted 6 lines
arch/riscv/kvm/vcpu.c +1
-2@@ -148,8 +148,10 @@ 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 ; +/* Setup VCPU vector context */
The function name is pretty self explanatory. So no need of this comment ?
Quoted 6 lines
arch/riscv/kvm/vcpu.c +3
-0+ rc =kvm_riscv_vcpu_alloc_vector_context (vcpu); +if (rc) +return rc;/* Setup VCPU timer */ kvm_riscv_vcpu_timer_init (vcpu);
Re: [PATCH 03/13] RISC-V: KVM: Check kvm_riscv_vcpu_alloc_vector_context() return value
Quoted 9 lines · Atish Patra
Quoted 2 lines · Anup Patel
The
kvm_riscv_vcpu_alloc_vector_context()does return an error code upon failure so don't ignore this inkvm_arch_vcpu_create().currently,
kvm_riscv_vcpu_alloc_vector_contextreturns-ENOMEMonly.Do you have some plans to return different errors in the future ?
Even if kvm_riscv_vcpu_alloc_vector_context() always returns -ENOMEM, the caller should not assume anything about the return value.
Quoted 14 lines
Otherwise, the code remains same before and after.
Quoted 11 lines
Signed-off-by Anup Patel <[email protected]>--- arch/riscv/kvm/vcpu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)arch/riscv/kvm/vcpu.c +0
-0@@ -148,8 +148,10 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
Quoted 6 lines
arch/riscv/kvm/vcpu.c int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) · line 151
Quoted 5 lines
arch/riscv/kvm/vcpu.c +1
-2spin_lock_init (&vcpu->arch.reset_state.lock); -if (kvm_riscv_vcpu_alloc_vector_context (vcpu)) -return -ENOMEM ; +/* Setup VCPU vector context */ The function name is pretty self explanatory. So no need of this comment ?
Yes, no need for this comment. I will drop it in the next revision.
Quoted 7 lines
arch/riscv/kvm/vcpu.c int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) · line 157
Quoted 6 lines
arch/riscv/kvm/vcpu.c +3
-0+ rc =kvm_riscv_vcpu_alloc_vector_context (vcpu); +if (rc) +return rc;/* Setup VCPU timer */ kvm_riscv_vcpu_timer_init (vcpu);
Regards,
Anup
PATCH 4/13 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
@@ -539,12 +539,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
@@ -556,8 +556,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
@@ -160,9 +160,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
Atish Patra
reviewerRe: [PATCH 04/13] RISC-V: KVM: Drop the return value of kvm_riscv_vcpu_aia_init()
Quoted 66 lines · Anup Patel
The
kvm_riscv_vcpu_aia_init()does not return any failure so drop the return value which is always zero.Signed-off-by Anup Patel <[email protected]>--- 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@@ -539,12 +539,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 @@ -556,8 +556,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@@ -160,9 +160,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
Re: [PATCH 04/13] RISC-V: KVM: Drop the return value of kvm_riscv_vcpu_aia_init()
In reply to Anup PatelQuoted 56 lines · Anup Patel
The
kvm_riscv_vcpu_aia_init()does not return any failure so drop the return value which is always zero.Signed-off-by Anup Patel <[email protected]>--- 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@@ -539,12 +539,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 @@ -556,8 +556,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 +0
-0
arch/riscv/kvm/vcpu.c int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) · line 164
Quoted 8 lines
arch/riscv/kvm/vcpu.c +1
-3@@ -160,9 +160,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);
This seems more reasonable.
Thanks,
Nutty
Quoted 2 lines
arch/riscv/kvm/vcpu.c +0
-0/* * Setup SBI extensions
PATCH 5/13 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
@@ -327,8 +327,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);
@@ -376,6 +374,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
@@ -961,12 +961,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
Re: [PATCH 05/13] RISC-V: KVM: Rename and move kvm_riscv_local_tlb_sanitize()
Quoted 110 lines · Anup Patel
The
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 tokvm_riscv_gstage_vmid_sanitize().Signed-off-by Anup Patel <[email protected]>--- 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@@ -327,8 +327,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);@@ -376,6 +374,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@@ -961,12 +961,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 +13
-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
arch/riscv/kvm/vmid.c void kvm_riscv_gstage_vmid_update(struct kvm_vcpu *vcpu) · line 147
Quoted 10 lines
arch/riscv/kvm/vmid.c +10
-0+* 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); +}
Re: [PATCH 05/13] RISC-V: KVM: Rename and move kvm_riscv_local_tlb_sanitize()
In reply to Anup PatelQuoted 110 lines · Anup Patel
The
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 tokvm_riscv_gstage_vmid_sanitize().Signed-off-by Anup Patel <[email protected]>--- 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@@ -327,8 +327,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);@@ -376,6 +374,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@@ -961,12 +961,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 +13
-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
arch/riscv/kvm/vmid.c void kvm_riscv_gstage_vmid_update(struct kvm_vcpu *vcpu) · line 147
Quoted 10 lines
arch/riscv/kvm/vmid.c +10
-0+* 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); +}
Thanks.
PATCH 6/13 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
@@ -36,7 +36,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 \
@@ -327,8 +326,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
@@ -720,12 +720,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
Re: [PATCH 06/13] RISC-V: KVM: Replace KVM_REQ_HFENCE_GVMA_VMID_ALL with KVM_REQ_TLB_FLUSH
Quoted 75 lines · Anup Patel
The
KVM_REQ_HFENCE_GVMA_VMID_ALLis same asKVM_REQ_TLB_FLUSHso to avoid confusion let's replaceKVM_REQ_HFENCE_GVMA_VMID_ALLwithKVM_REQ_TLB_FLUSH. Also, renamekvm_riscv_hfence_gvma_vmid_all_process()tokvm_riscv_tlb_flush_process().Signed-off-by Anup Patel <[email protected]>--- 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@@ -36,7 +36,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 \@@ -327,8 +326,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 +0
-1@@ -720,12 +720,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); -/*
arch/riscv/kvm/vcpu.c static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu) · line 727
Quoted 10 lines
arch/riscv/kvm/vcpu.c +2
-5-* 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);
PATCH 7/13 RISC-V: KVM: Don't flush TLB in gstage_set_pte() when PTE is unchanged
In reply to Anup PatelThe gstage_set_pte() should flush remote TLB only when a leaf PTE changes so that unnecessary remote TLB flushes can be avoided.
--- arch/riscv/kvm/mmu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
arch/riscv/kvm/mmu.c +5 -3
@@ -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 ; }
Signature · 1 line
2.43.0
PATCH 8/13 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
@@ -42,6 +42,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
@@ -342,7 +342,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
PATCH 9/13 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>
@@ -55,24 +57,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; };
@@ -98,15 +82,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;
@@ -307,77 +282,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> static int gstage_page_fault (struct kvm_vcpu *vcpu,struct kvm_run *run,struct kvm_cpu_trap *trap)
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
PATCH 10/13 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 page table level of the g-stage. 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
@@ -14,6 +14,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;
@@ -42,7 +43,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
PATCH 11/13 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
PATCH 12/13 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 into 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 | 335 +++++++++++++++++++ arch/riscv/kvm/main.c | 2 +- arch/riscv/kvm/mmu.c | 490 ++++++---------------------- arch/riscv/kvm/vcpu.c | 4 +- arch/riscv/kvm/vcpu_exit.c | 5 +- arch/riscv/kvm/vm.c | 6 +- 10 files changed, 528 insertions(+), 430 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 +335 -0
335 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 -394
676 lines not on this page · raw message
arch/riscv/kvm/vcpu.c +2 -2
@@ -631,7 +631,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);
@@ -716,7 +716,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
@@ -42,8 +42,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 13/13 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 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