linux/arch/x86/kvm/mmu
Vitaly Kuznetsov 9a2a0d3ca1 kvm: x86/mmu: Fix get_mmio_spte() on CPUs supporting 5-level PT
Commit 95fb5b0258 ("kvm: x86/mmu: Support MMIO in the TDP MMU") caused
the following WARNING on an Intel Ice Lake CPU:

 get_mmio_spte: detect reserved bits on spte, addr 0xb80a0, dump hierarchy:
 ------ spte 0xb80a0 level 5.
 ------ spte 0xfcd210107 level 4.
 ------ spte 0x1004c40107 level 3.
 ------ spte 0x1004c41107 level 2.
 ------ spte 0x1db00000000b83b6 level 1.
 WARNING: CPU: 109 PID: 10254 at arch/x86/kvm/mmu/mmu.c:3569 kvm_mmu_page_fault.cold.150+0x54/0x22f [kvm]
...
 Call Trace:
  ? kvm_io_bus_get_first_dev+0x55/0x110 [kvm]
  vcpu_enter_guest+0xaa1/0x16a0 [kvm]
  ? vmx_get_cs_db_l_bits+0x17/0x30 [kvm_intel]
  ? skip_emulated_instruction+0xaa/0x150 [kvm_intel]
  kvm_arch_vcpu_ioctl_run+0xca/0x520 [kvm]

The guest triggering this crashes. Note, this happens with the traditional
MMU and EPT enabled, not with the newly introduced TDP MMU. Turns out,
there was a subtle change in the above mentioned commit. Previously,
walk_shadow_page_get_mmio_spte() was setting 'root' to 'iterator.level'
which is returned by shadow_walk_init() and this equals to
'vcpu->arch.mmu->shadow_root_level'. Now, get_mmio_spte() sets it to
'int root = vcpu->arch.mmu->root_level'.

The difference between 'root_level' and 'shadow_root_level' on CPUs
supporting 5-level page tables is that in some case we don't want to
use 5-level, in particular when 'cpuid_maxphyaddr(vcpu) <= 48'
kvm_mmu_get_tdp_level() returns '4'. In case upper layer is not used,
the corresponding SPTE will fail '__is_rsvd_bits_set()' check.

Revert to using 'shadow_root_level'.

Fixes: 95fb5b0258 ("kvm: x86/mmu: Support MMIO in the TDP MMU")
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20201126110206.2118959-1-vkuznets@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2020-11-27 11:14:27 -05:00
..
mmu.c kvm: x86/mmu: Fix get_mmio_spte() on CPUs supporting 5-level PT 2020-11-27 11:14:27 -05:00
mmu_audit.c KVM: x86/mmu: Rename page_header() to to_shadow_page() 2020-07-08 16:21:55 -04:00
mmu_internal.h kvm: x86/mmu: NX largepage recovery for TDP MMU 2020-10-23 03:42:16 -04:00
mmutrace.h kvm: x86/mmu: Add TDP MMU PF handler 2020-10-23 03:42:04 -04:00
page_track.c kvm: mmu: page_track: Fix RCU list API usage 2020-08-24 18:36:23 -07:00
paging_tmpl.h kvm: x86/mmu: Remove disallowed_hugepage_adjust shadow_walk_iterator arg 2020-10-21 18:17:02 -04:00
spte.c KVM: x86: replace static const variables with macros 2020-10-30 13:39:55 -04:00
spte.h KVM: x86: replace static const variables with macros 2020-10-30 13:39:55 -04:00
tdp_iter.c kvm: x86/mmu: Support zapping SPTEs in the TDP MMU 2020-10-21 18:17:02 -04:00
tdp_iter.h kvm: x86/mmu: Support dirty logging for the TDP MMU 2020-10-23 03:42:13 -04:00
tdp_mmu.c kvm: mmu: fix is_tdp_mmu_check when the TDP MMU is not in use 2020-11-15 08:55:43 -05:00
tdp_mmu.h kvm: x86/mmu: Support MMIO in the TDP MMU 2020-10-23 03:42:15 -04:00