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