kvm: x86: mmio: fix setting the present bit of mmio spte
PATCH v2 1/1 kvm: x86: mmio: fix setting the present bit of mmio spte
In non-ept 64-bit of PAE case maxphyaddr may be 52bit as well, so we also need to disable mmio page fault. Here we can check MMIO_SPTE_GEN_HIGH_SHIFT directly to determine if we should set the present bit, and bring a little cleanup.
---
v2:
* Correct codes comments
* Need to use "|=" to set the present bit
arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/mmu.c | 25 +++++++++++++++++++++++++ arch/x86/kvm/x86.c | 30 ------------------------------ 3 files changed, 26 insertions(+), 30 deletions(-)
arch/x86/include/asm/kvm_host.h +1 -0
@@ -809,6 +809,7 @@ void kvm_mmu_write_protect_pt_masked(struct kvm *kvm,struct kvm_memory_slot *slot, gfn_t gfn_offset, unsigned long mask);void kvm_mmu_zap_all (struct kvm *kvm); +void kvm_set_mmio_spte_mask (void );void kvm_mmu_invalidate_mmio_sptes (struct kvm *kvm);unsigned int kvm_mmu_calculate_mmu_pages (struct kvm *kvm);void kvm_mmu_change_mmu_pages (struct kvm *kvm,unsigned int kvm_nr_mmu_pages);
arch/x86/kvm/mmu.c +25 -0
@@ -295,6 +295,31 @@ static bool check_mmio_spte(struct kvm *kvm, u64 spte)return likely (kvm_gen == spte_gen); } +/* +* Set the reserved bits and the present bit of an paging-structure +* entry to generate page fault with PFER.RSV = 1. +*/ +void kvm_set_mmio_spte_mask (void ) +{ +u64 mask; +int maxphyaddr = boot_cpu_data.x86_phys_bits; + +/* Mask the reserved physical address bits. */ + mask =rsvd_bits (maxphyaddr,MMIO_SPTE_GEN_HIGH_SHIFT -1 ); + +/* Magic bits are always reserved to identify mmio spte. +* On 32 bit systems we have bit 62. +*/ + mask |=0x3ull <<62 ; + +/* Set the present bit to enable mmio page fault. */ +if (maxphyaddr <MMIO_SPTE_GEN_HIGH_SHIFT ) + mask |=PT_PRESENT_MASK ; + +kvm_mmu_set_mmio_spte_mask (mask); +} +EXPORT_SYMBOL_GPL (kvm_set_mmio_spte_mask); +void kvm_mmu_set_mask_ptes (u64 user_mask,u64 accessed_mask,u64 dirty_mask,u64 nx_mask,u64 x_mask) {
arch/x86/kvm/x86.c +0 -30
@@ -5596,36 +5596,6 @@ void kvm_after_handle_nmi(struct kvm_vcpu *vcpu) }EXPORT_SYMBOL_GPL (kvm_after_handle_nmi); -static void kvm_set_mmio_spte_mask (void ) -{ -u64 mask; -int maxphyaddr = boot_cpu_data.x86_phys_bits; - -/* -* Set the reserved bits and the present bit of an paging-structure -* entry to generate page fault with PFER.RSV = 1. -*/ -/* Mask the reserved physical address bits. */ - mask =rsvd_bits (maxphyaddr,51 ); - -/* Bit 62 is always reserved for 32bit host. */ - mask |=0x3ull <<62 ; - -/* Set the present bit. */ - mask |=1ull ; - -#ifdef CONFIG_X86_64 -/* -* If reserved bit is not supported, clear the present bit to disable -* mmio page fault. -*/ -if (maxphyaddr ==52 ) - mask &= ~1ull ; -#endif - -kvm_mmu_set_mmio_spte_mask (mask); -} -#ifdef CONFIG_X86_64 static void pvclock_gtod_update_fn (struct work_struct *work) {
Signature · 1 line
1.9.1
Paolo Bonzini
maintainerQuoted 1 line · Tiejun Chen
In non-ept 64-bit of PAE case maxphyaddr may be 52bit as well,
There is no such thing as 64-bit PAE.
On 32-bit PAE hosts, PTEs have bit 62 reserved, as in your patch:
Review
Quoted 2 lines
(quoted diff) +2
-0+ /* Magic bits are always reserved for 32bit host. */ + mask |= 0x3ull << 62;
so there is no need to disable the MMIO page fault.
Paolo
Quoted 7 lines · Paolo Bonzini
Quoted 1 line · Tiejun Chen
In non-ept 64-bit of PAE case maxphyaddr may be 52bit as well,
There is no such thing as 64-bit PAE.
Definitely.
Quoted 2 lines
On 32-bit PAE hosts, PTEs have bit 62 reserved, as in your patch:
Do you mean just one reserved bit is fine enough in this case?
Thanks
Tiejun
Paolo Bonzini
maintainerQuoted 3 lines · Tiejun
Quoted 1 line
On 32-bit PAE hosts, PTEs have bit 62 reserved, as in your patch:
Do you mean just one reserved bit is fine enough in this case?
Yes.
Paolo