File Index
Files and directories
Sign in
FILE

vcpu_sbi_v01.c

File preview with syntax highlighting.

linux-6.19.14/arch/riscv/kvm/vcpu_sbi_v01.c C
  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/sbi.h>
 13#include <asm/kvm_vcpu_timer.h>
 14#include <asm/kvm_vcpu_sbi.h>
 15
 16static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
 17				   struct kvm_vcpu_sbi_return *retdata)
 18{
 19	ulong hmask;
 20	int i, ret = 0;
 21	u64 next_cycle;
 22	struct kvm_vcpu *rvcpu;
 23	struct kvm *kvm = vcpu->kvm;
 24	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
 25	struct kvm_cpu_trap *utrap = retdata->utrap;
 26	unsigned long vmid;
 27
 28	switch (cp->a7) {
 29	case SBI_EXT_0_1_CONSOLE_GETCHAR:
 30	case SBI_EXT_0_1_CONSOLE_PUTCHAR:
 31		/*
 32		 * The CONSOLE_GETCHAR/CONSOLE_PUTCHAR SBI calls cannot be
 33		 * handled in kernel so we forward these to user-space
 34		 */
 35		ret = kvm_riscv_vcpu_sbi_forward_handler(vcpu, run, retdata);
 36		break;
 37	case SBI_EXT_0_1_SET_TIMER:
 38#if __riscv_xlen == 32
 39		next_cycle = ((u64)cp->a1 << 32) | (u64)cp->a0;
 40#else
 41		next_cycle = (u64)cp->a0;
 42#endif
 43		ret = kvm_riscv_vcpu_timer_next_event(vcpu, next_cycle);
 44		break;
 45	case SBI_EXT_0_1_CLEAR_IPI:
 46		ret = kvm_riscv_vcpu_unset_interrupt(vcpu, IRQ_VS_SOFT);
 47		break;
 48	case SBI_EXT_0_1_SEND_IPI:
 49		if (cp->a0)
 50			hmask = kvm_riscv_vcpu_unpriv_read(vcpu, false, cp->a0, utrap);
 51		else
 52			hmask = (1UL << atomic_read(&kvm->online_vcpus)) - 1;
 53		if (utrap->scause)
 54			break;
 55
 56		for_each_set_bit(i, &hmask, BITS_PER_LONG) {
 57			rvcpu = kvm_get_vcpu_by_id(vcpu->kvm, i);
 58			ret = kvm_riscv_vcpu_set_interrupt(rvcpu, IRQ_VS_SOFT);
 59			if (ret < 0)
 60				break;
 61		}
 62		break;
 63	case SBI_EXT_0_1_SHUTDOWN:
 64		kvm_riscv_vcpu_sbi_system_reset(vcpu, run,
 65						KVM_SYSTEM_EVENT_SHUTDOWN, 0);
 66		retdata->uexit = true;
 67		break;
 68	case SBI_EXT_0_1_REMOTE_FENCE_I:
 69	case SBI_EXT_0_1_REMOTE_SFENCE_VMA:
 70	case SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID:
 71		if (cp->a0)
 72			hmask = kvm_riscv_vcpu_unpriv_read(vcpu, false, cp->a0, utrap);
 73		else
 74			hmask = (1UL << atomic_read(&kvm->online_vcpus)) - 1;
 75		if (utrap->scause)
 76			break;
 77
 78		if (cp->a7 == SBI_EXT_0_1_REMOTE_FENCE_I)
 79			kvm_riscv_fence_i(vcpu->kvm, 0, hmask);
 80		else if (cp->a7 == SBI_EXT_0_1_REMOTE_SFENCE_VMA) {
 81			vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid);
 82			if (cp->a1 == 0 && cp->a2 == 0)
 83				kvm_riscv_hfence_vvma_all(vcpu->kvm, 0, hmask, vmid);
 84			else
 85				kvm_riscv_hfence_vvma_gva(vcpu->kvm, 0, hmask, cp->a1,
 86							  cp->a2, PAGE_SHIFT, vmid);
 87		} else {
 88			vmid = READ_ONCE(vcpu->kvm->arch.vmid.vmid);
 89			if (cp->a1 == 0 && cp->a2 == 0)
 90				kvm_riscv_hfence_vvma_asid_all(vcpu->kvm, 0, hmask,
 91							       cp->a3, vmid);
 92			else
 93				kvm_riscv_hfence_vvma_asid_gva(vcpu->kvm, 0, hmask,
 94							       cp->a1, cp->a2, PAGE_SHIFT,
 95							       cp->a3, vmid);
 96		}
 97		break;
 98	default:
 99		retdata->err_val = SBI_ERR_NOT_SUPPORTED;
100		break;
101	}
102
103	return ret;
104}
105
106const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01 = {
107	.extid_start = SBI_EXT_0_1_SET_TIMER,
108	.extid_end = SBI_EXT_0_1_SHUTDOWN,
109	.handler = kvm_sbi_ext_v01_handler,
110};
~/ Read-only file preview.