FILE
vm.c
File preview with syntax highlighting.
linux-6.19.14/arch/riscv/kvm/vm.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.