| @@ -4373,6 +4373,52 @@ static int kvm_vcpu_ioctl_get_stats_fd(struct kvm_vcpu *vcpu) · 4372 unmodified lines |
| 4373 | 4373 | return fd; |
| 4374 | 4374 | } |
| 4375 | 4375 | |
| 4376 | +#ifdef CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY |
| 4377 | +static int kvm_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu, |
| 4378 | + struct kvm_pre_fault_memory *range) |
| 4379 | +{ |
| 4380 | + int idx; |
| 4381 | + long r; |
| 4382 | + u64 full_size; |
| 4383 | + |
| 4384 | + if (range->flags) |
| 4385 | + return -EINVAL; |
| 4386 | + |
| 4387 | + if (!PAGE_ALIGNED(range->gpa) || |
| 4388 | + !PAGE_ALIGNED(range->size) || |
| 4389 | + range->gpa + range->size <= range->gpa) |
| 4390 | + return -EINVAL; |
| 4391 | + |
| 4392 | + vcpu_load(vcpu); |
| 4393 | + idx = srcu_read_lock(&vcpu->kvm->srcu); |
| 4394 | + |
| 4395 | + full_size = range->size; |
| 4396 | + do { |
| 4397 | + if (signal_pending(current)) { |
| 4398 | + r = -EINTR; |
| 4399 | + break; |
| 4400 | + } |
| 4401 | + |
| 4402 | + r = kvm_arch_vcpu_pre_fault_memory(vcpu, range); |
| 4403 | + if (WARN_ON_ONCE(r == 0 || r == -EIO)) |
| 4404 | + break; |
| 4405 | + |
| 4406 | + if (r < 0) |
| 4407 | + break; |
| 4408 | + |
| 4409 | + range->size -= r; |
| 4410 | + range->gpa += r; |
| 4411 | + cond_resched(); |
| 4412 | + } while (range->size); |
| 4413 | + |
| 4414 | + srcu_read_unlock(&vcpu->kvm->srcu, idx); |
| 4415 | + vcpu_put(vcpu); |
| 4416 | + |
| 4417 | + /* Return success if at least one page was mapped successfully. */ |
| 4418 | + return full_size == range->size ? r : 0; |
| 4419 | +} |
| 4420 | +#endif |
| 4421 | + |
| 4376 | 4422 | static long kvm_vcpu_ioctl(struct file *filp, |
| 4377 | 4423 | unsigned int ioctl, unsigned long arg) |
| 4378 | 4424 | { |
| @@ -4573,6 +4619,20 @@ out_free1: · 194 unmodified lines |
| 4573 | 4619 | r = kvm_vcpu_ioctl_get_stats_fd(vcpu); |
| 4574 | 4620 | break; |
| 4575 | 4621 | } |
| 4622 | +#ifdef CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY |
| 4623 | + case KVM_PRE_FAULT_MEMORY: { |
| 4624 | + struct kvm_pre_fault_memory range; |
| 4625 | + |
| 4626 | + r = -EFAULT; |
| 4627 | + if (copy_from_user(&range, argp, sizeof(range))) |
| 4628 | + break; |
| 4629 | + r = kvm_vcpu_pre_fault_memory(vcpu, &range); |
| 4630 | + /* Pass back leftover range. */ |
| 4631 | + if (copy_to_user(argp, &range, sizeof(range))) |
| 4632 | + r = -EFAULT; |
| 4633 | + break; |
| 4634 | + } |
| 4635 | +#endif |
| 4576 | 4636 | default: |
| 4577 | 4637 | r = kvm_arch_vcpu_ioctl(filp, ioctl, arg); |
| 4578 | 4638 | } |