@@ -37,6 +37,7 @@ menuconfig KVM
select HAVE_KVM_VCPU_RUN_PID_CHANGE
select SCHED_INFO
select GUEST_PERF_EVENTS if PERF_EVENTS
+ select KVM_USERFAULT
help
Support hosting virtualized guest machines.
@@ -1434,7 +1434,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
* logging_active is guaranteed to never be true for VM_PFNMAP
* memslots.
*/
- if (logging_active) {
+ if (logging_active || kvm->userfault) {
force_pte = true;
vma_shift = PAGE_SHIFT;
} else {
@@ -1494,8 +1494,15 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
kvm_send_hwpoison_signal(hva, vma_shift);
return 0;
}
- if (is_error_noslot_pfn(pfn))
+ if (is_error_noslot_pfn(pfn)) {
+ if (pfn == KVM_PFN_ERR_USERFAULT)
+ kvm_prepare_memory_fault_exit(vcpu, gfn << PAGE_SHIFT,
+ PAGE_SIZE, write_fault,
+ /*exec=*/false,
+ /*private=*/false,
+ /*userfault=*/true);
return -EFAULT;
+ }
if (kvm_is_device_pfn(pfn)) {
/*
@@ -2105,3 +2112,28 @@ void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled)
trace_kvm_toggle_cache(*vcpu_pc(vcpu), was_enabled, now_enabled);
}
+
+#ifdef CONFIG_KVM_GENERIC_MEMORY_ATTRIBUTES
+bool kvm_arch_pre_set_memory_attributes(struct kvm *kvm,
+ struct kvm_gfn_range *range)
+{
+ unsigned long attrs = range->arg.attributes;
+
+ /*
+ * We only need to unmap if we're enabling userfault. Disabling it
+ * does not need an unmap. An unmap to get huge mappings will come
+ * later.
+ */
+ if (attrs & KVM_MEMORY_ATTRIBUTE_USERFAULT)
+ kvm_unmap_gfn_range(kvm, range);
+
+ return false;
+}
+
+bool kvm_arch_post_set_memory_attributes(struct kvm *kvm,
+ struct kvm_gfn_range *range)
+{
+ /* Nothing to do! */
+ return false;
+}
+#endif
Support comes in three parts: 1. When KVM Userfault is enabled, only install PAGE_SIZE PTEs. This prevents us from being able to map a userfault-enabled pfn with a huge PTE in response to a fault on a non-userfault pfn. 2. When we get KVM_PFN_ERR_USERFAULT from __gfn_to_pfn_memslot, return a memory fault to userspace. 3. When KVM Userfault is enabled for a particular kvm_gfn_range, unmap it, so that we can get faults on it. Signed-off-by: James Houghton <jthoughton@google.com> --- arch/arm64/kvm/Kconfig | 1 + arch/arm64/kvm/mmu.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-)