History

KVM: Add KVM_PRE_FAULT_MEMORY vcpu ioctl to pre-populate guest memory

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.

Isaku Yamahata committed 2 years ago

Commit bc1a5cd1 parent 9aed7a64 files · +78 −0Browse files

Unified · Split

4 files
  1. include/linux/kvm_host.h +5 −0
  2. include/uapi/linux/kvm.h +10 −0
  3. virt/kvm/Kconfig +3 −0
  4. virt/kvm/kvm_main.c +60 −0
include/linux/kvm_host.h+5−0
@@ -2477,4 +2477,9 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t gfn, void __user *src, long npages · 2476 unmodified lines
2477void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);2477void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);
2478#endif2478#endif
2479 2479
2480#ifdef CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY
2481long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
2482 struct kvm_pre_fault_memory *range);
2483#endif
2484
2480#endif2485#endif
include/uapi/linux/kvm.h+10−0
@@ -917,6 +917,7 @@ struct kvm_enable_cap { · 916 unmodified lines
917#define KVM_CAP_MEMORY_ATTRIBUTES 233917#define KVM_CAP_MEMORY_ATTRIBUTES 233
918#define KVM_CAP_GUEST_MEMFD 234918#define KVM_CAP_GUEST_MEMFD 234
919#define KVM_CAP_VM_TYPES 235919#define KVM_CAP_VM_TYPES 235
920#define KVM_CAP_PRE_FAULT_MEMORY 236
920 921
921struct kvm_irq_routing_irqchip {922struct 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
1554struct 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 */
virt/kvm/Kconfig+3−0
@@ -67,6 +67,9 @@ config HAVE_KVM_INVALID_WAKEUPS · 66 unmodified lines
67config KVM_GENERIC_DIRTYLOG_READ_PROTECT67config KVM_GENERIC_DIRTYLOG_READ_PROTECT
68 bool68 bool
69 69
70config KVM_GENERIC_PRE_FAULT_MEMORY
71 bool
72
70config KVM_COMPAT73config KVM_COMPAT
71 def_bool y74 def_bool y
72 depends on KVM && COMPAT && !(S390 || ARM64 || RISCV)75 depends on KVM && COMPAT && !(S390 || ARM64 || RISCV)
virt/kvm/kvm_main.c+60−0
@@ -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
4377static 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
4376static long kvm_vcpu_ioctl(struct file *filp,4422static 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 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t