Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/riscv/kvm/vm.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (C) 2019 Western Digital Corporation or its affiliates.
4
*
5
* Authors:
6
* Anup Patel <[email protected]>
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
16
const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
17
KVM_GENERIC_VM_STATS()
18
};
19
static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
20
sizeof(struct kvm_vm_stat) / sizeof(u64));
21
22
const 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
31
int 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
52
void kvm_arch_destroy_vm(struct kvm *kvm)
53
{
54
kvm_destroy_vcpus(kvm);
55
56
kvm_riscv_aia_destroy_vm(kvm);
57
}
58
59
int 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
68
int 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
86
static 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
93
int 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
114
bool kvm_arch_can_set_irq_routing(struct kvm *kvm)
115
{
116
return irqchip_in_kernel(kvm);
117
}
118
119
int 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;
146
out:
147
return r;
148
}
149
150
int 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
169
bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)
170
{
171
return irqchip_in_kernel(kvm);
172
}
173
174
int 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
213
int 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
226
int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
227
{
228
return -EINVAL;
229
}
230
231