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 <[email protected]>
> Signed-off-by: Xinhao Xu <[email protected]>
> ---
> 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html