From ab8dcba529725fdd6b57fa8a9650c5080f43bc15 Mon Sep 17 00:00:00 2001 From: yechao-w Date: Tue, 2 Sep 2025 14:55:04 +0800 Subject: [PATCH 1/4] RISC-V: KVM: Redirect AMO load/store access fault traps to guest mainline inclusion from Linux 6.13 commit e325618349cdc1fbbe63574080249730e7cff9ea category: feature bugzilla: https://github.com/RVCK-Project/rvck/issues/115 -------------------------------- The KVM RISC-V does not delegate AMO load/store access fault traps to VS-mode (hedeleg) so typically M-mode takes these traps and redirects them back to HS-mode. However, upon returning from M-mode, the KVM RISC-V running in HS-mode terminates VS-mode software. The KVM RISC-V should redirect AMO load/store access fault traps back to VS-mode and let the VS-mode trap handler determine the next steps. Signed-off-by: Yu-Wei Hsu Reviewed-by: Anup Patel Link: https://lore.kernel.org/r/20240429092113.70695-1-betterman5240@gmail.com Signed-off-by: Anup Patel Signed-off-by: yechao-w --- arch/riscv/kvm/vcpu_exit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c index 2415722c01b8e..ef8c5e3ec8a0d 100644 --- a/arch/riscv/kvm/vcpu_exit.c +++ b/arch/riscv/kvm/vcpu_exit.c @@ -185,6 +185,8 @@ int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, case EXC_INST_ILLEGAL: case EXC_LOAD_MISALIGNED: case EXC_STORE_MISALIGNED: + case EXC_LOAD_ACCESS: + case EXC_STORE_ACCESS: if (vcpu->arch.guest_context.hstatus & HSTATUS_SPV) { kvm_riscv_vcpu_trap_redirect(vcpu, trap); ret = 1; From 859221ad16ec5abd17c7f4314bfb116785c33022 Mon Sep 17 00:00:00 2001 From: yechao-w Date: Tue, 2 Sep 2025 14:56:36 +0800 Subject: [PATCH 2/4] RISC-V: KVM: Redirect instruction access fault trap to guest mainline inclusion from Linux 6.13 commit 51c58956732bb20c5782dea1b2966270827e3aa2 category: feature bugzilla: https://github.com/RVCK-Project/rvck/issues/115 -------------------------------- The M-mode redirects an unhandled instruction access fault trap back to S-mode when not delegating it to VS-mode(hedeleg). However, KVM running in HS-mode terminates the VS-mode software when back from M-mode. The KVM should redirect the trap back to VS-mode, and let VS-mode trap handler decide the next step. Signed-off-by: Quan Zhou Reviewed-by: Anup Patel Signed-off-by: Atish Patra Link: https://lore.kernel.org/r/20241224-kvm_guest_stat-v2-1-08a77ac36b02@rivosinc.com Signed-off-by: Anup Patel Signed-off-by: yechao-w --- arch/riscv/kvm/vcpu_exit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c index ef8c5e3ec8a0d..bd7f8556c4797 100644 --- a/arch/riscv/kvm/vcpu_exit.c +++ b/arch/riscv/kvm/vcpu_exit.c @@ -187,6 +187,7 @@ int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, case EXC_STORE_MISALIGNED: case EXC_LOAD_ACCESS: case EXC_STORE_ACCESS: + case EXC_INST_ACCESS: if (vcpu->arch.guest_context.hstatus & HSTATUS_SPV) { kvm_riscv_vcpu_trap_redirect(vcpu, trap); ret = 1; From 2e3f2b78296ae8dfa08156a2f591366c25bf0bc5 Mon Sep 17 00:00:00 2001 From: yechao-w Date: Tue, 2 Sep 2025 14:56:40 +0800 Subject: [PATCH 3/4] RISC-V: KVM: Update firmware counters for various events mainline inclusion from Linux 6.13 commit 2f15b5eaff79b70b004b0aae79dee62d3b3abda0 category: feature bugzilla: https://github.com/RVCK-Project/rvck/issues/115 -------------------------------- SBI PMU specification defines few firmware counters which can be used by the guests to collect the statstics about various traps occurred in the host. Update these counters whenever a corresponding trap is taken Reviewed-by: Anup Patel Signed-off-by: Atish Patra Link: https://lore.kernel.org/r/20241224-kvm_guest_stat-v2-2-08a77ac36b02@rivosinc.com Signed-off-by: Anup Patel Signed-off-by: yechao-w --- arch/riscv/kvm/vcpu_exit.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c index bd7f8556c4797..ea4ddf0bee7af 100644 --- a/arch/riscv/kvm/vcpu_exit.c +++ b/arch/riscv/kvm/vcpu_exit.c @@ -165,6 +165,17 @@ void kvm_riscv_vcpu_trap_redirect(struct kvm_vcpu *vcpu, vcpu->arch.guest_context.sstatus |= SR_SPP; } +static inline int vcpu_redirect(struct kvm_vcpu *vcpu, struct kvm_cpu_trap *trap) +{ + int ret = -EFAULT; + + if (vcpu->arch.guest_context.hstatus & HSTATUS_SPV) { + kvm_riscv_vcpu_trap_redirect(vcpu, trap); + ret = 1; + } + return ret; +} + /* * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on * proper exit to userspace. @@ -183,15 +194,27 @@ int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, run->exit_reason = KVM_EXIT_UNKNOWN; switch (trap->scause) { case EXC_INST_ILLEGAL: + kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_ILLEGAL_INSN); + ret = vcpu_redirect(vcpu, trap); + break; case EXC_LOAD_MISALIGNED: + kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_MISALIGNED_LOAD); + ret = vcpu_redirect(vcpu, trap); + break; case EXC_STORE_MISALIGNED: + kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_MISALIGNED_STORE); + ret = vcpu_redirect(vcpu, trap); + break; case EXC_LOAD_ACCESS: + kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_ACCESS_LOAD); + ret = vcpu_redirect(vcpu, trap); + break; case EXC_STORE_ACCESS: + kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_ACCESS_STORE); + ret = vcpu_redirect(vcpu, trap); + break; case EXC_INST_ACCESS: - if (vcpu->arch.guest_context.hstatus & HSTATUS_SPV) { - kvm_riscv_vcpu_trap_redirect(vcpu, trap); - ret = 1; - } + ret = vcpu_redirect(vcpu, trap); break; case EXC_VIRTUAL_INST_FAULT: if (vcpu->arch.guest_context.hstatus & HSTATUS_SPV) From da513b913728031338d2104b14fd6bc097e3d1df Mon Sep 17 00:00:00 2001 From: yechao-w Date: Tue, 2 Sep 2025 14:56:43 +0800 Subject: [PATCH 4/4] RISC-V: KVM: Add new exit statstics for redirected traps mainline inclusion from Linux 6.13 commit af79caa83f6aa41e9092292a2ba7f701e57353ec category: feature bugzilla: https://github.com/RVCK-Project/rvck/issues/115 -------------------------------- Currently, kvm doesn't delegate the few traps such as misaligned load/store, illegal instruction and load/store access faults because it is not expected to occur in the guest very frequently. Thus, kvm gets a chance to act upon it or collect statistics about it before redirecting the traps to the guest. Collect both guest and host visible statistics during the traps. Enable them so that both guest and host can collect the stats about them if required. Reviewed-by: Anup Patel Signed-off-by: Atish Patra Link: https://lore.kernel.org/r/20241224-kvm_guest_stat-v2-3-08a77ac36b02@rivosinc.com Signed-off-by: Anup Patel Signed-off-by: yechao-w --- arch/riscv/include/asm/kvm_host.h | 5 +++++ arch/riscv/kvm/vcpu.c | 7 ++++++- arch/riscv/kvm/vcpu_exit.c | 5 +++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h index fb6def20ddc75..aac879b7021ed 100644 --- a/arch/riscv/include/asm/kvm_host.h +++ b/arch/riscv/include/asm/kvm_host.h @@ -74,6 +74,11 @@ struct kvm_vcpu_stat { u64 csr_exit_kernel; u64 signal_exits; u64 exits; + u64 instr_illegal_exits; + u64 load_misaligned_exits; + u64 store_misaligned_exits; + u64 load_access_exits; + u64 store_access_exits; }; struct kvm_arch_memory_slot { diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c index 47949518a1e19..0d689df654711 100644 --- a/arch/riscv/kvm/vcpu.c +++ b/arch/riscv/kvm/vcpu.c @@ -30,7 +30,12 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { STATS_DESC_COUNTER(VCPU, csr_exit_user), STATS_DESC_COUNTER(VCPU, csr_exit_kernel), STATS_DESC_COUNTER(VCPU, signal_exits), - STATS_DESC_COUNTER(VCPU, exits) + STATS_DESC_COUNTER(VCPU, exits), + STATS_DESC_COUNTER(VCPU, instr_illegal_exits), + STATS_DESC_COUNTER(VCPU, load_misaligned_exits), + STATS_DESC_COUNTER(VCPU, store_misaligned_exits), + STATS_DESC_COUNTER(VCPU, load_access_exits), + STATS_DESC_COUNTER(VCPU, store_access_exits), }; const struct kvm_stats_header kvm_vcpu_stats_header = { diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c index ea4ddf0bee7af..e992b2870cc02 100644 --- a/arch/riscv/kvm/vcpu_exit.c +++ b/arch/riscv/kvm/vcpu_exit.c @@ -195,22 +195,27 @@ int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, switch (trap->scause) { case EXC_INST_ILLEGAL: kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_ILLEGAL_INSN); + vcpu->stat.instr_illegal_exits++; ret = vcpu_redirect(vcpu, trap); break; case EXC_LOAD_MISALIGNED: kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_MISALIGNED_LOAD); + vcpu->stat.load_misaligned_exits++; ret = vcpu_redirect(vcpu, trap); break; case EXC_STORE_MISALIGNED: kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_MISALIGNED_STORE); + vcpu->stat.store_misaligned_exits++; ret = vcpu_redirect(vcpu, trap); break; case EXC_LOAD_ACCESS: kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_ACCESS_LOAD); + vcpu->stat.load_access_exits++; ret = vcpu_redirect(vcpu, trap); break; case EXC_STORE_ACCESS: kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_ACCESS_STORE); + vcpu->stat.store_access_exits++; ret = vcpu_redirect(vcpu, trap); break; case EXC_INST_ACCESS: