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
24772477 void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);
24782478 #endif
24792479
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+
24802485 #endif
include/uapi/linux/kvm.h+10−0
@@ -917,6 +917,7 @@ struct kvm_enable_cap { · 916 unmodified lines
917917 #define KVM_CAP_MEMORY_ATTRIBUTES 233
918918 #define KVM_CAP_GUEST_MEMFD 234
919919 #define KVM_CAP_VM_TYPES 235
920+#define KVM_CAP_PRE_FAULT_MEMORY 236
920921
921922 struct kvm_irq_routing_irqchip {
922923 __u32 irqchip;
@@ -1548,4 +1549,13 @@ struct kvm_create_guest_memfd { · 625 unmodified lines
15481549 __u64 reserved[6];
15491550 };
15501551
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+
15511561 #endif /* __LINUX_KVM_H */
virt/kvm/Kconfig+3−0
@@ -67,6 +67,9 @@ config HAVE_KVM_INVALID_WAKEUPS · 66 unmodified lines
6767 config KVM_GENERIC_DIRTYLOG_READ_PROTECT
6868 bool
6969
70+config KVM_GENERIC_PRE_FAULT_MEMORY
71+ bool
72+
7073 config KVM_COMPAT
7174 def_bool y
7275 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
43734373 return fd;
43744374 }
43754375
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+
43764422 static long kvm_vcpu_ioctl(struct file *filp,
43774423 unsigned int ioctl, unsigned long arg)
43784424 {
@@ -4573,6 +4619,20 @@ out_free1: · 194 unmodified lines
45734619 r = kvm_vcpu_ioctl_get_stats_fd(vcpu);
45744620 break;
45754621 }
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
45764636 default:
45774637 r = kvm_arch_vcpu_ioctl(filp, ioctl, arg);
45784638 }

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