mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
KVM: Allow architectures to disallow pre-fault
All existing architectures which implement KVM pre-fault (x86, s390) have mechanisms for disallowing pre-faulting. Currently these are open coded as part of kvm_arch_vcpu_pre_fault_memory(). Formalise this by moving them into a new kvm_arch_pre_fault_allowed() hook, which every architecture selecting CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY must implement, returning an error code if the operation is disallowed or 0 otherwise. The hook is called early in the generic code, allowing architectures to disallow the operation prior to vCPU load. This is important, as kvm_vcpu_pre_fault_memory() is the only place where generic code can call vcpu_load() on a vCPU that has not yet been initialised. This lays the foundation for a future change which implements pre-faulting for arm64 which needs to disallow the mechanism for uninitialised vCPUs. Suggested-by: Oliver Upton <oupton@kernel.org> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> Acked-by: Sean Christopherson <seanjc@google.com> Reviewed-by: Fuad Tabba <fuad.tabba@linux.dev> Tested-by: Fuad Tabba <fuad.tabba@linux.dev> Link: https://patch.msgid.link/20260923-kvm-arm-prefault-v4-1-d4b0b4dfa8c3@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
c2778d14cd
commit
caa63620f9
|
|
@ -5784,6 +5784,14 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, struct kvm_memory_slot *old,
|
|||
s390_kvm_mmu_commit_memory_region(kvm, old, new, change);
|
||||
}
|
||||
|
||||
int kvm_arch_pre_fault_allowed(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (kvm_is_ucontrol(vcpu->kvm))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_arch_vcpu_pre_fault_memory() -- pre-fault and link gmap dat tables
|
||||
* @vcpu: the vcpu that shall appear to have generated the fault-in.
|
||||
|
|
@ -5810,9 +5818,6 @@ long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu, struct kvm_pre_fault_
|
|||
gpa_t end;
|
||||
int rc;
|
||||
|
||||
if (kvm_is_ucontrol(vcpu->kvm))
|
||||
return -EINVAL;
|
||||
|
||||
rc = kvm_s390_faultin_gfn(vcpu, NULL, &f);
|
||||
if (rc == PGM_ADDRESSING)
|
||||
return -ENOENT;
|
||||
|
|
|
|||
|
|
@ -5086,6 +5086,14 @@ static int kvm_tdp_page_prefault(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|||
}
|
||||
}
|
||||
|
||||
int kvm_arch_pre_fault_allowed(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (!vcpu->kvm->arch.pre_fault_allowed)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
|
||||
struct kvm_pre_fault_memory *range)
|
||||
{
|
||||
|
|
@ -5095,9 +5103,6 @@ long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
|
|||
u64 end;
|
||||
int r;
|
||||
|
||||
if (!vcpu->kvm->arch.pre_fault_allowed)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (kvm_is_gfn_alias(vcpu->kvm, gpa_to_gfn(range->gpa)))
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
|||
|
|
@ -1708,7 +1708,7 @@ static int tdx_sept_map_leaf_spte(struct kvm *kvm, gfn_t gfn, enum pg_level leve
|
|||
WARN_ON_ONCE((new_spte & VMX_EPT_RWX_MASK) != VMX_EPT_RWX_MASK);
|
||||
|
||||
/*
|
||||
* Ensure pre_fault_allowed is read by kvm_arch_vcpu_pre_fault_memory()
|
||||
* Ensure pre_fault_allowed is read by kvm_arch_pre_fault_allowed()
|
||||
* before kvm_tdx->state. Userspace must not be allowed to pre-fault
|
||||
* arbitrary memory until the initial memory image is finalized. Pairs
|
||||
* with the smp_wmb() in tdx_td_finalize().
|
||||
|
|
|
|||
|
|
@ -2643,6 +2643,7 @@ void kvm_arch_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY
|
||||
int kvm_arch_pre_fault_allowed(struct kvm_vcpu *vcpu);
|
||||
long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
|
||||
struct kvm_pre_fault_memory *range);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4353,7 +4353,7 @@ static int kvm_vcpu_ioctl_get_stats_fd(struct kvm_vcpu *vcpu)
|
|||
static int kvm_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
|
||||
struct kvm_pre_fault_memory *range)
|
||||
{
|
||||
int idx;
|
||||
int idx, err;
|
||||
long r;
|
||||
u64 full_size;
|
||||
|
||||
|
|
@ -4365,6 +4365,14 @@ static int kvm_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
|
|||
range->gpa + range->size <= range->gpa)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Certain architectures (e.g. arm64) need to reject the ioctl 'early'
|
||||
* before vcpu_load().
|
||||
*/
|
||||
err = kvm_arch_pre_fault_allowed(vcpu);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
vcpu_load(vcpu);
|
||||
idx = srcu_read_lock(&vcpu->kvm->srcu);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user