Introduce page table population function for direct build EPT feature
RFC 2/9 Introduce page table population function for direct build EPT feature
From: Yulei Zhang <[email protected]>
Page table population function will pin the memory and pre-construct the EPT base on the input memory slot configuration so that it won't relay on the page fault interrupt to setup the page table.
Signed-off-by Yulei Zhang <[email protected]>
--- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/mmu/mmu.c | 212 +++++++++++++++++++++++++++++++- arch/x86/kvm/svm/svm.c | 2 +- arch/x86/kvm/vmx/vmx.c | 17 ++- include/linux/kvm_host.h | 4 +- virt/kvm/kvm_main.c | 30 ++++- 6 files changed, 250 insertions(+), 17 deletions(-)
arch/x86/include/asm/kvm_host.h +1 -1
@@ -1152,7 +1152,7 @@ struct kvm_x86_ops {int (*set_tss_addr)(struct kvm *kvm,unsigned int addr);int (*set_identity_map_addr)(struct kvm *kvm,u64 ident_addr);int (*get_tdp_level)(struct kvm_vcpu *vcpu); -u64 (*get_mt_mask)(struct kvm_vcpu *vcpu,gfn_t gfn,bool is_mmio); +u64 (*get_mt_mask)(struct kvm *kvm,struct kvm_vcpu *vcpu,gfn_t gfn,bool is_mmio);void (*load_mmu_pgd)(struct kvm_vcpu *vcpu,unsigned long cr3);
arch/x86/kvm/mmu/mmu.c +208 -4
240 lines not on this page · raw message
arch/x86/kvm/svm/svm.c +1 -1
@@ -3488,7 +3488,7 @@ static bool svm_has_emulated_msr(int index)return true; } -static u64 svm_get_mt_mask (struct kvm_vcpu *vcpu,gfn_t gfn,bool is_mmio) +static u64 svm_get_mt_mask (struct kvm *kvm,struct kvm_vcpu *vcpu,gfn_t gfn,bool is_mmio) {return 0 ; }
arch/x86/kvm/vmx/vmx.c +11 -6
@@ -2972,10 +2972,12 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)static int get_ept_level (struct kvm_vcpu *vcpu) { -if (is_guest_mode (vcpu) &&nested_cpu_has_ept (get_vmcs12 (vcpu))) -return vmx_eptp_page_walk_level (nested_ept_get_eptp (vcpu)); -if (cpu_has_vmx_ept_5levels () && (cpuid_maxphyaddr (vcpu) >48 )) -return 5 ; +if (vcpu) { +if (is_guest_mode (vcpu) &&nested_cpu_has_ept (get_vmcs12 (vcpu))) +return vmx_eptp_page_walk_level (nested_ept_get_eptp (vcpu)); +if (cpu_has_vmx_ept_5levels () && (cpuid_maxphyaddr (vcpu) >48 )) +return 5 ; + }return 4 ; }
@@ -6861,7 +6863,7 @@ static int __init vmx_check_processor_compat(void)return 0 ; } -static u64 vmx_get_mt_mask (struct kvm_vcpu *vcpu,gfn_t gfn,bool is_mmio) +static u64 vmx_get_mt_mask (struct kvm *kvm,struct kvm_vcpu *vcpu,gfn_t gfn,bool is_mmio) {u8 cache;u64 ipat =0 ;
@@ -6889,12 +6891,15 @@ static u64 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio) goto exit; } -if (!kvm_arch_has_noncoherent_dma (vcpu->kvm)) { +if (!kvm_arch_has_noncoherent_dma (kvm)) { ipat =VMX_EPT_IPAT_BIT ; cache =MTRR_TYPE_WRBACK ; goto exit; } +if (!vcpu) + vcpu = kvm->vcpus[0 ]; +if (kvm_read_cr0 (vcpu) &X86_CR0_CD ) { ipat =VMX_EPT_IPAT_BIT ;if (kvm_check_has_quirk (vcpu->kvm,KVM_X86_QUIRK_CD_NW_CLEARED ))
include/linux/kvm_host.h +3 -1
@@ -693,6 +693,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,struct kvm_memory_slot *old, const struct kvm_memory_slot *new, enum kvm_mr_change change); +void mark_page_dirty_in_slot (struct kvm_memory_slot *memslot,gfn_t gfn);/* flush all memory translations */ void kvm_arch_flush_shadow_all (struct kvm *kvm);/* flush memory translations pointing to 'slot' */
@@ -720,6 +721,7 @@ kvm_pfn_t gfn_to_pfn_memslot_atomic(struct kvm_memory_slot *slot, gfn_t gfn);kvm_pfn_t __gfn_to_pfn_memslot (struct kvm_memory_slot *slot,gfn_t gfn,bool atomic,bool *async,bool write_fault,bool *writable); +kvm_pfn_t gfn_to_pfn_try_write (struct kvm_memory_slot *slot,gfn_t gfn);void kvm_release_pfn_clean (kvm_pfn_t pfn);void kvm_release_pfn_dirty (kvm_pfn_t pfn);
@@ -770,7 +772,7 @@ int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);int kvm_clear_guest (struct kvm *kvm,gpa_t gpa,unsigned long len);struct kvm_memory_slot *gfn_to_memslot (struct kvm *kvm,gfn_t gfn);bool kvm_is_visible_gfn (struct kvm *kvm,gfn_t gfn); -unsigned long kvm_host_page_size (struct kvm_vcpu *vcpu,gfn_t gfn); +unsigned long kvm_host_page_size (struct kvm *kvm,struct kvm_vcpu *vcpu,gfn_t gfn);void mark_page_dirty (struct kvm *kvm,gfn_t gfn);struct kvm_memslots *kvm_vcpu_memslots (struct kvm_vcpu *vcpu);
virt/kvm/kvm_main.c +26 -4
@@ -144,7 +144,7 @@ static void hardware_disable_all(void);static void kvm_io_bus_destroy (struct kvm_io_bus *bus); -static void mark_page_dirty_in_slot (struct kvm_memory_slot *memslot,gfn_t gfn); +void mark_page_dirty_in_slot (struct kvm_memory_slot *memslot,gfn_t gfn); __visible bool kvm_rebooting;EXPORT_SYMBOL_GPL (kvm_rebooting);
@@ -1629,14 +1629,17 @@ bool kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn) }EXPORT_SYMBOL_GPL (kvm_is_visible_gfn); -unsigned long kvm_host_page_size (struct kvm_vcpu *vcpu,gfn_t gfn) +unsigned long kvm_host_page_size (struct kvm *kvm,struct kvm_vcpu *vcpu,gfn_t gfn) {struct vm_area_struct *vma;unsigned long addr, size; size =PAGE_SIZE ; - addr =kvm_vcpu_gfn_to_hva_prot (vcpu, gfn,NULL ); +if (vcpu) + addr =kvm_vcpu_gfn_to_hva_prot (vcpu, gfn,NULL ); +else + addr =gfn_to_hva (kvm, gfn);if (kvm_is_error_hva (addr))return PAGE_SIZE ;
@@ -1931,6 +1934,25 @@ static kvm_pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool *async,return pfn; } +/* Map pfn for direct EPT mode, if map failed and it is readonly memslot, +* will try to remap it with readonly flag. +*/ +kvm_pfn_t gfn_to_pfn_try_write (struct kvm_memory_slot *slot,gfn_t gfn) +{ +kvm_pfn_t pfn; +unsigned long addr =__gfn_to_hva_many (slot, gfn,NULL , !memslot_is_readonly (slot)); + +if (kvm_is_error_hva (addr)) +return KVM_PFN_NOSLOT ; + + pfn =hva_to_pfn (addr, false,NULL , true,NULL ); +if (pfn &KVM_PFN_ERR_FAULT ) { +if (memslot_is_readonly (slot)) + pfn =hva_to_pfn (addr, false,NULL , false,NULL ); + } +return pfn; +} +kvm_pfn_t __gfn_to_pfn_memslot (struct kvm_memory_slot *slot,gfn_t gfn,bool atomic,bool *async,bool write_fault,bool *writable)
@@ -2571,7 +2593,7 @@ int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len) }EXPORT_SYMBOL_GPL (kvm_clear_guest); -static void mark_page_dirty_in_slot (struct kvm_memory_slot *memslot, +void mark_page_dirty_in_slot (struct kvm_memory_slot *memslot,gfn_t gfn) {if (memslot && memslot->dirty_bitmap) {
Signature · 1 line
2.17.1