cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vcpu_sbi_hsm.c (2764B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2021 Western Digital Corporation or its affiliates.
      4 *
      5 * Authors:
      6 *     Atish Patra <atish.patra@wdc.com>
      7 */
      8
      9#include <linux/errno.h>
     10#include <linux/err.h>
     11#include <linux/kvm_host.h>
     12#include <asm/csr.h>
     13#include <asm/sbi.h>
     14#include <asm/kvm_vcpu_sbi.h>
     15
     16static int kvm_sbi_hsm_vcpu_start(struct kvm_vcpu *vcpu)
     17{
     18	struct kvm_cpu_context *reset_cntx;
     19	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
     20	struct kvm_vcpu *target_vcpu;
     21	unsigned long target_vcpuid = cp->a0;
     22
     23	target_vcpu = kvm_get_vcpu_by_id(vcpu->kvm, target_vcpuid);
     24	if (!target_vcpu)
     25		return -EINVAL;
     26	if (!target_vcpu->arch.power_off)
     27		return -EALREADY;
     28
     29	reset_cntx = &target_vcpu->arch.guest_reset_context;
     30	/* start address */
     31	reset_cntx->sepc = cp->a1;
     32	/* target vcpu id to start */
     33	reset_cntx->a0 = target_vcpuid;
     34	/* private data passed from kernel */
     35	reset_cntx->a1 = cp->a2;
     36	kvm_make_request(KVM_REQ_VCPU_RESET, target_vcpu);
     37
     38	kvm_riscv_vcpu_power_on(target_vcpu);
     39
     40	return 0;
     41}
     42
     43static int kvm_sbi_hsm_vcpu_stop(struct kvm_vcpu *vcpu)
     44{
     45	if (vcpu->arch.power_off)
     46		return -EINVAL;
     47
     48	kvm_riscv_vcpu_power_off(vcpu);
     49
     50	return 0;
     51}
     52
     53static int kvm_sbi_hsm_vcpu_get_status(struct kvm_vcpu *vcpu)
     54{
     55	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
     56	unsigned long target_vcpuid = cp->a0;
     57	struct kvm_vcpu *target_vcpu;
     58
     59	target_vcpu = kvm_get_vcpu_by_id(vcpu->kvm, target_vcpuid);
     60	if (!target_vcpu)
     61		return -EINVAL;
     62	if (!target_vcpu->arch.power_off)
     63		return SBI_HSM_STATE_STARTED;
     64	else if (vcpu->stat.generic.blocking)
     65		return SBI_HSM_STATE_SUSPENDED;
     66	else
     67		return SBI_HSM_STATE_STOPPED;
     68}
     69
     70static int kvm_sbi_ext_hsm_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
     71				   unsigned long *out_val,
     72				   struct kvm_cpu_trap *utrap,
     73				   bool *exit)
     74{
     75	int ret = 0;
     76	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
     77	struct kvm *kvm = vcpu->kvm;
     78	unsigned long funcid = cp->a6;
     79
     80	switch (funcid) {
     81	case SBI_EXT_HSM_HART_START:
     82		mutex_lock(&kvm->lock);
     83		ret = kvm_sbi_hsm_vcpu_start(vcpu);
     84		mutex_unlock(&kvm->lock);
     85		break;
     86	case SBI_EXT_HSM_HART_STOP:
     87		ret = kvm_sbi_hsm_vcpu_stop(vcpu);
     88		break;
     89	case SBI_EXT_HSM_HART_STATUS:
     90		ret = kvm_sbi_hsm_vcpu_get_status(vcpu);
     91		if (ret >= 0) {
     92			*out_val = ret;
     93			ret = 0;
     94		}
     95		break;
     96	case SBI_EXT_HSM_HART_SUSPEND:
     97		switch (cp->a0) {
     98		case SBI_HSM_SUSPEND_RET_DEFAULT:
     99			kvm_riscv_vcpu_wfi(vcpu);
    100			break;
    101		case SBI_HSM_SUSPEND_NON_RET_DEFAULT:
    102			ret = -EOPNOTSUPP;
    103			break;
    104		default:
    105			ret = -EINVAL;
    106		}
    107		break;
    108	default:
    109		ret = -EOPNOTSUPP;
    110	}
    111
    112	return ret;
    113}
    114
    115const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm = {
    116	.extid_start = SBI_EXT_HSM,
    117	.extid_end = SBI_EXT_HSM,
    118	.handler = kvm_sbi_ext_hsm_handler,
    119};