1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2020-2023 Loongson Technology Corporation Limited 4 */ 5 6 #include <linux/kvm_host.h> 7 #include <asm/kvm_mmu.h> 8 #include <asm/kvm_vcpu.h> 9 #include <asm/kvm_csr.h> 10 #include <asm/kvm_eiointc.h> 11 #include <asm/kvm_pch_pic.h> 12 13 const struct kvm_stats_desc kvm_vm_stats_desc[] = { 14 KVM_GENERIC_VM_STATS(), 15 STATS_DESC_ICOUNTER(VM, pages), 16 STATS_DESC_ICOUNTER(VM, hugepages), 17 }; 18 19 const struct kvm_stats_header kvm_vm_stats_header = { 20 .name_size = KVM_STATS_NAME_SIZE, 21 .num_desc = ARRAY_SIZE(kvm_vm_stats_desc), 22 .id_offset = sizeof(struct kvm_stats_header), 23 .desc_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE, 24 .data_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE + 25 sizeof(kvm_vm_stats_desc), 26 }; 27 28 static void kvm_vm_init_features(struct kvm *kvm) 29 { 30 unsigned long val; 31 32 if (cpu_has_lsx) 33 kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_LSX); 34 if (cpu_has_lasx) 35 kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_LASX); 36 if (cpu_has_lbt_x86) 37 kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_X86BT); 38 if (cpu_has_lbt_arm) 39 kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_ARMBT); 40 if (cpu_has_lbt_mips) 41 kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_MIPSBT); 42 if (cpu_has_ptw) 43 kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PTW); 44 if (cpu_has_msgint) 45 kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_MSGINT); 46 47 val = read_csr_gcfg(); 48 if (val & CSR_GCFG_GPMP) 49 kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU); 50 51 /* Enable all PV features by default */ 52 kvm->arch.pv_features |= BIT(KVM_FEATURE_IPI); 53 kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_IPI); 54 if (kvm_pvtime_supported()) { 55 kvm->arch.pv_features |= BIT(KVM_FEATURE_PREEMPT); 56 kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME); 57 kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_PREEMPT); 58 kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_STEALTIME); 59 } 60 } 61 62 int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) 63 { 64 int i; 65 66 /* Allocate page table to map GPA -> RPA */ 67 kvm->arch.pgd = kvm_pgd_alloc(); 68 if (!kvm->arch.pgd) 69 return -ENOMEM; 70 71 kvm->arch.phyid_map = kvzalloc_obj(struct kvm_phyid_map, 72 GFP_KERNEL_ACCOUNT); 73 if (!kvm->arch.phyid_map) { 74 free_page((unsigned long)kvm->arch.pgd); 75 kvm->arch.pgd = NULL; 76 return -ENOMEM; 77 } 78 spin_lock_init(&kvm->arch.phyid_map_lock); 79 spin_lock_init(&kvm->arch.pv_setting_lock); 80 81 kvm_init_vmcs(kvm); 82 kvm_vm_init_features(kvm); 83 84 /* 85 * cpu_vabits means user address space only (a half of total). 86 * GPA size of VM is the same with the size of user address space. 87 */ 88 kvm->arch.gpa_size = BIT(cpu_vabits); 89 kvm->arch.root_level = CONFIG_PGTABLE_LEVELS - 1; 90 kvm->arch.invalid_ptes[0] = 0; 91 kvm->arch.invalid_ptes[1] = (unsigned long)invalid_pte_table; 92 #if CONFIG_PGTABLE_LEVELS > 2 93 kvm->arch.invalid_ptes[2] = (unsigned long)invalid_pmd_table; 94 #endif 95 #if CONFIG_PGTABLE_LEVELS > 3 96 kvm->arch.invalid_ptes[3] = (unsigned long)invalid_pud_table; 97 #endif 98 for (i = 0; i <= kvm->arch.root_level; i++) 99 kvm->arch.pte_shifts[i] = PAGE_SHIFT + i * (PAGE_SHIFT - 3); 100 101 return 0; 102 } 103 104 void kvm_arch_destroy_vm(struct kvm *kvm) 105 { 106 kvm_destroy_vcpus(kvm); 107 free_page((unsigned long)kvm->arch.pgd); 108 kvm->arch.pgd = NULL; 109 kvfree(kvm->arch.phyid_map); 110 kvm->arch.phyid_map = NULL; 111 } 112 113 int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) 114 { 115 int r; 116 117 switch (ext) { 118 case KVM_CAP_IRQCHIP: 119 case KVM_CAP_ONE_REG: 120 case KVM_CAP_ENABLE_CAP: 121 case KVM_CAP_READONLY_MEM: 122 case KVM_CAP_IMMEDIATE_EXIT: 123 case KVM_CAP_IOEVENTFD: 124 case KVM_CAP_MP_STATE: 125 case KVM_CAP_SET_GUEST_DEBUG: 126 case KVM_CAP_VCPU_ATTRIBUTES: 127 r = 1; 128 break; 129 case KVM_CAP_NR_VCPUS: 130 r = min_t(unsigned int, num_online_cpus(), KVM_MAX_VCPUS); 131 break; 132 case KVM_CAP_MAX_VCPUS: 133 r = KVM_MAX_VCPUS; 134 break; 135 case KVM_CAP_MAX_VCPU_ID: 136 r = KVM_MAX_VCPU_IDS; 137 break; 138 case KVM_CAP_NR_MEMSLOTS: 139 r = KVM_USER_MEM_SLOTS; 140 break; 141 case KVM_CAP_STEAL_TIME: 142 r = kvm_pvtime_supported(); 143 break; 144 default: 145 r = 0; 146 break; 147 } 148 149 return r; 150 } 151 152 static int kvm_vm_feature_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) 153 { 154 switch (attr->attr) { 155 case KVM_LOONGARCH_VM_FEAT_LSX: 156 case KVM_LOONGARCH_VM_FEAT_LASX: 157 case KVM_LOONGARCH_VM_FEAT_X86BT: 158 case KVM_LOONGARCH_VM_FEAT_ARMBT: 159 case KVM_LOONGARCH_VM_FEAT_MIPSBT: 160 case KVM_LOONGARCH_VM_FEAT_PTW: 161 case KVM_LOONGARCH_VM_FEAT_MSGINT: 162 case KVM_LOONGARCH_VM_FEAT_PMU: 163 case KVM_LOONGARCH_VM_FEAT_PV_IPI: 164 case KVM_LOONGARCH_VM_FEAT_PV_PREEMPT: 165 case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME: 166 if (kvm_vm_support(&kvm->arch, attr->attr)) 167 return 0; 168 return -ENXIO; 169 default: 170 return -ENXIO; 171 } 172 } 173 174 static int kvm_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) 175 { 176 switch (attr->group) { 177 case KVM_LOONGARCH_VM_FEAT_CTRL: 178 return kvm_vm_feature_has_attr(kvm, attr); 179 default: 180 return -ENXIO; 181 } 182 } 183 184 int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) 185 { 186 void __user *argp = (void __user *)arg; 187 struct kvm *kvm = filp->private_data; 188 struct kvm_device_attr attr; 189 190 switch (ioctl) { 191 case KVM_CREATE_IRQCHIP: 192 return 0; 193 case KVM_HAS_DEVICE_ATTR: 194 if (copy_from_user(&attr, argp, sizeof(attr))) 195 return -EFAULT; 196 197 return kvm_vm_has_attr(kvm, &attr); 198 default: 199 return -ENOIOCTLCMD; 200 } 201 } 202 203 int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event, bool line_status) 204 { 205 if (!kvm_arch_irqchip_in_kernel(kvm)) 206 return -ENXIO; 207 208 irq_event->status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 209 irq_event->irq, irq_event->level, line_status); 210 211 return 0; 212 } 213 214 bool kvm_arch_irqchip_in_kernel(struct kvm *kvm) 215 { 216 return (kvm->arch.ipi && kvm->arch.eiointc && kvm->arch.pch_pic); 217 } 218