/** * kvm_arch_init_vm - initializes a VM data structure * @kvm: pointer to the KVM struct */ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) { int ret = 0; if (type) return -EINVAL; ret = kvm_alloc_stage2_pgd(kvm); if (ret) goto out_fail_alloc; ret = create_hyp_mappings(kvm, kvm + 1); if (ret) goto out_free_stage2_pgd; kvm_vgic_early_init(kvm); kvm_timer_init(kvm); /* Mark the initial VMID generation invalid */ kvm->arch.vmid_gen = 0; /* The maximum number of VCPUs is limited by the host's GIC model */ kvm->arch.max_vcpus = kvm_vgic_get_max_vcpus(); return ret; out_free_stage2_pgd: kvm_free_stage2_pgd(kvm); out_fail_alloc: return ret; }
/* * Called on entry to KVM_RUN unless this vcpu previously ran at least * once and the most recent prior KVM_RUN for this vcpu was called from * the same task as current (highly likely). * * This is guaranteed to execute before kvm_arch_vcpu_load_fp(vcpu), * such that on entering hyp the relevant parts of current are already * mapped. */ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu) { int ret; struct thread_info *ti = ¤t->thread_info; struct user_fpsimd_state *fpsimd = ¤t->thread.uw.fpsimd_state; /* * Make sure the host task thread flags and fpsimd state are * visible to hyp: */ ret = create_hyp_mappings(ti, ti + 1, PAGE_HYP); if (ret) goto error; ret = create_hyp_mappings(fpsimd, fpsimd + 1, PAGE_HYP); if (ret) goto error; vcpu->arch.host_thread_info = kern_hyp_va(ti); vcpu->arch.host_fpsimd_state = kern_hyp_va(fpsimd); error: return ret; }
/** * kvm_arch_init_vm - initializes a VM data structure * @kvm: pointer to the KVM struct */ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) { int ret, cpu; if (type) return -EINVAL; kvm->arch.last_vcpu_ran = alloc_percpu(typeof(*kvm->arch.last_vcpu_ran)); if (!kvm->arch.last_vcpu_ran) return -ENOMEM; for_each_possible_cpu(cpu) *per_cpu_ptr(kvm->arch.last_vcpu_ran, cpu) = -1; ret = kvm_alloc_stage2_pgd(kvm); if (ret) goto out_fail_alloc; ret = create_hyp_mappings(kvm, kvm + 1, PAGE_HYP); if (ret) goto out_free_stage2_pgd; kvm_vgic_early_init(kvm); /* Mark the initial VMID generation invalid */ kvm->arch.vmid_gen = 0; /* The maximum number of VCPUs is limited by the host's GIC model */ kvm->arch.max_vcpus = vgic_present ? kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS; return ret; out_free_stage2_pgd: kvm_free_stage2_pgd(kvm); out_fail_alloc: free_percpu(kvm->arch.last_vcpu_ran); kvm->arch.last_vcpu_ran = NULL; return ret; }
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) { int err; struct kvm_vcpu *vcpu; if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) { err = -EBUSY; goto out; } if (id >= kvm->arch.max_vcpus) { err = -EINVAL; goto out; } vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); if (!vcpu) { err = -ENOMEM; goto out; } err = kvm_vcpu_init(vcpu, kvm, id); if (err) goto free_vcpu; err = create_hyp_mappings(vcpu, vcpu + 1); if (err) goto vcpu_uninit; return vcpu; vcpu_uninit: kvm_vcpu_uninit(vcpu); free_vcpu: kmem_cache_free(kvm_vcpu_cache, vcpu); out: return ERR_PTR(err); }