diff options
Diffstat (limited to 'arch/loongarch/kvm/vm.c')
| -rw-r--r-- | arch/loongarch/kvm/vm.c | 73 |
1 files changed, 44 insertions, 29 deletions
diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c index edccfc8c9cd8..1317c718f896 100644 --- a/arch/loongarch/kvm/vm.c +++ b/arch/loongarch/kvm/vm.c @@ -6,10 +6,11 @@ #include <linux/kvm_host.h> #include <asm/kvm_mmu.h> #include <asm/kvm_vcpu.h> +#include <asm/kvm_csr.h> #include <asm/kvm_eiointc.h> #include <asm/kvm_pch_pic.h> -const struct _kvm_stats_desc kvm_vm_stats_desc[] = { +const struct kvm_stats_desc kvm_vm_stats_desc[] = { KVM_GENERIC_VM_STATS(), STATS_DESC_ICOUNTER(VM, pages), STATS_DESC_ICOUNTER(VM, hugepages), @@ -24,6 +25,40 @@ const struct kvm_stats_header kvm_vm_stats_header = { sizeof(kvm_vm_stats_desc), }; +static void kvm_vm_init_features(struct kvm *kvm) +{ + unsigned long val; + + if (cpu_has_lsx) + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_LSX); + if (cpu_has_lasx) + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_LASX); + if (cpu_has_lbt_x86) + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_X86BT); + if (cpu_has_lbt_arm) + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_ARMBT); + if (cpu_has_lbt_mips) + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_MIPSBT); + if (cpu_has_ptw) + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PTW); + if (cpu_has_msgint) + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_MSGINT); + + val = read_csr_gcfg(); + if (val & CSR_GCFG_GPMP) + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU); + + /* Enable all PV features by default */ + kvm->arch.pv_features |= BIT(KVM_FEATURE_IPI); + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_IPI); + if (kvm_pvtime_supported()) { + kvm->arch.pv_features |= BIT(KVM_FEATURE_PREEMPT); + kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME); + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_PREEMPT); + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_STEALTIME); + } +} + int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) { int i; @@ -33,7 +68,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) if (!kvm->arch.pgd) return -ENOMEM; - kvm->arch.phyid_map = kvzalloc(sizeof(struct kvm_phyid_map), GFP_KERNEL_ACCOUNT); + kvm->arch.phyid_map = kvzalloc_obj(struct kvm_phyid_map, + GFP_KERNEL_ACCOUNT); if (!kvm->arch.phyid_map) { free_page((unsigned long)kvm->arch.pgd); kvm->arch.pgd = NULL; @@ -42,11 +78,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) spin_lock_init(&kvm->arch.phyid_map_lock); kvm_init_vmcs(kvm); - - /* Enable all PV features by default */ - kvm->arch.pv_features = BIT(KVM_FEATURE_IPI); - if (kvm_pvtime_supported()) - kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME); + kvm_vm_init_features(kvm); /* * cpu_vabits means user address space only (a half of total). @@ -86,7 +118,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ONE_REG: case KVM_CAP_ENABLE_CAP: case KVM_CAP_READONLY_MEM: - case KVM_CAP_SYNC_MMU: case KVM_CAP_IMMEDIATE_EXIT: case KVM_CAP_IOEVENTFD: case KVM_CAP_MP_STATE: @@ -94,7 +125,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = 1; break; case KVM_CAP_NR_VCPUS: - r = num_online_cpus(); + r = min_t(unsigned int, num_online_cpus(), KVM_MAX_VCPUS); break; case KVM_CAP_MAX_VCPUS: r = KVM_MAX_VCPUS; @@ -117,33 +148,17 @@ static int kvm_vm_feature_has_attr(struct kvm *kvm, struct kvm_device_attr *attr { switch (attr->attr) { case KVM_LOONGARCH_VM_FEAT_LSX: - if (cpu_has_lsx) - return 0; - return -ENXIO; case KVM_LOONGARCH_VM_FEAT_LASX: - if (cpu_has_lasx) - return 0; - return -ENXIO; case KVM_LOONGARCH_VM_FEAT_X86BT: - if (cpu_has_lbt_x86) - return 0; - return -ENXIO; case KVM_LOONGARCH_VM_FEAT_ARMBT: - if (cpu_has_lbt_arm) - return 0; - return -ENXIO; case KVM_LOONGARCH_VM_FEAT_MIPSBT: - if (cpu_has_lbt_mips) - return 0; - return -ENXIO; + case KVM_LOONGARCH_VM_FEAT_PTW: + case KVM_LOONGARCH_VM_FEAT_MSGINT: case KVM_LOONGARCH_VM_FEAT_PMU: - if (cpu_has_pmp) - return 0; - return -ENXIO; case KVM_LOONGARCH_VM_FEAT_PV_IPI: - return 0; + case KVM_LOONGARCH_VM_FEAT_PV_PREEMPT: case KVM_LOONGARCH_VM_FEAT_PV_STEALTIME: - if (kvm_pvtime_supported()) + if (kvm_vm_support(&kvm->arch, attr->attr)) return 0; return -ENXIO; default: |
