[PATCH RFC] KVM: SVM: reduce guest MAXPHYADDR by one in case C-bit is a physical bit

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Several selftests (memslot_modification_stress_test, kvm_page_table_test,
dirty_log_perf_test,.. ) which rely on vm_get_max_gfn() started to fail
since commit ef4c9f4f65462 ("KVM: selftests: Fix 32-bit truncation of
vm_get_max_gfn()") on AMD EPYC 7401P:

 ./tools/testing/selftests/kvm/demand_paging_test
 Testing guest mode: PA-bits:ANY, VA-bits:48,  4K pages
 guest physical test memory offset: 0xffffbffff000
 Finished creating vCPUs and starting uffd threads
 Started all vCPUs
 ==== Test Assertion Failure ====
   demand_paging_test.c:63: false
   pid=47131 tid=47134 errno=0 - Success
      1	0x000000000040281b: vcpu_worker at demand_paging_test.c:63
      2	0x00007fb36716e431: ?? ??:0
      3	0x00007fb36709c912: ?? ??:0
   Invalid guest sync status: exit_reason=SHUTDOWN

The commit, however, seems to be correct, it just revealed an already
present issue. AMD CPUs which support SEV may have a reduced physical
address space, e.g. on AMD EPYC 7401P I see:

 Address sizes:  43 bits physical, 48 bits virtual

The guest physical address space, however, is not reduced as stated in
commit e39f00f60ebd ("KVM: x86: Use kernel's x86_phys_bits to handle
reduced MAXPHYADDR"). This seems to be almost correct, however, APM has one
more clause (15.34.6):

  Note that because guest physical addresses are always translated through
  the nested page tables, the size of the guest physical address space is
  not impacted by any physical address space reduction indicated in CPUID
  8000_001F[EBX]. If the C-bit is a physical address bit however, the guest
  physical address space is effectively reduced by 1 bit.

Implement the reduction.

Fixes: e39f00f60ebd (KVM: x86: Use kernel's x86_phys_bits to handle reduced MAXPHYADDR)
Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx>
---
- RFC: I may have misdiagnosed the problem as I didn't dig to where exactly
 the guest crashes.
---
 arch/x86/kvm/cpuid.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 751aa85a3001..04ae280a0b66 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -923,13 +923,20 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
 		 *
 		 * If TDP is enabled but an explicit guest MAXPHYADDR is not
 		 * provided, use the raw bare metal MAXPHYADDR as reductions to
-		 * the HPAs do not affect GPAs.
+		 * the HPAs do not affect GPAs. The value, however, has to be
+		 * reduced by 1 in case C-bit is a physical bit (APM section
+		 * 15.34.6).
 		 */
-		if (!tdp_enabled)
+		if (!tdp_enabled) {
 			g_phys_as = boot_cpu_data.x86_phys_bits;
-		else if (!g_phys_as)
+		} else if (!g_phys_as) {
 			g_phys_as = phys_as;
 
+			if (kvm_cpu_cap_has(X86_FEATURE_SEV) &&
+			    (cpuid_ebx(0x8000001f) & 0x3f) < g_phys_as)
+				g_phys_as -= 1;
+		}
+
 		entry->eax = g_phys_as | (virt_as << 8);
 		entry->edx = 0;
 		cpuid_entry_override(entry, CPUID_8000_0008_EBX);
-- 
2.31.1




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux