Skip to content

Commit 5b9db9c

Browse files
radimkrcmaravpatel
authored andcommitted
RISC-V: KVM: add KVM_CAP_RISCV_MP_STATE_RESET
Add a toggleable VM capability to reset the VCPU from userspace by setting MP_STATE_INIT_RECEIVED through IOCTL. Reset through a mp_state to avoid adding a new IOCTL. Do not reset on a transition from STOPPED to RUNNABLE, because it's better to avoid side effects that would complicate userspace adoption. The MP_STATE_INIT_RECEIVED is not a permanent mp_state -- IOCTL resets the VCPU while preserving the original mp_state -- because we wouldn't gain much from having a new state it in the rest of KVM, but it's a very non-standard use of the IOCTL. Signed-off-by: Radim Krčmář <rkrcmar@ventanamicro.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://lore.kernel.org/r/20250515143723.2450630-5-rkrcmar@ventanamicro.com Signed-off-by: Anup Patel <anup@brainfault.org>
1 parent 5bc4097 commit 5b9db9c

File tree

7 files changed

+60
-13
lines changed

7 files changed

+60
-13
lines changed

Documentation/virt/kvm/api.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8496,6 +8496,17 @@ aforementioned registers before the first KVM_RUN. These registers are VM
84968496
scoped, meaning that the same set of values are presented on all vCPUs in a
84978497
given VM.
84988498

8499+
7.43 KVM_CAP_RISCV_MP_STATE_RESET
8500+
---------------------------------
8501+
8502+
:Architectures: riscv
8503+
:Type: VM
8504+
:Parameters: None
8505+
:Returns: 0 on success, -EINVAL if arg[0] is not zero
8506+
8507+
When this capability is enabled, KVM resets the VCPU when setting
8508+
MP_STATE_INIT_RECEIVED through IOCTL. The original MP_STATE is preserved.
8509+
84998510
8. Other capabilities.
85008511
======================
85018512

arch/riscv/include/asm/kvm_host.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ struct kvm_arch {
119119

120120
/* AIA Guest/VM context */
121121
struct kvm_aia aia;
122+
123+
/* KVM_CAP_RISCV_MP_STATE_RESET */
124+
bool mp_state_reset;
122125
};
123126

124127
struct kvm_cpu_trap {

arch/riscv/include/asm/kvm_vcpu_sbi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu,
5757
u32 type, u64 flags);
5858
void kvm_riscv_vcpu_sbi_request_reset(struct kvm_vcpu *vcpu,
5959
unsigned long pc, unsigned long a1);
60+
void kvm_riscv_vcpu_sbi_load_reset_state(struct kvm_vcpu *vcpu);
6061
int kvm_riscv_vcpu_sbi_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
6162
int kvm_riscv_vcpu_set_reg_sbi_ext(struct kvm_vcpu *vcpu,
6263
const struct kvm_one_reg *reg);

arch/riscv/kvm/vcpu.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ const struct kvm_stats_header kvm_vcpu_stats_header = {
5151
sizeof(kvm_vcpu_stats_desc),
5252
};
5353

54-
static void kvm_riscv_vcpu_context_reset(struct kvm_vcpu *vcpu)
54+
static void kvm_riscv_vcpu_context_reset(struct kvm_vcpu *vcpu,
55+
bool kvm_sbi_reset)
5556
{
5657
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
5758
struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
58-
struct kvm_vcpu_reset_state *reset_state = &vcpu->arch.reset_state;
5959
void *vector_datap = cntx->vector.datap;
6060

6161
memset(cntx, 0, sizeof(*cntx));
@@ -65,13 +65,8 @@ static void kvm_riscv_vcpu_context_reset(struct kvm_vcpu *vcpu)
6565
/* Restore datap as it's not a part of the guest context. */
6666
cntx->vector.datap = vector_datap;
6767

68-
/* Load SBI reset values */
69-
cntx->a0 = vcpu->vcpu_id;
70-
71-
spin_lock(&reset_state->lock);
72-
cntx->sepc = reset_state->pc;
73-
cntx->a1 = reset_state->a1;
74-
spin_unlock(&reset_state->lock);
68+
if (kvm_sbi_reset)
69+
kvm_riscv_vcpu_sbi_load_reset_state(vcpu);
7570

7671
/* Setup reset state of shadow SSTATUS and HSTATUS CSRs */
7772
cntx->sstatus = SR_SPP | SR_SPIE;
@@ -81,7 +76,7 @@ static void kvm_riscv_vcpu_context_reset(struct kvm_vcpu *vcpu)
8176
cntx->hstatus |= HSTATUS_SPV;
8277
}
8378

84-
static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
79+
static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu, bool kvm_sbi_reset)
8580
{
8681
bool loaded;
8782

@@ -97,7 +92,7 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
9792

9893
vcpu->arch.last_exit_cpu = -1;
9994

100-
kvm_riscv_vcpu_context_reset(vcpu);
95+
kvm_riscv_vcpu_context_reset(vcpu, kvm_sbi_reset);
10196

10297
kvm_riscv_vcpu_fp_reset(vcpu);
10398

@@ -174,7 +169,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
174169
kvm_riscv_vcpu_sbi_init(vcpu);
175170

176171
/* Reset VCPU */
177-
kvm_riscv_reset_vcpu(vcpu);
172+
kvm_riscv_reset_vcpu(vcpu, false);
178173

179174
return 0;
180175
}
@@ -523,6 +518,12 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
523518
case KVM_MP_STATE_STOPPED:
524519
__kvm_riscv_vcpu_power_off(vcpu);
525520
break;
521+
case KVM_MP_STATE_INIT_RECEIVED:
522+
if (vcpu->kvm->arch.mp_state_reset)
523+
kvm_riscv_reset_vcpu(vcpu, false);
524+
else
525+
ret = -EINVAL;
526+
break;
526527
default:
527528
ret = -EINVAL;
528529
}
@@ -711,7 +712,7 @@ static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu)
711712
}
712713

713714
if (kvm_check_request(KVM_REQ_VCPU_RESET, vcpu))
714-
kvm_riscv_reset_vcpu(vcpu);
715+
kvm_riscv_reset_vcpu(vcpu, true);
715716

716717
if (kvm_check_request(KVM_REQ_UPDATE_HGATP, vcpu))
717718
kvm_riscv_gstage_update_hgatp(vcpu);

arch/riscv/kvm/vcpu_sbi.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,23 @@ void kvm_riscv_vcpu_sbi_request_reset(struct kvm_vcpu *vcpu,
167167
kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
168168
}
169169

170+
void kvm_riscv_vcpu_sbi_load_reset_state(struct kvm_vcpu *vcpu)
171+
{
172+
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
173+
struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
174+
struct kvm_vcpu_reset_state *reset_state = &vcpu->arch.reset_state;
175+
176+
cntx->a0 = vcpu->vcpu_id;
177+
178+
spin_lock(&vcpu->arch.reset_state.lock);
179+
cntx->sepc = reset_state->pc;
180+
cntx->a1 = reset_state->a1;
181+
spin_unlock(&vcpu->arch.reset_state.lock);
182+
183+
cntx->sstatus &= ~SR_SIE;
184+
csr->vsatp = 0;
185+
}
186+
170187
int kvm_riscv_vcpu_sbi_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
171188
{
172189
struct kvm_cpu_context *cp = &vcpu->arch.guest_context;

arch/riscv/kvm/vm.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,19 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
209209
return r;
210210
}
211211

212+
int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
213+
{
214+
switch (cap->cap) {
215+
case KVM_CAP_RISCV_MP_STATE_RESET:
216+
if (cap->flags)
217+
return -EINVAL;
218+
kvm->arch.mp_state_reset = true;
219+
return 0;
220+
default:
221+
return -EINVAL;
222+
}
223+
}
224+
212225
int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
213226
{
214227
return -EINVAL;

include/uapi/linux/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,7 @@ struct kvm_enable_cap {
930930
#define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237
931931
#define KVM_CAP_X86_GUEST_MODE 238
932932
#define KVM_CAP_ARM_WRITABLE_IMP_ID_REGS 239
933+
#define KVM_CAP_RISCV_MP_STATE_RESET 240
933934

934935
struct kvm_irq_routing_irqchip {
935936
__u32 irqchip;

0 commit comments

Comments
 (0)