From a84ef0f6e411df37f7fdd1e19332e098dc214d49 Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Mon, 25 Nov 2019 17:47:03 +0100 Subject: [PATCH] [x86] KVM: x86: introduce is_pae_paging (Regression in 4.19.77) Fixes a regression in 4.19.81 while including backport of 16cfacc80857 ("KVM: x86: Manually calculate reserved bits when loading PDPTRS") but not bf03d4f93347 ("KVM: x86: introduce is_pae_paging"). --- debian/changelog | 1 + .../x86/KVM-x86-introduce-is_pae_paging.patch | 113 ++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 115 insertions(+) create mode 100644 debian/patches/bugfix/x86/KVM-x86-introduce-is_pae_paging.patch diff --git a/debian/changelog b/debian/changelog index f60fee223..5c47a9a97 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1201,6 +1201,7 @@ linux (4.19.81-1) UNRELEASED; urgency=medium * ixgbe: Fix secpath usage for IPsec TX offload (Closes: #930443) * ipv4: Return -ENETUNREACH if we can't create route but saddr is valid (Closes: #945023) + * [x86] KVM: x86: introduce is_pae_paging (Regression in 4.19.77) [ Bastian Blank ] * [amd64/cloud-amd64] Re-enable RTC drivers. (closes: #931341) diff --git a/debian/patches/bugfix/x86/KVM-x86-introduce-is_pae_paging.patch b/debian/patches/bugfix/x86/KVM-x86-introduce-is_pae_paging.patch new file mode 100644 index 000000000..5f593cf5e --- /dev/null +++ b/debian/patches/bugfix/x86/KVM-x86-introduce-is_pae_paging.patch @@ -0,0 +1,113 @@ +From: Paolo Bonzini +Date: Thu, 6 Jun 2019 18:52:44 +0200 +Subject: KVM: x86: introduce is_pae_paging +Origin: https://git.kernel.org/linus/bf03d4f9334728bf7c8ffc7de787df48abd6340e +Bug: https://bugzilla.kernel.org/show_bug.cgi?id=205441 +Bug: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1851709 +Bug: https://lore.kernel.org/lkml/68d02406-b9cc-2fc1-848c-5d272d9a3350@proxmox.com/ + +Checking for 32-bit PAE is quite common around code that fiddles with +the PDPTRs. Add a function to compress all checks into a single +invocation. + +Moving to the common helper also fixes a subtle bug in kvm_set_cr3() +where it fails to check is_long_mode() and results in KVM incorrectly +attempting to load PDPTRs for a 64-bit guest. + +Reviewed-by: Sean Christopherson +Signed-off-by: Paolo Bonzini +[sean: backport to 4.x; handle vmx.c split in 5.x, call out the bugfix] +Signed-off-by: Sean Christopherson +Acked-by: Paolo Bonzini +Tested-by: Thomas Lamprecht +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/vmx.c | 7 +++---- + arch/x86/kvm/x86.c | 8 ++++---- + arch/x86/kvm/x86.h | 5 +++++ + 3 files changed, 12 insertions(+), 8 deletions(-) + +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index 4eda2a9c234a..1ab4bb3d6a04 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -5173,7 +5173,7 @@ static void ept_load_pdptrs(struct kvm_vcpu *vcpu) + (unsigned long *)&vcpu->arch.regs_dirty)) + return; + +- if (is_paging(vcpu) && is_pae(vcpu) && !is_long_mode(vcpu)) { ++ if (is_pae_paging(vcpu)) { + vmcs_write64(GUEST_PDPTR0, mmu->pdptrs[0]); + vmcs_write64(GUEST_PDPTR1, mmu->pdptrs[1]); + vmcs_write64(GUEST_PDPTR2, mmu->pdptrs[2]); +@@ -5185,7 +5185,7 @@ static void ept_save_pdptrs(struct kvm_vcpu *vcpu) + { + struct kvm_mmu *mmu = vcpu->arch.walk_mmu; + +- if (is_paging(vcpu) && is_pae(vcpu) && !is_long_mode(vcpu)) { ++ if (is_pae_paging(vcpu)) { + mmu->pdptrs[0] = vmcs_read64(GUEST_PDPTR0); + mmu->pdptrs[1] = vmcs_read64(GUEST_PDPTR1); + mmu->pdptrs[2] = vmcs_read64(GUEST_PDPTR2); +@@ -12013,8 +12013,7 @@ static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool ne + * If PAE paging and EPT are both on, CR3 is not used by the CPU and + * must not be dereferenced. + */ +- if (!is_long_mode(vcpu) && is_pae(vcpu) && is_paging(vcpu) && +- !nested_ept) { ++ if (is_pae_paging(vcpu) && !nested_ept) { + if (!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3)) { + *entry_failure_code = ENTRY_FAIL_PDPTE; + return 1; +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index e536503ac788..6cf8af022b21 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -634,7 +634,7 @@ bool pdptrs_changed(struct kvm_vcpu *vcpu) + gfn_t gfn; + int r; + +- if (is_long_mode(vcpu) || !is_pae(vcpu) || !is_paging(vcpu)) ++ if (!is_pae_paging(vcpu)) + return false; + + if (!test_bit(VCPU_EXREG_PDPTR, +@@ -885,8 +885,8 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) + if (is_long_mode(vcpu) && + (cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 63))) + return 1; +- else if (is_pae(vcpu) && is_paging(vcpu) && +- !load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3)) ++ else if (is_pae_paging(vcpu) && ++ !load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3)) + return 1; + + kvm_mmu_new_cr3(vcpu, cr3, skip_tlb_flush); +@@ -8348,7 +8348,7 @@ static int __set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) + kvm_update_cpuid(vcpu); + + idx = srcu_read_lock(&vcpu->kvm->srcu); +- if (!is_long_mode(vcpu) && is_pae(vcpu) && is_paging(vcpu)) { ++ if (is_pae_paging(vcpu)) { + load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu)); + mmu_reset_needed = 1; + } +diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h +index 3a91ea760f07..608e5f8c5d0a 100644 +--- a/arch/x86/kvm/x86.h ++++ b/arch/x86/kvm/x86.h +@@ -139,6 +139,11 @@ static inline int is_paging(struct kvm_vcpu *vcpu) + return likely(kvm_read_cr0_bits(vcpu, X86_CR0_PG)); + } + ++static inline bool is_pae_paging(struct kvm_vcpu *vcpu) ++{ ++ return !is_long_mode(vcpu) && is_pae(vcpu) && is_paging(vcpu); ++} ++ + static inline u32 bit(int bitno) + { + return 1 << (bitno & 31); +-- +2.20.1 + diff --git a/debian/patches/series b/debian/patches/series index 4a4743aa1..0f6d9349f 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -80,6 +80,7 @@ bugfix/arm/ARM-dts-sun8i-h3-add-sy8106a-to-orange-pi-plus.patch bugfix/arm64/arm64-dts-allwinner-a64-Enable-A64-timer-workaround.patch bugfix/mips/MIPS-Loongson-Introduce-and-use-loongson_llsc_mb.patch bugfix/powerpc/powerpc-vdso-make-vdso32-installation-conditional-in.patch +bugfix/x86/KVM-x86-introduce-is_pae_paging.patch # Arch features features/mips/MIPS-increase-MAX-PHYSMEM-BITS-on-Loongson-3-only.patch