Add a new ioctl KVM_PRE_FAULT_MEMORY in the KVM common code. It iterates on the memory range and calls the arch-specific function. The implementation is optional and enabled by a Kconfig symbol.
Unified · Split
| @@ -2477,4 +2477,9 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t gfn, void __user *src, long npages · 2476 unmodified lines | |||
| 2477 | void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end); | 2477 | void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end); |
| 2478 | #endif | 2478 | #endif |
| 2479 | 2479 | ||
| 2480 | #ifdef CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY | ||
| 2481 | long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu, | ||
| 2482 | struct kvm_pre_fault_memory *range); | ||
| 2483 | #endif | ||
| 2484 | |||
| 2480 | #endif | 2485 | #endif |
| @@ -917,6 +917,7 @@ struct kvm_enable_cap { · 916 unmodified lines | |||
| 917 | #define KVM_CAP_MEMORY_ATTRIBUTES 233 | 917 | #define KVM_CAP_MEMORY_ATTRIBUTES 233 |
| 918 | #define KVM_CAP_GUEST_MEMFD 234 | 918 | #define KVM_CAP_GUEST_MEMFD 234 |
| 919 | #define KVM_CAP_VM_TYPES 235 | 919 | #define KVM_CAP_VM_TYPES 235 |
| 920 | #define KVM_CAP_PRE_FAULT_MEMORY 236 | ||
| 920 | 921 | ||
| 921 | struct kvm_irq_routing_irqchip { | 922 | struct kvm_irq_routing_irqchip { |
| 922 | __u32 irqchip; | 923 | __u32 irqchip; |
| @@ -1548,4 +1549,13 @@ struct kvm_create_guest_memfd { · 625 unmodified lines | |||
| 1548 | __u64 reserved[6]; | 1549 | __u64 reserved[6]; |
| 1549 | }; | 1550 | }; |
| 1550 | 1551 | ||
| 1552 | #define KVM_PRE_FAULT_MEMORY _IOWR(KVMIO, 0xd5, struct kvm_pre_fault_memory) | ||
| 1553 | |||
| 1554 | struct kvm_pre_fault_memory { | ||
| 1555 | __u64 gpa; | ||
| 1556 | __u64 size; | ||
| 1557 | __u64 flags; | ||
| 1558 | __u64 padding[5]; | ||
| 1559 | }; | ||
| 1560 | |||
| 1551 | #endif /* __LINUX_KVM_H */ | 1561 | #endif /* __LINUX_KVM_H */ |
| @@ -67,6 +67,9 @@ config HAVE_KVM_INVALID_WAKEUPS · 66 unmodified lines | |||
| 67 | config KVM_GENERIC_DIRTYLOG_READ_PROTECT | 67 | config KVM_GENERIC_DIRTYLOG_READ_PROTECT |
| 68 | bool | 68 | bool |
| 69 | 69 | ||
| 70 | config KVM_GENERIC_PRE_FAULT_MEMORY | ||
| 71 | bool | ||
| 72 | |||
| 70 | config KVM_COMPAT | 73 | config KVM_COMPAT |
| 71 | def_bool y | 74 | def_bool y |
| 72 | depends on KVM && COMPAT && !(S390 || ARM64 || RISCV) | 75 | depends on KVM && COMPAT && !(S390 || ARM64 || RISCV) |
| @@ -4373,6 +4373,52 @@ static int kvm_vcpu_ioctl_get_stats_fd(struct kvm_vcpu *vcpu) · 4372 unmodified lines | |||
| 4373 | return fd; | 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 | static long kvm_vcpu_ioctl(struct file *filp, | 4422 | static long kvm_vcpu_ioctl(struct file *filp, |
| 4377 | unsigned int ioctl, unsigned long arg) | 4423 | unsigned int ioctl, unsigned long arg) |
| 4378 | { | 4424 | { |
| @@ -4573,6 +4619,20 @@ out_free1: · 194 unmodified lines | |||
| 4573 | r = kvm_vcpu_ioctl_get_stats_fd(vcpu); | 4619 | r = kvm_vcpu_ioctl_get_stats_fd(vcpu); |
| 4574 | break; | 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 | default: | 4636 | default: |
| 4577 | r = kvm_arch_vcpu_ioctl(filp, ioctl, arg); | 4637 | r = kvm_arch_vcpu_ioctl(filp, ioctl, arg); |
| 4578 | } | 4638 | } |