vm.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2020-2023 Loongson Technology Corporation Limited
  4. */
  5. #include <linux/kvm_host.h>
  6. #include <asm/kvm_mmu.h>
  7. #include <asm/kvm_vcpu.h>
  8. const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
  9. KVM_GENERIC_VM_STATS(),
  10. STATS_DESC_ICOUNTER(VM, pages),
  11. STATS_DESC_ICOUNTER(VM, hugepages),
  12. };
  13. const struct kvm_stats_header kvm_vm_stats_header = {
  14. .name_size = KVM_STATS_NAME_SIZE,
  15. .num_desc = ARRAY_SIZE(kvm_vm_stats_desc),
  16. .id_offset = sizeof(struct kvm_stats_header),
  17. .desc_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE,
  18. .data_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE +
  19. sizeof(kvm_vm_stats_desc),
  20. };
  21. int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
  22. {
  23. int i;
  24. /* Allocate page table to map GPA -> RPA */
  25. kvm->arch.pgd = kvm_pgd_alloc();
  26. if (!kvm->arch.pgd)
  27. return -ENOMEM;
  28. kvm->arch.phyid_map = kvzalloc(sizeof(struct kvm_phyid_map), GFP_KERNEL_ACCOUNT);
  29. if (!kvm->arch.phyid_map) {
  30. free_page((unsigned long)kvm->arch.pgd);
  31. kvm->arch.pgd = NULL;
  32. return -ENOMEM;
  33. }
  34. spin_lock_init(&kvm->arch.phyid_map_lock);
  35. kvm_init_vmcs(kvm);
  36. /* Enable all PV features by default */
  37. kvm->arch.pv_features = BIT(KVM_FEATURE_IPI);
  38. if (kvm_pvtime_supported())
  39. kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME);
  40. kvm->arch.gpa_size = BIT(cpu_vabits - 1);
  41. kvm->arch.root_level = CONFIG_PGTABLE_LEVELS - 1;
  42. kvm->arch.invalid_ptes[0] = 0;
  43. kvm->arch.invalid_ptes[1] = (unsigned long)invalid_pte_table;
  44. #if CONFIG_PGTABLE_LEVELS > 2
  45. kvm->arch.invalid_ptes[2] = (unsigned long)invalid_pmd_table;
  46. #endif
  47. #if CONFIG_PGTABLE_LEVELS > 3
  48. kvm->arch.invalid_ptes[3] = (unsigned long)invalid_pud_table;
  49. #endif
  50. for (i = 0; i <= kvm->arch.root_level; i++)
  51. kvm->arch.pte_shifts[i] = PAGE_SHIFT + i * (PAGE_SHIFT - 3);
  52. return 0;
  53. }
  54. void kvm_arch_destroy_vm(struct kvm *kvm)
  55. {
  56. kvm_destroy_vcpus(kvm);
  57. free_page((unsigned long)kvm->arch.pgd);
  58. kvm->arch.pgd = NULL;
  59. kvfree(kvm->arch.phyid_map);
  60. kvm->arch.phyid_map = NULL;
  61. }
  62. int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
  63. {
  64. int r;
  65. switch (ext) {
  66. case KVM_CAP_ONE_REG:
  67. case KVM_CAP_ENABLE_CAP:
  68. case KVM_CAP_READONLY_MEM:
  69. case KVM_CAP_SYNC_MMU:
  70. case KVM_CAP_IMMEDIATE_EXIT:
  71. case KVM_CAP_IOEVENTFD:
  72. case KVM_CAP_MP_STATE:
  73. case KVM_CAP_SET_GUEST_DEBUG:
  74. r = 1;
  75. break;
  76. case KVM_CAP_NR_VCPUS:
  77. r = num_online_cpus();
  78. break;
  79. case KVM_CAP_MAX_VCPUS:
  80. r = KVM_MAX_VCPUS;
  81. break;
  82. case KVM_CAP_MAX_VCPU_ID:
  83. r = KVM_MAX_VCPU_IDS;
  84. break;
  85. case KVM_CAP_NR_MEMSLOTS:
  86. r = KVM_USER_MEM_SLOTS;
  87. break;
  88. default:
  89. r = 0;
  90. break;
  91. }
  92. return r;
  93. }
  94. static int kvm_vm_feature_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
  95. {
  96. switch (attr->attr) {
  97. case KVM_LOONGARCH_VM_FEAT_LSX:
  98. if (cpu_has_lsx)
  99. return 0;
  100. return -ENXIO;
  101. case KVM_LOONGARCH_VM_FEAT_LASX:
  102. if (cpu_has_lasx)
  103. return 0;
  104. return -ENXIO;
  105. case KVM_LOONGARCH_VM_FEAT_X86BT:
  106. if (cpu_has_lbt_x86)
  107. return 0;
  108. return -ENXIO;
  109. case KVM_LOONGARCH_VM_FEAT_ARMBT:
  110. if (cpu_has_lbt_arm)
  111. return 0;
  112. return -ENXIO;
  113. case KVM_LOONGARCH_VM_FEAT_MIPSBT:
  114. if (cpu_has_lbt_mips)
  115. return 0;
  116. return -ENXIO;
  117. case KVM_LOONGARCH_VM_FEAT_PMU:
  118. if (cpu_has_pmp)
  119. return 0;
  120. return -ENXIO;
  121. case KVM_LOONGARCH_VM_FEAT_PV_IPI:
  122. return 0;
  123. case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME:
  124. if (kvm_pvtime_supported())
  125. return 0;
  126. return -ENXIO;
  127. default:
  128. return -ENXIO;
  129. }
  130. }
  131. static int kvm_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
  132. {
  133. switch (attr->group) {
  134. case KVM_LOONGARCH_VM_FEAT_CTRL:
  135. return kvm_vm_feature_has_attr(kvm, attr);
  136. default:
  137. return -ENXIO;
  138. }
  139. }
  140. int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
  141. {
  142. void __user *argp = (void __user *)arg;
  143. struct kvm *kvm = filp->private_data;
  144. struct kvm_device_attr attr;
  145. switch (ioctl) {
  146. case KVM_HAS_DEVICE_ATTR:
  147. if (copy_from_user(&attr, argp, sizeof(attr)))
  148. return -EFAULT;
  149. return kvm_vm_has_attr(kvm, &attr);
  150. default:
  151. return -ENOIOCTLCMD;
  152. }
  153. }