Currently 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 can be problematic, as being uninitialised, a vCPU might not be in a
state where it is correct to do so.

Provide kvm_arch_vcpu_allow_pre_fault_memory() to allow architectures to
override this behaviour before the load is attempted.

Implement it as a __weak symbol defaulting to the current state where it is
always permitted.

This lays the foundation for a future change which implements pre-faulting
for arm64 which will wish to disallow this for uninitialised vCPUs.

As no architecture currently overrides it, no functional change intended.

Suggested-by: Oliver Upton <[email protected]>
Signed-off-by: Lorenzo Stoakes (ARM) <[email protected]>
---
 include/linux/kvm_host.h | 1 +
 virt/kvm/kvm_main.c      | 8 ++++++++
 2 files changed, 9 insertions(+)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 03bfc92864b6..c11fda8704a3 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1693,6 +1693,7 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
 bool kvm_arch_dy_runnable(struct kvm_vcpu *vcpu);
 bool kvm_arch_dy_has_pending_interrupt(struct kvm_vcpu *vcpu);
 bool kvm_arch_vcpu_preempted_in_kernel(struct kvm_vcpu *vcpu);
+bool kvm_arch_vcpu_allow_pre_fault_memory(struct kvm_vcpu *vcpu);
 void kvm_arch_pre_destroy_vm(struct kvm *kvm);
 void kvm_arch_create_vm_debugfs(struct kvm *kvm);
 
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 65eb26a0520d..9662baf2bfca 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3961,6 +3961,11 @@ bool __weak kvm_arch_dy_has_pending_interrupt(struct 
kvm_vcpu *vcpu)
        return false;
 }
 
+bool __weak kvm_arch_vcpu_allow_pre_fault_memory(struct kvm_vcpu *vcpu)
+{
+       return true;
+}
+
 void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode)
 {
        int nr_vcpus, start, i, idx, yielded;
@@ -4365,6 +4370,9 @@ static int kvm_vcpu_pre_fault_memory(struct kvm_vcpu 
*vcpu,
            range->gpa + range->size <= range->gpa)
                return -EINVAL;
 
+       if (!kvm_arch_vcpu_allow_pre_fault_memory(vcpu))
+               return -ENOEXEC;
+
        vcpu_load(vcpu);
        idx = srcu_read_lock(&vcpu->kvm->srcu);
 

-- 
2.55.0


Reply via email to