File Index
Files and directories
Sign in
FILE

vm.c

File preview with syntax highlighting.

linux-6.19.14/arch/riscv/kvm/vm.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2019 Western Digital Corporation or its affiliates.
  4 *
  5 * Authors:
  6 *     Anup Patel <anup.patel@wdc.com>
  7 */
  8
  9#include <linux/errno.h>
 10#include <linux/err.h>
 11#include <linux/module.h>
 12#include <linux/uaccess.h>
 13#include <linux/kvm_host.h>
 14#include <asm/kvm_mmu.h>
 15
 16const struct kvm_stats_desc kvm_vm_stats_desc[] = {
 17	KVM_GENERIC_VM_STATS()
 18};
 19static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
 20		sizeof(struct kvm_vm_stat) / sizeof(u64));
 21
 22const struct kvm_stats_header kvm_vm_stats_header = {
 23	.name_size = KVM_STATS_NAME_SIZE,
 24	.num_desc = ARRAY_SIZE(kvm_vm_stats_desc),
 25	.id_offset =  sizeof(struct kvm_stats_header),
 26	.desc_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE,
 27	.data_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE +
 28		       sizeof(kvm_vm_stats_desc),
 29};
 30
 31int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 32{
 33	int r;
 34
 35	r = kvm_riscv_mmu_alloc_pgd(kvm);
 36	if (r)
 37		return r;
 38
 39	r = kvm_riscv_gstage_vmid_init(kvm);
 40	if (r) {
 41		kvm_riscv_mmu_free_pgd(kvm);
 42		return r;
 43	}
 44
 45	kvm_riscv_aia_init_vm(kvm);
 46
 47	kvm_riscv_guest_timer_init(kvm);
 48
 49	return 0;
 50}
 51
 52void kvm_arch_destroy_vm(struct kvm *kvm)
 53{
 54	kvm_destroy_vcpus(kvm);
 55
 56	kvm_riscv_aia_destroy_vm(kvm);
 57}
 58
 59int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irql,
 60			  bool line_status)
 61{
 62	if (!irqchip_in_kernel(kvm))
 63		return -ENXIO;
 64
 65	return kvm_riscv_aia_inject_irq(kvm, irql->irq, irql->level);
 66}
 67
 68int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
 69		struct kvm *kvm, int irq_source_id,
 70		int level, bool line_status)
 71{
 72	struct kvm_msi msi;
 73
 74	if (!level)
 75		return -1;
 76
 77	msi.address_lo = e->msi.address_lo;
 78	msi.address_hi = e->msi.address_hi;
 79	msi.data = e->msi.data;
 80	msi.flags = e->msi.flags;
 81	msi.devid = e->msi.devid;
 82
 83	return kvm_riscv_aia_inject_msi(kvm, &msi);
 84}
 85
 86static int kvm_riscv_set_irq(struct kvm_kernel_irq_routing_entry *e,
 87			     struct kvm *kvm, int irq_source_id,
 88			     int level, bool line_status)
 89{
 90	return kvm_riscv_aia_inject_irq(kvm, e->irqchip.pin, level);
 91}
 92
 93int kvm_riscv_setup_default_irq_routing(struct kvm *kvm, u32 lines)
 94{
 95	struct kvm_irq_routing_entry *ents;
 96	int i, rc;
 97
 98	ents = kcalloc(lines, sizeof(*ents), GFP_KERNEL);
 99	if (!ents)
100		return -ENOMEM;
101
102	for (i = 0; i < lines; i++) {
103		ents[i].gsi = i;
104		ents[i].type = KVM_IRQ_ROUTING_IRQCHIP;
105		ents[i].u.irqchip.irqchip = 0;
106		ents[i].u.irqchip.pin = i;
107	}
108	rc = kvm_set_irq_routing(kvm, ents, lines, 0);
109	kfree(ents);
110
111	return rc;
112}
113
114bool kvm_arch_can_set_irq_routing(struct kvm *kvm)
115{
116	return irqchip_in_kernel(kvm);
117}
118
119int kvm_set_routing_entry(struct kvm *kvm,
120			  struct kvm_kernel_irq_routing_entry *e,
121			  const struct kvm_irq_routing_entry *ue)
122{
123	int r = -EINVAL;
124
125	switch (ue->type) {
126	case KVM_IRQ_ROUTING_IRQCHIP:
127		e->set = kvm_riscv_set_irq;
128		e->irqchip.irqchip = ue->u.irqchip.irqchip;
129		e->irqchip.pin = ue->u.irqchip.pin;
130		if ((e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) ||
131		    (e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
132			goto out;
133		break;
134	case KVM_IRQ_ROUTING_MSI:
135		e->set = kvm_set_msi;
136		e->msi.address_lo = ue->u.msi.address_lo;
137		e->msi.address_hi = ue->u.msi.address_hi;
138		e->msi.data = ue->u.msi.data;
139		e->msi.flags = ue->flags;
140		e->msi.devid = ue->u.msi.devid;
141		break;
142	default:
143		goto out;
144	}
145	r = 0;
146out:
147	return r;
148}
149
150int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
151			      struct kvm *kvm, int irq_source_id, int level,
152			      bool line_status)
153{
154	if (!level)
155		return -EWOULDBLOCK;
156
157	switch (e->type) {
158	case KVM_IRQ_ROUTING_MSI:
159		return kvm_set_msi(e, kvm, irq_source_id, level, line_status);
160
161	case KVM_IRQ_ROUTING_IRQCHIP:
162		return kvm_riscv_set_irq(e, kvm, irq_source_id,
163					 level, line_status);
164	}
165
166	return -EWOULDBLOCK;
167}
168
169bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)
170{
171	return irqchip_in_kernel(kvm);
172}
173
174int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
175{
176	int r;
177
178	switch (ext) {
179	case KVM_CAP_IRQCHIP:
180		r = kvm_riscv_aia_available();
181		break;
182	case KVM_CAP_IOEVENTFD:
183	case KVM_CAP_USER_MEMORY:
184	case KVM_CAP_SYNC_MMU:
185	case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
186	case KVM_CAP_ONE_REG:
187	case KVM_CAP_READONLY_MEM:
188	case KVM_CAP_MP_STATE:
189	case KVM_CAP_IMMEDIATE_EXIT:
190	case KVM_CAP_SET_GUEST_DEBUG:
191		r = 1;
192		break;
193	case KVM_CAP_NR_VCPUS:
194		r = min_t(unsigned int, num_online_cpus(), KVM_MAX_VCPUS);
195		break;
196	case KVM_CAP_MAX_VCPUS:
197		r = KVM_MAX_VCPUS;
198		break;
199	case KVM_CAP_NR_MEMSLOTS:
200		r = KVM_USER_MEM_SLOTS;
201		break;
202	case KVM_CAP_VM_GPA_BITS:
203		r = kvm_riscv_gstage_gpa_bits;
204		break;
205	default:
206		r = 0;
207		break;
208	}
209
210	return r;
211}
212
213int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
214{
215	switch (cap->cap) {
216	case KVM_CAP_RISCV_MP_STATE_RESET:
217		if (cap->flags)
218			return -EINVAL;
219		kvm->arch.mp_state_reset = true;
220		return 0;
221	default:
222		return -EINVAL;
223	}
224}
225
226int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
227{
228	return -EINVAL;
229}
~/ Read-only file preview.