1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00
linux/arch/riscv/kvm/vcpu_sbi_system.c
Andrew Jones 351e02b173 riscv: KVM: Fix SBI sleep_type use
The spec says sleep_type is 32 bits wide and "In case the data is
defined as 32bit wide, higher privilege software must ensure that it
only uses 32 bit data." Mask off upper bits of sleep_type before
using it.

Fixes: 023c15151f ("RISC-V: KVM: Add SBI system suspend support")
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20250217084506.18763-12-ajones@ventanamicro.com
Signed-off-by: Anup Patel <anup@brainfault.org>
2025-02-17 16:28:28 +05:30

74 lines
1.7 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2024 Ventana Micro Systems Inc.
*/
#include <linux/kvm_host.h>
#include <linux/wordpart.h>
#include <asm/kvm_vcpu_sbi.h>
#include <asm/sbi.h>
static int kvm_sbi_ext_susp_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
struct kvm_vcpu_sbi_return *retdata)
{
struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
struct kvm_cpu_context *reset_cntx;
unsigned long funcid = cp->a6;
unsigned long hva, i;
struct kvm_vcpu *tmp;
switch (funcid) {
case SBI_EXT_SUSP_SYSTEM_SUSPEND:
if (lower_32_bits(cp->a0) != SBI_SUSP_SLEEP_TYPE_SUSPEND_TO_RAM) {
retdata->err_val = SBI_ERR_INVALID_PARAM;
return 0;
}
if (!(cp->sstatus & SR_SPP)) {
retdata->err_val = SBI_ERR_FAILURE;
return 0;
}
hva = kvm_vcpu_gfn_to_hva_prot(vcpu, cp->a1 >> PAGE_SHIFT, NULL);
if (kvm_is_error_hva(hva)) {
retdata->err_val = SBI_ERR_INVALID_ADDRESS;
return 0;
}
kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
if (tmp == vcpu)
continue;
if (!kvm_riscv_vcpu_stopped(tmp)) {
retdata->err_val = SBI_ERR_DENIED;
return 0;
}
}
spin_lock(&vcpu->arch.reset_cntx_lock);
reset_cntx = &vcpu->arch.guest_reset_context;
reset_cntx->sepc = cp->a1;
reset_cntx->a0 = vcpu->vcpu_id;
reset_cntx->a1 = cp->a2;
spin_unlock(&vcpu->arch.reset_cntx_lock);
kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
/* userspace provides the suspend implementation */
kvm_riscv_vcpu_sbi_forward(vcpu, run);
retdata->uexit = true;
break;
default:
retdata->err_val = SBI_ERR_NOT_SUPPORTED;
break;
}
return 0;
}
const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_susp = {
.extid_start = SBI_EXT_SUSP,
.extid_end = SBI_EXT_SUSP,
.default_disabled = true,
.handler = kvm_sbi_ext_susp_handler,
};