Merge branch 'kvm-arm64/pkvm-6.15' into kvmarm/next
* kvm-arm64/pkvm-6.15: : pKVM updates for 6.15 : : - SecPageTable stats for stage-2 table pages allocated by the protected : hypervisor (Vincent Donnefort) : : - HCRX_EL2 trap + vCPU initialization fixes for pKVM (Fuad Tabba) KVM: arm64: Create each pKVM hyp vcpu after its corresponding host vcpu KVM: arm64: Factor out pKVM hyp vcpu creation to separate function KVM: arm64: Initialize HCRX_EL2 traps in pKVM KVM: arm64: Factor out setting HCRX_EL2 traps into separate function KVM: arm64: Count pKVM stage-2 usage in secondary pagetable stats KVM: arm64: Distinct pKVM teardown memcache for stage-2 KVM: arm64: Add flags to kvm_hyp_memcache Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
This commit is contained in:
@@ -662,4 +662,28 @@ static inline bool guest_hyp_sve_traps_enabled(const struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return __guest_hyp_cptr_xen_trap_enabled(vcpu, ZEN);
|
||||
}
|
||||
|
||||
static inline void vcpu_set_hcrx(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
|
||||
if (cpus_have_final_cap(ARM64_HAS_HCX)) {
|
||||
/*
|
||||
* In general, all HCRX_EL2 bits are gated by a feature.
|
||||
* The only reason we can set SMPME without checking any
|
||||
* feature is that its effects are not directly observable
|
||||
* from the guest.
|
||||
*/
|
||||
vcpu->arch.hcrx_el2 = HCRX_EL2_SMPME;
|
||||
|
||||
if (kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
|
||||
vcpu->arch.hcrx_el2 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
|
||||
|
||||
if (kvm_has_tcr2(kvm))
|
||||
vcpu->arch.hcrx_el2 |= HCRX_EL2_TCR2En;
|
||||
|
||||
if (kvm_has_fpmr(kvm))
|
||||
vcpu->arch.hcrx_el2 |= HCRX_EL2_EnFPM;
|
||||
}
|
||||
}
|
||||
#endif /* __ARM64_KVM_EMULATE_H__ */
|
||||
|
||||
@@ -87,6 +87,9 @@ struct kvm_hyp_memcache {
|
||||
phys_addr_t head;
|
||||
unsigned long nr_pages;
|
||||
struct pkvm_mapping *mapping; /* only used from EL1 */
|
||||
|
||||
#define HYP_MEMCACHE_ACCOUNT_STAGE2 BIT(1)
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
static inline void push_hyp_memcache(struct kvm_hyp_memcache *mc,
|
||||
@@ -247,6 +250,7 @@ typedef unsigned int pkvm_handle_t;
|
||||
struct kvm_protected_vm {
|
||||
pkvm_handle_t handle;
|
||||
struct kvm_hyp_memcache teardown_mc;
|
||||
struct kvm_hyp_memcache stage2_teardown_mc;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
@@ -902,6 +906,8 @@ struct kvm_vcpu_arch {
|
||||
#define VCPU_INITIALIZED __vcpu_single_flag(cflags, BIT(0))
|
||||
/* SVE config completed */
|
||||
#define VCPU_SVE_FINALIZED __vcpu_single_flag(cflags, BIT(1))
|
||||
/* pKVM VCPU setup completed */
|
||||
#define VCPU_PKVM_FINALIZED __vcpu_single_flag(cflags, BIT(2))
|
||||
|
||||
/* Exception pending */
|
||||
#define PENDING_EXCEPTION __vcpu_single_flag(iflags, BIT(0))
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
int pkvm_init_host_vm(struct kvm *kvm);
|
||||
int pkvm_create_hyp_vm(struct kvm *kvm);
|
||||
void pkvm_destroy_hyp_vm(struct kvm *kvm);
|
||||
int pkvm_create_hyp_vcpu(struct kvm_vcpu *vcpu);
|
||||
|
||||
/*
|
||||
* This functions as an allow-list of protected VM capabilities.
|
||||
|
||||
@@ -866,6 +866,10 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
|
||||
ret = pkvm_create_hyp_vm(kvm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pkvm_create_hyp_vcpu(vcpu);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock(&kvm->arch.config_lock);
|
||||
|
||||
@@ -56,7 +56,7 @@ void handle_host_mem_abort(struct kvm_cpu_context *host_ctxt);
|
||||
|
||||
int hyp_pin_shared_mem(void *from, void *to);
|
||||
void hyp_unpin_shared_mem(void *from, void *to);
|
||||
void reclaim_guest_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc);
|
||||
void reclaim_pgtable_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc);
|
||||
int refill_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages,
|
||||
struct kvm_hyp_memcache *host_mc);
|
||||
|
||||
|
||||
@@ -43,12 +43,6 @@ struct pkvm_hyp_vm {
|
||||
struct hyp_pool pool;
|
||||
hyp_spinlock_t lock;
|
||||
|
||||
/*
|
||||
* The number of vcpus initialized and ready to run.
|
||||
* Modifying this is protected by 'vm_table_lock'.
|
||||
*/
|
||||
unsigned int nr_vcpus;
|
||||
|
||||
/* Array of the hyp vCPU structures for this VM. */
|
||||
struct pkvm_hyp_vcpu *vcpus[];
|
||||
};
|
||||
|
||||
@@ -266,7 +266,7 @@ int kvm_guest_prepare_stage2(struct pkvm_hyp_vm *vm, void *pgd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void reclaim_guest_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc)
|
||||
void reclaim_pgtable_pages(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc)
|
||||
{
|
||||
struct hyp_page *page;
|
||||
void *addr;
|
||||
|
||||
@@ -167,8 +167,13 @@ static int pkvm_vcpu_init_traps(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
|
||||
pkvm_vcpu_reset_hcr(vcpu);
|
||||
|
||||
if ((!pkvm_hyp_vcpu_is_protected(hyp_vcpu)))
|
||||
if ((!pkvm_hyp_vcpu_is_protected(hyp_vcpu))) {
|
||||
struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu;
|
||||
|
||||
/* Trust the host for non-protected vcpu features. */
|
||||
vcpu->arch.hcrx_el2 = host_vcpu->arch.hcrx_el2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = pkvm_check_pvm_cpu_features(vcpu);
|
||||
if (ret)
|
||||
@@ -176,6 +181,7 @@ static int pkvm_vcpu_init_traps(struct pkvm_hyp_vcpu *hyp_vcpu)
|
||||
|
||||
pvm_init_traps_hcr(vcpu);
|
||||
pvm_init_traps_mdcr(vcpu);
|
||||
vcpu_set_hcrx(vcpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -240,10 +246,12 @@ struct pkvm_hyp_vcpu *pkvm_load_hyp_vcpu(pkvm_handle_t handle,
|
||||
|
||||
hyp_spin_lock(&vm_table_lock);
|
||||
hyp_vm = get_vm_by_handle(handle);
|
||||
if (!hyp_vm || hyp_vm->nr_vcpus <= vcpu_idx)
|
||||
if (!hyp_vm || hyp_vm->kvm.created_vcpus <= vcpu_idx)
|
||||
goto unlock;
|
||||
|
||||
hyp_vcpu = hyp_vm->vcpus[vcpu_idx];
|
||||
if (!hyp_vcpu)
|
||||
goto unlock;
|
||||
|
||||
/* Ensure vcpu isn't loaded on more than one cpu simultaneously. */
|
||||
if (unlikely(hyp_vcpu->loaded_hyp_vcpu)) {
|
||||
@@ -369,8 +377,14 @@ static void unpin_host_vcpus(struct pkvm_hyp_vcpu *hyp_vcpus[],
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_vcpus; i++)
|
||||
unpin_host_vcpu(hyp_vcpus[i]->host_vcpu);
|
||||
for (i = 0; i < nr_vcpus; i++) {
|
||||
struct pkvm_hyp_vcpu *hyp_vcpu = hyp_vcpus[i];
|
||||
|
||||
if (!hyp_vcpu)
|
||||
continue;
|
||||
|
||||
unpin_host_vcpu(hyp_vcpu->host_vcpu);
|
||||
}
|
||||
}
|
||||
|
||||
static void init_pkvm_hyp_vm(struct kvm *host_kvm, struct pkvm_hyp_vm *hyp_vm,
|
||||
@@ -394,24 +408,18 @@ static void pkvm_vcpu_init_sve(struct pkvm_hyp_vcpu *hyp_vcpu, struct kvm_vcpu *
|
||||
|
||||
static int init_pkvm_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu,
|
||||
struct pkvm_hyp_vm *hyp_vm,
|
||||
struct kvm_vcpu *host_vcpu,
|
||||
unsigned int vcpu_idx)
|
||||
struct kvm_vcpu *host_vcpu)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (hyp_pin_shared_mem(host_vcpu, host_vcpu + 1))
|
||||
return -EBUSY;
|
||||
|
||||
if (host_vcpu->vcpu_idx != vcpu_idx) {
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
hyp_vcpu->host_vcpu = host_vcpu;
|
||||
|
||||
hyp_vcpu->vcpu.kvm = &hyp_vm->kvm;
|
||||
hyp_vcpu->vcpu.vcpu_id = READ_ONCE(host_vcpu->vcpu_id);
|
||||
hyp_vcpu->vcpu.vcpu_idx = vcpu_idx;
|
||||
hyp_vcpu->vcpu.vcpu_idx = READ_ONCE(host_vcpu->vcpu_idx);
|
||||
|
||||
hyp_vcpu->vcpu.arch.hw_mmu = &hyp_vm->kvm.arch.mmu;
|
||||
hyp_vcpu->vcpu.arch.cflags = READ_ONCE(host_vcpu->arch.cflags);
|
||||
@@ -649,27 +657,28 @@ int __pkvm_init_vcpu(pkvm_handle_t handle, struct kvm_vcpu *host_vcpu,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
idx = hyp_vm->nr_vcpus;
|
||||
ret = init_pkvm_hyp_vcpu(hyp_vcpu, hyp_vm, host_vcpu);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
idx = hyp_vcpu->vcpu.vcpu_idx;
|
||||
if (idx >= hyp_vm->kvm.created_vcpus) {
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = init_pkvm_hyp_vcpu(hyp_vcpu, hyp_vm, host_vcpu, idx);
|
||||
if (ret)
|
||||
if (hyp_vm->vcpus[idx]) {
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
hyp_vm->vcpus[idx] = hyp_vcpu;
|
||||
hyp_vm->nr_vcpus++;
|
||||
unlock:
|
||||
hyp_spin_unlock(&vm_table_lock);
|
||||
|
||||
if (ret) {
|
||||
if (ret)
|
||||
unmap_donated_memory(hyp_vcpu, sizeof(*hyp_vcpu));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -686,7 +695,7 @@ teardown_donated_memory(struct kvm_hyp_memcache *mc, void *addr, size_t size)
|
||||
|
||||
int __pkvm_teardown_vm(pkvm_handle_t handle)
|
||||
{
|
||||
struct kvm_hyp_memcache *mc;
|
||||
struct kvm_hyp_memcache *mc, *stage2_mc;
|
||||
struct pkvm_hyp_vm *hyp_vm;
|
||||
struct kvm *host_kvm;
|
||||
unsigned int idx;
|
||||
@@ -714,18 +723,24 @@ int __pkvm_teardown_vm(pkvm_handle_t handle)
|
||||
|
||||
/* Reclaim guest pages (including page-table pages) */
|
||||
mc = &host_kvm->arch.pkvm.teardown_mc;
|
||||
reclaim_guest_pages(hyp_vm, mc);
|
||||
unpin_host_vcpus(hyp_vm->vcpus, hyp_vm->nr_vcpus);
|
||||
stage2_mc = &host_kvm->arch.pkvm.stage2_teardown_mc;
|
||||
reclaim_pgtable_pages(hyp_vm, stage2_mc);
|
||||
unpin_host_vcpus(hyp_vm->vcpus, hyp_vm->kvm.created_vcpus);
|
||||
|
||||
/* Push the metadata pages to the teardown memcache */
|
||||
for (idx = 0; idx < hyp_vm->nr_vcpus; ++idx) {
|
||||
for (idx = 0; idx < hyp_vm->kvm.created_vcpus; ++idx) {
|
||||
struct pkvm_hyp_vcpu *hyp_vcpu = hyp_vm->vcpus[idx];
|
||||
struct kvm_hyp_memcache *vcpu_mc = &hyp_vcpu->vcpu.arch.pkvm_memcache;
|
||||
struct kvm_hyp_memcache *vcpu_mc;
|
||||
|
||||
if (!hyp_vcpu)
|
||||
continue;
|
||||
|
||||
vcpu_mc = &hyp_vcpu->vcpu.arch.pkvm_memcache;
|
||||
|
||||
while (vcpu_mc->nr_pages) {
|
||||
void *addr = pop_hyp_memcache(vcpu_mc, hyp_phys_to_virt);
|
||||
|
||||
push_hyp_memcache(mc, addr, hyp_virt_to_phys);
|
||||
push_hyp_memcache(stage2_mc, addr, hyp_virt_to_phys);
|
||||
unmap_donated_memory_noclear(addr, PAGE_SIZE);
|
||||
}
|
||||
|
||||
|
||||
+17
-5
@@ -1086,14 +1086,26 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu)
|
||||
}
|
||||
}
|
||||
|
||||
static void hyp_mc_free_fn(void *addr, void *unused)
|
||||
static void hyp_mc_free_fn(void *addr, void *mc)
|
||||
{
|
||||
struct kvm_hyp_memcache *memcache = mc;
|
||||
|
||||
if (memcache->flags & HYP_MEMCACHE_ACCOUNT_STAGE2)
|
||||
kvm_account_pgtable_pages(addr, -1);
|
||||
|
||||
free_page((unsigned long)addr);
|
||||
}
|
||||
|
||||
static void *hyp_mc_alloc_fn(void *unused)
|
||||
static void *hyp_mc_alloc_fn(void *mc)
|
||||
{
|
||||
return (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
|
||||
struct kvm_hyp_memcache *memcache = mc;
|
||||
void *addr;
|
||||
|
||||
addr = (void *)__get_free_page(GFP_KERNEL_ACCOUNT);
|
||||
if (addr && memcache->flags & HYP_MEMCACHE_ACCOUNT_STAGE2)
|
||||
kvm_account_pgtable_pages(addr, 1);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void free_hyp_memcache(struct kvm_hyp_memcache *mc)
|
||||
@@ -1102,7 +1114,7 @@ void free_hyp_memcache(struct kvm_hyp_memcache *mc)
|
||||
return;
|
||||
|
||||
kfree(mc->mapping);
|
||||
__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, NULL);
|
||||
__free_hyp_memcache(mc, hyp_mc_free_fn, kvm_host_va, mc);
|
||||
}
|
||||
|
||||
int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
|
||||
@@ -1117,7 +1129,7 @@ int topup_hyp_memcache(struct kvm_hyp_memcache *mc, unsigned long min_pages)
|
||||
}
|
||||
|
||||
return __topup_hyp_memcache(mc, min_pages, hyp_mc_alloc_fn,
|
||||
kvm_host_pa, NULL);
|
||||
kvm_host_pa, mc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+39
-36
@@ -111,6 +111,29 @@ static void __pkvm_destroy_hyp_vm(struct kvm *host_kvm)
|
||||
|
||||
host_kvm->arch.pkvm.handle = 0;
|
||||
free_hyp_memcache(&host_kvm->arch.pkvm.teardown_mc);
|
||||
free_hyp_memcache(&host_kvm->arch.pkvm.stage2_teardown_mc);
|
||||
}
|
||||
|
||||
static int __pkvm_create_hyp_vcpu(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
size_t hyp_vcpu_sz = PAGE_ALIGN(PKVM_HYP_VCPU_SIZE);
|
||||
pkvm_handle_t handle = vcpu->kvm->arch.pkvm.handle;
|
||||
void *hyp_vcpu;
|
||||
int ret;
|
||||
|
||||
vcpu->arch.pkvm_memcache.flags |= HYP_MEMCACHE_ACCOUNT_STAGE2;
|
||||
|
||||
hyp_vcpu = alloc_pages_exact(hyp_vcpu_sz, GFP_KERNEL_ACCOUNT);
|
||||
if (!hyp_vcpu)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = kvm_call_hyp_nvhe(__pkvm_init_vcpu, handle, vcpu, hyp_vcpu);
|
||||
if (!ret)
|
||||
vcpu_set_flag(vcpu, VCPU_PKVM_FINALIZED);
|
||||
else
|
||||
free_pages_exact(hyp_vcpu, hyp_vcpu_sz);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -125,11 +148,8 @@ static void __pkvm_destroy_hyp_vm(struct kvm *host_kvm)
|
||||
*/
|
||||
static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
|
||||
{
|
||||
size_t pgd_sz, hyp_vm_sz, hyp_vcpu_sz;
|
||||
struct kvm_vcpu *host_vcpu;
|
||||
pkvm_handle_t handle;
|
||||
size_t pgd_sz, hyp_vm_sz;
|
||||
void *pgd, *hyp_vm;
|
||||
unsigned long idx;
|
||||
int ret;
|
||||
|
||||
if (host_kvm->created_vcpus < 1)
|
||||
@@ -161,40 +181,11 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
|
||||
if (ret < 0)
|
||||
goto free_vm;
|
||||
|
||||
handle = ret;
|
||||
|
||||
host_kvm->arch.pkvm.handle = handle;
|
||||
|
||||
/* Donate memory for the vcpus at hyp and initialize it. */
|
||||
hyp_vcpu_sz = PAGE_ALIGN(PKVM_HYP_VCPU_SIZE);
|
||||
kvm_for_each_vcpu(idx, host_vcpu, host_kvm) {
|
||||
void *hyp_vcpu;
|
||||
|
||||
/* Indexing of the vcpus to be sequential starting at 0. */
|
||||
if (WARN_ON(host_vcpu->vcpu_idx != idx)) {
|
||||
ret = -EINVAL;
|
||||
goto destroy_vm;
|
||||
}
|
||||
|
||||
hyp_vcpu = alloc_pages_exact(hyp_vcpu_sz, GFP_KERNEL_ACCOUNT);
|
||||
if (!hyp_vcpu) {
|
||||
ret = -ENOMEM;
|
||||
goto destroy_vm;
|
||||
}
|
||||
|
||||
ret = kvm_call_hyp_nvhe(__pkvm_init_vcpu, handle, host_vcpu,
|
||||
hyp_vcpu);
|
||||
if (ret) {
|
||||
free_pages_exact(hyp_vcpu, hyp_vcpu_sz);
|
||||
goto destroy_vm;
|
||||
}
|
||||
}
|
||||
host_kvm->arch.pkvm.handle = ret;
|
||||
host_kvm->arch.pkvm.stage2_teardown_mc.flags |= HYP_MEMCACHE_ACCOUNT_STAGE2;
|
||||
kvm_account_pgtable_pages(pgd, pgd_sz / PAGE_SIZE);
|
||||
|
||||
return 0;
|
||||
|
||||
destroy_vm:
|
||||
__pkvm_destroy_hyp_vm(host_kvm);
|
||||
return ret;
|
||||
free_vm:
|
||||
free_pages_exact(hyp_vm, hyp_vm_sz);
|
||||
free_pgd:
|
||||
@@ -214,6 +205,18 @@ int pkvm_create_hyp_vm(struct kvm *host_kvm)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pkvm_create_hyp_vcpu(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&vcpu->kvm->arch.config_lock);
|
||||
if (!vcpu_get_flag(vcpu, VCPU_PKVM_FINALIZED))
|
||||
ret = __pkvm_create_hyp_vcpu(vcpu);
|
||||
mutex_unlock(&vcpu->kvm->arch.config_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pkvm_destroy_hyp_vm(struct kvm *host_kvm)
|
||||
{
|
||||
mutex_lock(&host_kvm->arch.config_lock);
|
||||
|
||||
@@ -5132,25 +5132,7 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu)
|
||||
mutex_lock(&kvm->arch.config_lock);
|
||||
vcpu_set_hcr(vcpu);
|
||||
vcpu_set_ich_hcr(vcpu);
|
||||
|
||||
if (cpus_have_final_cap(ARM64_HAS_HCX)) {
|
||||
/*
|
||||
* In general, all HCRX_EL2 bits are gated by a feature.
|
||||
* The only reason we can set SMPME without checking any
|
||||
* feature is that its effects are not directly observable
|
||||
* from the guest.
|
||||
*/
|
||||
vcpu->arch.hcrx_el2 = HCRX_EL2_SMPME;
|
||||
|
||||
if (kvm_has_feat(kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
|
||||
vcpu->arch.hcrx_el2 |= (HCRX_EL2_MSCEn | HCRX_EL2_MCE2);
|
||||
|
||||
if (kvm_has_tcr2(kvm))
|
||||
vcpu->arch.hcrx_el2 |= HCRX_EL2_TCR2En;
|
||||
|
||||
if (kvm_has_fpmr(kvm))
|
||||
vcpu->arch.hcrx_el2 |= HCRX_EL2_EnFPM;
|
||||
}
|
||||
vcpu_set_hcrx(vcpu);
|
||||
|
||||
if (test_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags))
|
||||
goto out;
|
||||
|
||||
Reference in New Issue
Block a user