diff --git a/0001-KVM-x86-build-kvm_userspace_memory_region-in-x86_set.patch b/0001-KVM-x86-build-kvm_userspace_memory_region-in-x86_set.patch new file mode 100644 index 0000000..6395b17 --- /dev/null +++ b/0001-KVM-x86-build-kvm_userspace_memory_region-in-x86_set.patch @@ -0,0 +1,169 @@ +From 1d8007bdee074fdffcf3539492d8a151a1fb3436 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 12 Oct 2015 13:38:32 +0200 +Subject: [PATCH] KVM: x86: build kvm_userspace_memory_region in + x86_set_memory_region +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The next patch will make x86_set_memory_region fill the +userspace_addr. Since the struct is not used untouched +anymore, it makes sense to build it in x86_set_memory_region +directly; it also simplifies the callers. + +Reported-by: Alexandre DERUMIER +Cc: stable@vger.kernel.org +Fixes: 9da0e4d5ac969909f6b435ce28ea28135a9cbd69 +Reviewed-by: Radim Krčmář +Signed-off-by: Paolo Bonzini +--- + arch/x86/include/asm/kvm_host.h | 6 ++---- + arch/x86/kvm/vmx.c | 26 ++++++-------------------- + arch/x86/kvm/x86.c | 31 +++++++++++++------------------ + 3 files changed, 21 insertions(+), 42 deletions(-) + +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index 49ec903..4e7ad7e 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -1199,9 +1199,7 @@ void kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err); + + int kvm_is_in_guest(void); + +-int __x86_set_memory_region(struct kvm *kvm, +- const struct kvm_userspace_memory_region *mem); +-int x86_set_memory_region(struct kvm *kvm, +- const struct kvm_userspace_memory_region *mem); ++int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size); ++int x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size); + + #endif /* _ASM_X86_KVM_HOST_H */ +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 18c30b4..8461e0c 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -4105,17 +4105,13 @@ static void seg_setup(int seg) + static int alloc_apic_access_page(struct kvm *kvm) + { + struct page *page; +- struct kvm_userspace_memory_region kvm_userspace_mem; + int r = 0; + + mutex_lock(&kvm->slots_lock); + if (kvm->arch.apic_access_page_done) + goto out; +- kvm_userspace_mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT; +- kvm_userspace_mem.flags = 0; +- kvm_userspace_mem.guest_phys_addr = APIC_DEFAULT_PHYS_BASE; +- kvm_userspace_mem.memory_size = PAGE_SIZE; +- r = __x86_set_memory_region(kvm, &kvm_userspace_mem); ++ r = __x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT, ++ APIC_DEFAULT_PHYS_BASE, PAGE_SIZE); + if (r) + goto out; + +@@ -4140,17 +4136,12 @@ static int alloc_identity_pagetable(struct kvm *kvm) + { + /* Called with kvm->slots_lock held. */ + +- struct kvm_userspace_memory_region kvm_userspace_mem; + int r = 0; + + BUG_ON(kvm->arch.ept_identity_pagetable_done); + +- kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT; +- kvm_userspace_mem.flags = 0; +- kvm_userspace_mem.guest_phys_addr = +- kvm->arch.ept_identity_map_addr; +- kvm_userspace_mem.memory_size = PAGE_SIZE; +- r = __x86_set_memory_region(kvm, &kvm_userspace_mem); ++ r = __x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT, ++ kvm->arch.ept_identity_map_addr, PAGE_SIZE); + + return r; + } +@@ -4949,14 +4940,9 @@ static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu) + static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr) + { + int ret; +- struct kvm_userspace_memory_region tss_mem = { +- .slot = TSS_PRIVATE_MEMSLOT, +- .guest_phys_addr = addr, +- .memory_size = PAGE_SIZE * 3, +- .flags = 0, +- }; + +- ret = x86_set_memory_region(kvm, &tss_mem); ++ ret = x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, addr, ++ PAGE_SIZE * 3); + if (ret) + return ret; + kvm->arch.tss_addr = addr; +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 373328b..b12665b 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -7721,18 +7721,21 @@ void kvm_arch_sync_events(struct kvm *kvm) + kvm_free_pit(kvm); + } + +-int __x86_set_memory_region(struct kvm *kvm, +- const struct kvm_userspace_memory_region *mem) ++int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size) + { + int i, r; + + /* Called with kvm->slots_lock held. */ +- BUG_ON(mem->slot >= KVM_MEM_SLOTS_NUM); ++ if (WARN_ON(id >= KVM_MEM_SLOTS_NUM)) ++ return -EINVAL; + + for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) { +- struct kvm_userspace_memory_region m = *mem; ++ struct kvm_userspace_memory_region m; + +- m.slot |= i << 16; ++ m.slot = id | (i << 16); ++ m.flags = 0; ++ m.guest_phys_addr = gpa; ++ m.memory_size = size; + r = __kvm_set_memory_region(kvm, &m); + if (r < 0) + return r; +@@ -7742,13 +7745,12 @@ int __x86_set_memory_region(struct kvm *kvm, + } + EXPORT_SYMBOL_GPL(__x86_set_memory_region); + +-int x86_set_memory_region(struct kvm *kvm, +- const struct kvm_userspace_memory_region *mem) ++int x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size) + { + int r; + + mutex_lock(&kvm->slots_lock); +- r = __x86_set_memory_region(kvm, mem); ++ r = __x86_set_memory_region(kvm, id, gpa, size); + mutex_unlock(&kvm->slots_lock); + + return r; +@@ -7763,16 +7765,9 @@ void kvm_arch_destroy_vm(struct kvm *kvm) + * unless the the memory map has changed due to process exit + * or fd copying. + */ +- struct kvm_userspace_memory_region mem; +- memset(&mem, 0, sizeof(mem)); +- mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT; +- x86_set_memory_region(kvm, &mem); +- +- mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT; +- x86_set_memory_region(kvm, &mem); +- +- mem.slot = TSS_PRIVATE_MEMSLOT; +- x86_set_memory_region(kvm, &mem); ++ x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT, 0, 0); ++ x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT, 0, 0); ++ x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, 0, 0); + } + kvm_iommu_unmap_guest(kvm); + kfree(kvm->arch.vpic); diff --git a/0002-KVM-x86-map-unmap-private-slots-in-__x86_set_memory_.patch b/0002-KVM-x86-map-unmap-private-slots-in-__x86_set_memory_.patch new file mode 100644 index 0000000..261c6e1 --- /dev/null +++ b/0002-KVM-x86-map-unmap-private-slots-in-__x86_set_memory_.patch @@ -0,0 +1,134 @@ +From f0d648bdf0a5bbc91da6099d5282f77996558ea4 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 12 Oct 2015 13:56:27 +0200 +Subject: [PATCH] KVM: x86: map/unmap private slots in __x86_set_memory_region +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Otherwise, two copies (one of them never populated and thus bogus) +are allocated for the regular and SMM address spaces. This breaks +SMM with EPT but without unrestricted guest support, because the +SMM copy of the identity page map is all zeros. + +By moving the allocation to the caller we also remove the last +vestiges of kernel-allocated memory regions (not accessible anymore +in userspace since commit b74a07beed0e, "KVM: Remove kernel-allocated +memory regions", 2010-06-21); that is a nice bonus. + +Reported-by: Alexandre DERUMIER +Cc: stable@vger.kernel.org +Fixes: 9da0e4d5ac969909f6b435ce28ea28135a9cbd69 +Reviewed-by: Radim Krčmář +Signed-off-by: Paolo Bonzini +--- + arch/x86/kvm/x86.c | 62 ++++++++++++++++++++++++++---------------------------- + 1 file changed, 30 insertions(+), 32 deletions(-) + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 7bf8096..3ac33f8 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -7477,23 +7477,53 @@ void kvm_arch_sync_events(struct kvm *kvm) + int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size) + { + int i, r; ++ u64 hva; ++ struct kvm_memslots *slots = kvm_memslots(kvm); ++ struct kvm_memory_slot *slot, old; + + /* Called with kvm->slots_lock held. */ + if (WARN_ON(id >= KVM_MEM_SLOTS_NUM)) + return -EINVAL; + ++ slot = id_to_memslot(slots, id); ++ if (size) { ++ if (WARN_ON(slot->npages)) ++ return -EEXIST; ++ ++ /* ++ * MAP_SHARED to prevent internal slot pages from being moved ++ * by fork()/COW. ++ */ ++ hva = vm_mmap(NULL, 0, size, PROT_READ | PROT_WRITE, ++ MAP_SHARED | MAP_ANONYMOUS, 0); ++ if (IS_ERR((void *)hva)) ++ return PTR_ERR((void *)hva); ++ } else { ++ if (!slot->npages) ++ return 0; ++ ++ hva = 0; ++ } ++ ++ old = *slot; + for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) { + struct kvm_userspace_memory_region m; + + m.slot = id | (i << 16); + m.flags = 0; + m.guest_phys_addr = gpa; ++ m.userspace_addr = hva; + m.memory_size = size; + r = __kvm_set_memory_region(kvm, &m); + if (r < 0) + return r; + } + ++ if (!size) { ++ r = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE); ++ WARN_ON(r < 0); ++ } ++ + return 0; + } + EXPORT_SYMBOL_GPL(__x86_set_memory_region); +@@ -7623,27 +7653,6 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, + const struct kvm_userspace_memory_region *mem, + enum kvm_mr_change change) + { +- /* +- * Only private memory slots need to be mapped here since +- * KVM_SET_MEMORY_REGION ioctl is no longer supported. +- */ +- if ((memslot->id >= KVM_USER_MEM_SLOTS) && (change == KVM_MR_CREATE)) { +- unsigned long userspace_addr; +- +- /* +- * MAP_SHARED to prevent internal slot pages from being moved +- * by fork()/COW. +- */ +- userspace_addr = vm_mmap(NULL, 0, memslot->npages * PAGE_SIZE, +- PROT_READ | PROT_WRITE, +- MAP_SHARED | MAP_ANONYMOUS, 0); +- +- if (IS_ERR((void *)userspace_addr)) +- return PTR_ERR((void *)userspace_addr); +- +- memslot->userspace_addr = userspace_addr; +- } +- + return 0; + } + +@@ -7705,17 +7714,6 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, + { + int nr_mmu_pages = 0; + +- if (change == KVM_MR_DELETE && old->id >= KVM_USER_MEM_SLOTS) { +- int ret; +- +- ret = vm_munmap(old->userspace_addr, +- old->npages * PAGE_SIZE); +- if (ret < 0) +- printk(KERN_WARNING +- "kvm_vm_ioctl_set_memory_region: " +- "failed to munmap memory\n"); +- } +- + if (!kvm->arch.n_requested_mmu_pages) + nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm); + +-- +2.5.0 + diff --git a/0003-KVM-x86-fix-previous-commit-for-32-bit.patch b/0003-KVM-x86-fix-previous-commit-for-32-bit.patch new file mode 100644 index 0000000..df99e60 --- /dev/null +++ b/0003-KVM-x86-fix-previous-commit-for-32-bit.patch @@ -0,0 +1,30 @@ +From 25188b9986cf6b0cadcf1bc1d1693a2e9c50ed47 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Wed, 14 Oct 2015 15:51:08 +0200 +Subject: [PATCH] KVM: x86: fix previous commit for 32-bit + +Unfortunately I only noticed this after pushing. + +Fixes: f0d648bdf0a5bbc91da6099d5282f77996558ea4 +Cc: stable@vger.kernel.org +Signed-off-by: Paolo Bonzini +--- + arch/x86/kvm/x86.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 6e03546..9a9a198 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -7482,7 +7482,7 @@ void kvm_arch_sync_events(struct kvm *kvm) + int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size) + { + int i, r; +- u64 hva; ++ unsigned long hva; + struct kvm_memslots *slots = kvm_memslots(kvm); + struct kvm_memory_slot *slot, old; + +-- +2.5.0 + diff --git a/kernel.spec b/kernel.spec index 8a33c6e..0f3796f 100644 --- a/kernel.spec +++ b/kernel.spec @@ -40,7 +40,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 200 +%global baserelease 201 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -650,6 +650,11 @@ Patch558: netfilter-ipset-Fix-hash-type-expire-release-empty-h.patch #rhbz 1272571 Patch559: 0001-ipv6-Avoid-creating-RTF_CACHE-from-a-rt-that-is-not-.patch +#rhbz 1278688 +Patch560: 0001-KVM-x86-build-kvm_userspace_memory_region-in-x86_set.patch +Patch561: 0002-KVM-x86-map-unmap-private-slots-in-__x86_set_memory_.patch +Patch562: 0003-KVM-x86-fix-previous-commit-for-32-bit.patch + # END OF PATCH DEFINITIONS %endif @@ -1420,6 +1425,11 @@ ApplyPatch netfilter-ipset-Fix-hash-type-expire-release-empty-h.patch #rhbz 1272571 ApplyPatch 0001-ipv6-Avoid-creating-RTF_CACHE-from-a-rt-that-is-not-.patch +#rhbz 1278688 +ApplyPatch 0001-KVM-x86-build-kvm_userspace_memory_region-in-x86_set.patch +ApplyPatch 0002-KVM-x86-map-unmap-private-slots-in-__x86_set_memory_.patch +ApplyPatch 0003-KVM-x86-fix-previous-commit-for-32-bit.patch + # END OF PATCH APPLICATIONS %endif @@ -2270,8 +2280,9 @@ fi # # %changelog - Fri Nov 20 2015 Justin M. Forbes +* Fri Nov 20 2015 Justin M. Forbes - Fix for GRE tunnel running in IPSec (rhbz 1272571) +- Fix KVM on specific hardware (rhbz 1278688) * Mon Nov 16 2015 Josh Boyer - Fix ipset netfilter issues (rhbz 1279189)