Fix KVM on specific hardware (rhbz 1278688)
This commit is contained in:
parent
c63b7d89c4
commit
8176c9e476
|
@ -0,0 +1,169 @@
|
|||
From 1d8007bdee074fdffcf3539492d8a151a1fb3436 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
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 <aderumier@odiso.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 9da0e4d5ac969909f6b435ce28ea28135a9cbd69
|
||||
Reviewed-by: Radim Krčmář <rkrcmar@redhat.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
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);
|
|
@ -0,0 +1,134 @@
|
|||
From f0d648bdf0a5bbc91da6099d5282f77996558ea4 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
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 <aderumier@odiso.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 9da0e4d5ac969909f6b435ce28ea28135a9cbd69
|
||||
Reviewed-by: Radim Krčmář <rkrcmar@redhat.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
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
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
From 25188b9986cf6b0cadcf1bc1d1693a2e9c50ed47 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
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 <pbonzini@redhat.com>
|
||||
---
|
||||
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
|
||||
|
15
kernel.spec
15
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 <jmforbes@fedoraproject.org>
|
||||
* Fri Nov 20 2015 Justin M. Forbes <jmforbes@fedoraproject.org>
|
||||
- Fix for GRE tunnel running in IPSec (rhbz 1272571)
|
||||
- Fix KVM on specific hardware (rhbz 1278688)
|
||||
|
||||
* Mon Nov 16 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- Fix ipset netfilter issues (rhbz 1279189)
|
||||
|
|
Loading…
Reference in New Issue