-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RISC-V: KVM: Add SBI HSM extension in KVM
SBI HSM extension allows OS to start/stop harts any time. It also allows ordered booting of harts instead of random booting. Implement SBI HSM exntesion and designate the vcpu 0 as the boot vcpu id. All other non-zero non-booting vcpus should be brought up by the OS implementing HSM extension. If the guest OS doesn't implement HSM extension, only single vcpu will be available to OS. Signed-off-by: Atish Patra <atish.patra@wdc.com> Signed-off-by: Atish Patra <atishp@rivosinc.com> Signed-off-by: Anup Patel <anup.patel@wdc.com>
- Loading branch information
Atish Patra
authored and
Anup Patel
committed
Jan 6, 2022
1 parent
5f862df
commit 3e1d865
Showing
5 changed files
with
134 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Copyright (c) 2021 Western Digital Corporation or its affiliates. | ||
* | ||
* Authors: | ||
* Atish Patra <atish.patra@wdc.com> | ||
*/ | ||
|
||
#include <linux/errno.h> | ||
#include <linux/err.h> | ||
#include <linux/kvm_host.h> | ||
#include <asm/csr.h> | ||
#include <asm/sbi.h> | ||
#include <asm/kvm_vcpu_sbi.h> | ||
|
||
static int kvm_sbi_hsm_vcpu_start(struct kvm_vcpu *vcpu) | ||
{ | ||
struct kvm_cpu_context *reset_cntx; | ||
struct kvm_cpu_context *cp = &vcpu->arch.guest_context; | ||
struct kvm_vcpu *target_vcpu; | ||
unsigned long target_vcpuid = cp->a0; | ||
|
||
target_vcpu = kvm_get_vcpu_by_id(vcpu->kvm, target_vcpuid); | ||
if (!target_vcpu) | ||
return -EINVAL; | ||
if (!target_vcpu->arch.power_off) | ||
return -EALREADY; | ||
|
||
reset_cntx = &target_vcpu->arch.guest_reset_context; | ||
/* start address */ | ||
reset_cntx->sepc = cp->a1; | ||
/* target vcpu id to start */ | ||
reset_cntx->a0 = target_vcpuid; | ||
/* private data passed from kernel */ | ||
reset_cntx->a1 = cp->a2; | ||
kvm_make_request(KVM_REQ_VCPU_RESET, target_vcpu); | ||
|
||
kvm_riscv_vcpu_power_on(target_vcpu); | ||
|
||
return 0; | ||
} | ||
|
||
static int kvm_sbi_hsm_vcpu_stop(struct kvm_vcpu *vcpu) | ||
{ | ||
if (vcpu->arch.power_off) | ||
return -EINVAL; | ||
|
||
kvm_riscv_vcpu_power_off(vcpu); | ||
|
||
return 0; | ||
} | ||
|
||
static int kvm_sbi_hsm_vcpu_get_status(struct kvm_vcpu *vcpu) | ||
{ | ||
struct kvm_cpu_context *cp = &vcpu->arch.guest_context; | ||
unsigned long target_vcpuid = cp->a0; | ||
struct kvm_vcpu *target_vcpu; | ||
|
||
target_vcpu = kvm_get_vcpu_by_id(vcpu->kvm, target_vcpuid); | ||
if (!target_vcpu) | ||
return -EINVAL; | ||
if (!target_vcpu->arch.power_off) | ||
return SBI_HSM_HART_STATUS_STARTED; | ||
else | ||
return SBI_HSM_HART_STATUS_STOPPED; | ||
} | ||
|
||
static int kvm_sbi_ext_hsm_handler(struct kvm_vcpu *vcpu, struct kvm_run *run, | ||
unsigned long *out_val, | ||
struct kvm_cpu_trap *utrap, | ||
bool *exit) | ||
{ | ||
int ret = 0; | ||
struct kvm_cpu_context *cp = &vcpu->arch.guest_context; | ||
struct kvm *kvm = vcpu->kvm; | ||
unsigned long funcid = cp->a6; | ||
|
||
switch (funcid) { | ||
case SBI_EXT_HSM_HART_START: | ||
mutex_lock(&kvm->lock); | ||
ret = kvm_sbi_hsm_vcpu_start(vcpu); | ||
mutex_unlock(&kvm->lock); | ||
break; | ||
case SBI_EXT_HSM_HART_STOP: | ||
ret = kvm_sbi_hsm_vcpu_stop(vcpu); | ||
break; | ||
case SBI_EXT_HSM_HART_STATUS: | ||
ret = kvm_sbi_hsm_vcpu_get_status(vcpu); | ||
if (ret >= 0) { | ||
*out_val = ret; | ||
ret = 0; | ||
} | ||
break; | ||
default: | ||
ret = -EOPNOTSUPP; | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm = { | ||
.extid_start = SBI_EXT_HSM, | ||
.extid_end = SBI_EXT_HSM, | ||
.handler = kvm_sbi_ext_hsm_handler, | ||
}; |