On 05/19/2013 12:52 PM, Jun Nakajima wrote: > Add code to detect EPT misconfiguration and inject it to L1 VMM. Also, > it injects more correct exit qualification upon EPT violation to L1 > VMM. Now L1 can correctly go to ept_misconfig handler (instead of > wrongly going to fast_page_fault), it will try to handle mmio page > fault, if failed, it is a real EPT misconfiguration. > > Signed-off-by: Jun Nakajima <jun.nakajima@xxxxxxxxx> > Signed-off-by: Xinhao Xu <xinhao.xu@xxxxxxxxx> > --- > arch/x86/include/asm/kvm_host.h | 4 +++ > arch/x86/kvm/mmu.c | 5 --- > arch/x86/kvm/mmu.h | 5 +++ > arch/x86/kvm/paging_tmpl.h | 26 ++++++++++++++ > arch/x86/kvm/vmx.c | 79 +++++++++++++++++++++++++++++++++++++++-- > 5 files changed, 111 insertions(+), 8 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 3741c65..1d03202 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -262,6 +262,8 @@ struct kvm_mmu { > void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva); > void (*update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, > u64 *spte, const void *pte); > + bool (*check_tdp_pte)(u64 pte, int level); > + > hpa_t root_hpa; > int root_level; > int shadow_root_level; > @@ -503,6 +505,8 @@ struct kvm_vcpu_arch { > * instruction. > */ > bool write_fault_to_shadow_pgtable; > + > + unsigned long exit_qualification; /* set at EPT violation at this point */ > }; > > struct kvm_lpage_info { > diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c > index 93d6abf..3a3b11f 100644 > --- a/arch/x86/kvm/mmu.c > +++ b/arch/x86/kvm/mmu.c > @@ -233,11 +233,6 @@ static bool set_mmio_spte(u64 *sptep, gfn_t gfn, pfn_t pfn, unsigned access) > return false; > } > > -static inline u64 rsvd_bits(int s, int e) > -{ > - return ((1ULL << (e - s + 1)) - 1) << s; > -} > - > void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, > u64 dirty_mask, u64 nx_mask, u64 x_mask) > { > diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h > index 8fc94dd..559e2e0 100644 > --- a/arch/x86/kvm/mmu.h > +++ b/arch/x86/kvm/mmu.h > @@ -88,6 +88,11 @@ static inline bool is_write_protection(struct kvm_vcpu *vcpu) > return kvm_read_cr0_bits(vcpu, X86_CR0_WP); > } > > +static inline u64 rsvd_bits(int s, int e) > +{ > + return ((1ULL << (e - s + 1)) - 1) << s; > +} > + > /* > * Will a fault with a given page-fault error code (pfec) cause a permission > * fault with the given access (in ACC_* format)? > diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h > index 2432d49..067b1f8 100644 > --- a/arch/x86/kvm/paging_tmpl.h > +++ b/arch/x86/kvm/paging_tmpl.h > @@ -126,10 +126,14 @@ static int FNAME(cmpxchg_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, > > static bool FNAME(is_rsvd_bits_set)(struct kvm_mmu *mmu, u64 gpte, int level) > { > +#if PTTYPE == PTTYPE_EPT > + return (mmu->check_tdp_pte(gpte, level)); > +#else > int bit7; > > bit7 = (gpte >> 7) & 1; > return (gpte & mmu->rsvd_bits_mask[bit7][level-1]) != 0; > +#endif > } It is better that set mmu->check_tdp_pte = is_rsvd_bits_set for the current modes, then this part can be moved to mmu.c > > static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu, > @@ -352,6 +356,28 @@ error: > walker->fault.vector = PF_VECTOR; > walker->fault.error_code_valid = true; > walker->fault.error_code = errcode; > + > +#if PTTYPE == PTTYPE_EPT > + /* > + * Use PFERR_RSVD_MASK in erorr_code to to tell if EPT > + * misconfiguration requires to be injected. The detection is > + * done by is_rsvd_bits_set() above. > + * > + * We set up the value of exit_qualification to inject: > + * [2:0] -- Derive from [2:0] of real exit_qualification at EPT violation > + * [5:3] -- Calculated by the page walk of the guest EPT page tables > + * [7:8] -- Clear to 0. > + * > + * The other bits are set to 0. > + */ > + if (!(errcode & PFERR_RSVD_MASK)) { > + unsigned long exit_qualification = vcpu->arch.exit_qualification; > + > + pte_access = pt_access & pte; > + vcpu->arch.exit_qualification = ((pte_access & 0x7) << 3) | > + (exit_qualification & 0x7); > + } > +#endif This specified operations can be move to nested_ept_inject_page_fault()? -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html