Skip to content

Commit 023c151

Browse files
jones-drewavpatel
authored andcommitted
RISC-V: KVM: Add SBI system suspend support
Implement a KVM SBI SUSP extension handler. The handler only validates the system suspend entry criteria and prepares for resuming in the appropriate state at the resume_addr (as specified by the SBI spec), but then it forwards the call to the VMM where any system suspend behavior may be implemented. Since VMM support is needed, KVM disables the extension by default. Signed-off-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20241017074538.18867-5-ajones@ventanamicro.com Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent fc033cf commit 023c151

File tree

5 files changed

+80
-0
lines changed

5 files changed

+80
-0
lines changed

arch/riscv/include/asm/kvm_vcpu_sbi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_rfence;
8585
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_srst;
8686
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm;
8787
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_dbcn;
88+
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_susp;
8889
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_sta;
8990
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental;
9091
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor;

arch/riscv/include/uapi/asm/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ enum KVM_RISCV_SBI_EXT_ID {
198198
KVM_RISCV_SBI_EXT_VENDOR,
199199
KVM_RISCV_SBI_EXT_DBCN,
200200
KVM_RISCV_SBI_EXT_STA,
201+
KVM_RISCV_SBI_EXT_SUSP,
201202
KVM_RISCV_SBI_EXT_MAX,
202203
};
203204

arch/riscv/kvm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ kvm-y += vcpu_sbi_hsm.o
3030
kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_sbi_pmu.o
3131
kvm-y += vcpu_sbi_replace.o
3232
kvm-y += vcpu_sbi_sta.o
33+
kvm-y += vcpu_sbi_system.o
3334
kvm-$(CONFIG_RISCV_SBI_V01) += vcpu_sbi_v01.o
3435
kvm-y += vcpu_switch.o
3536
kvm-y += vcpu_timer.o

arch/riscv/kvm/vcpu_sbi.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ static const struct kvm_riscv_sbi_extension_entry sbi_ext[] = {
7070
.ext_idx = KVM_RISCV_SBI_EXT_DBCN,
7171
.ext_ptr = &vcpu_sbi_ext_dbcn,
7272
},
73+
{
74+
.ext_idx = KVM_RISCV_SBI_EXT_SUSP,
75+
.ext_ptr = &vcpu_sbi_ext_susp,
76+
},
7377
{
7478
.ext_idx = KVM_RISCV_SBI_EXT_STA,
7579
.ext_ptr = &vcpu_sbi_ext_sta,

arch/riscv/kvm/vcpu_sbi_system.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (c) 2024 Ventana Micro Systems Inc.
4+
*/
5+
6+
#include <linux/kvm_host.h>
7+
8+
#include <asm/kvm_vcpu_sbi.h>
9+
#include <asm/sbi.h>
10+
11+
static int kvm_sbi_ext_susp_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
12+
struct kvm_vcpu_sbi_return *retdata)
13+
{
14+
struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
15+
struct kvm_cpu_context *reset_cntx;
16+
unsigned long funcid = cp->a6;
17+
unsigned long hva, i;
18+
struct kvm_vcpu *tmp;
19+
20+
switch (funcid) {
21+
case SBI_EXT_SUSP_SYSTEM_SUSPEND:
22+
if (cp->a0 != SBI_SUSP_SLEEP_TYPE_SUSPEND_TO_RAM) {
23+
retdata->err_val = SBI_ERR_INVALID_PARAM;
24+
return 0;
25+
}
26+
27+
if (!(cp->sstatus & SR_SPP)) {
28+
retdata->err_val = SBI_ERR_FAILURE;
29+
return 0;
30+
}
31+
32+
hva = kvm_vcpu_gfn_to_hva_prot(vcpu, cp->a1 >> PAGE_SHIFT, NULL);
33+
if (kvm_is_error_hva(hva)) {
34+
retdata->err_val = SBI_ERR_INVALID_ADDRESS;
35+
return 0;
36+
}
37+
38+
kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
39+
if (tmp == vcpu)
40+
continue;
41+
if (!kvm_riscv_vcpu_stopped(tmp)) {
42+
retdata->err_val = SBI_ERR_DENIED;
43+
return 0;
44+
}
45+
}
46+
47+
spin_lock(&vcpu->arch.reset_cntx_lock);
48+
reset_cntx = &vcpu->arch.guest_reset_context;
49+
reset_cntx->sepc = cp->a1;
50+
reset_cntx->a0 = vcpu->vcpu_id;
51+
reset_cntx->a1 = cp->a2;
52+
spin_unlock(&vcpu->arch.reset_cntx_lock);
53+
54+
kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
55+
56+
/* userspace provides the suspend implementation */
57+
kvm_riscv_vcpu_sbi_forward(vcpu, run);
58+
retdata->uexit = true;
59+
break;
60+
default:
61+
retdata->err_val = SBI_ERR_NOT_SUPPORTED;
62+
break;
63+
}
64+
65+
return 0;
66+
}
67+
68+
const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_susp = {
69+
.extid_start = SBI_EXT_SUSP,
70+
.extid_end = SBI_EXT_SUSP,
71+
.default_disabled = true,
72+
.handler = kvm_sbi_ext_susp_handler,
73+
};

0 commit comments

Comments
 (0)