Re: [PATCH v4 1/5] KVM: MMU: fix release noslot pfn

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Oct 11, 2012 at 09:06:12PM +0800, Xiao Guangrong wrote:
> On 10/10/2012 11:11 PM, Marcelo Tosatti wrote:
> 
> > 
> > Why does is_error_pfn() return true for mmio spte? Its not an "error",
> > after all. 
> > 
> > Please kill is_invalid_pfn and use
> > 
> > -> is_error_pfn for checking for errors (mmio spte is not an error pfn,
> > its a special pfn)
> > 
> > -> add explicit is_noslot_pfn checks where necessary in the code
> > (say to avoid interpreting a noslot_pfn's pfn "address" bits).
> > 
> > (should have noticed this earlier, sorry).
> 
> Never mind, your comments are always appreciated! ;)
> 
> Marcelo, is it good to you?
> (will post it after your check and full test)

Yes, this works (please check the validity of each case in addition to
testing, haven't done it).

Also add a oneline comment on top of each
is_error_pfn,is_noslot_pfn,is_error_noslot_pfn

/* is_noslot_pfn: userspace translation valid but no memory slot */
/* is_error_pfn: ... */

etc.

Thanks.

> diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
> index 837f13e..3a4d967 100644
> --- a/arch/powerpc/kvm/book3s_32_mmu_host.c
> +++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
> @@ -155,7 +155,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
> 
>  	/* Get host physical address for gpa */
>  	hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT);
> -	if (is_error_pfn(hpaddr)) {
> +	if (is_error_noslot_pfn(hpaddr)) {
>  		printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n",
>  				 orig_pte->eaddr);
>  		r = -EINVAL;
> diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
> index 0688b6b..6c230a2 100644
> --- a/arch/powerpc/kvm/book3s_64_mmu_host.c
> +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
> @@ -92,7 +92,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
> 
>  	/* Get host physical address for gpa */
>  	hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT);
> -	if (is_error_pfn(hpaddr)) {
> +	if (is_error_noslot_pfn(hpaddr)) {
>  		printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte->eaddr);
>  		r = -EINVAL;
>  		goto out;
> diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
> index ff38b66..4b47eeb 100644
> --- a/arch/powerpc/kvm/e500_tlb.c
> +++ b/arch/powerpc/kvm/e500_tlb.c
> @@ -521,7 +521,7 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
>  	if (likely(!pfnmap)) {
>  		unsigned long tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
>  		pfn = gfn_to_pfn_memslot(slot, gfn);
> -		if (is_error_pfn(pfn)) {
> +		if (is_error_noslot_pfn(pfn)) {
>  			printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
>  					(long)gfn);
>  			return;
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index 56c0e39..54c3557 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -2699,7 +2699,7 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
>  	 * PT_PAGE_TABLE_LEVEL and there would be no adjustment done
>  	 * here.
>  	 */
> -	if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn) &&
> +	if (!is_error_noslot_pfn(pfn) && !kvm_is_mmio_pfn(pfn) &&
>  	    level == PT_PAGE_TABLE_LEVEL &&
>  	    PageTransCompound(pfn_to_page(pfn)) &&
>  	    !has_wrprotected_page(vcpu->kvm, gfn, PT_DIRECTORY_LEVEL)) {
> @@ -2733,7 +2733,7 @@ static bool handle_abnormal_pfn(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn,
>  	bool ret = true;
> 
>  	/* The pfn is invalid, report the error! */
> -	if (unlikely(is_invalid_pfn(pfn))) {
> +	if (unlikely(is_error_pfn(pfn))) {
>  		*ret_val = kvm_handle_bad_page(vcpu, gfn, pfn);
>  		goto exit;
>  	}
> diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c
> index daff69e..7709a75 100644
> --- a/arch/x86/kvm/mmu_audit.c
> +++ b/arch/x86/kvm/mmu_audit.c
> @@ -116,7 +116,7 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level)
>  	gfn = kvm_mmu_page_get_gfn(sp, sptep - sp->spt);
>  	pfn = gfn_to_pfn_atomic(vcpu->kvm, gfn);
> 
> -	if (is_error_pfn(pfn))
> +	if (is_error_noslot_pfn(pfn))
>  		return;
> 
>  	hpa =  pfn << PAGE_SHIFT;
> diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
> index f887e4c..89f3241 100644
> --- a/arch/x86/kvm/paging_tmpl.h
> +++ b/arch/x86/kvm/paging_tmpl.h
> @@ -323,7 +323,7 @@ FNAME(prefetch_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
>  	protect_clean_gpte(&pte_access, gpte);
>  	pfn = pte_prefetch_gfn_to_pfn(vcpu, gfn,
>  			no_dirty_log && (pte_access & ACC_WRITE_MASK));
> -	if (is_invalid_pfn(pfn))
> +	if (is_error_pfn(pfn))
>  		return false;
> 
>  	/*
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 1eefebe..91f8f71 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -4502,7 +4502,7 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva)
>  	 * instruction -> ...
>  	 */
>  	pfn = gfn_to_pfn(vcpu->kvm, gpa_to_gfn(gpa));
> -	if (!is_error_pfn(pfn)) {
> +	if (!is_error_noslot_pfn(pfn)) {
>  		kvm_release_pfn_clean(pfn);
>  		return true;
>  	}
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 93bfc9f..45ff7c6 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -58,28 +58,30 @@
> 
>  /*
>   * For the normal pfn, the highest 12 bits should be zero,
> - * so we can mask these bits to indicate the error.
> + * so we can mask bit 62 ~ bit 52  to indicate the error pfn,
> + * mask bit 63 to indicate the noslot pfn.
>   */
> -#define KVM_PFN_ERR_MASK	(0xfffULL << 52)
> +#define KVM_PFN_ERR_MASK	(0x7ffULL << 52)
> +#define KVM_PFN_ERR_NOSLOT_MASK	(0xfffULL << 52)
> +#define KVM_PFN_NOSLOT		(0x1ULL << 63)
> 
>  #define KVM_PFN_ERR_FAULT	(KVM_PFN_ERR_MASK)
>  #define KVM_PFN_ERR_HWPOISON	(KVM_PFN_ERR_MASK + 1)
> -#define KVM_PFN_ERR_BAD		(KVM_PFN_ERR_MASK + 2)
> -#define KVM_PFN_ERR_RO_FAULT	(KVM_PFN_ERR_MASK + 3)
> +#define KVM_PFN_ERR_RO_FAULT	(KVM_PFN_ERR_MASK + 2)
> 
>  static inline bool is_error_pfn(pfn_t pfn)
>  {
>  	return !!(pfn & KVM_PFN_ERR_MASK);
>  }
> 
> -static inline bool is_noslot_pfn(pfn_t pfn)
> +static inline bool is_error_noslot_pfn(pfn_t pfn)
>  {
> -	return pfn == KVM_PFN_ERR_BAD;
> +	return !!(pfn & KVM_PFN_ERR_NOSLOT_MASK);
>  }
> 
> -static inline bool is_invalid_pfn(pfn_t pfn)
> +static inline bool is_noslot_pfn(pfn_t pfn)
>  {
> -	return !is_noslot_pfn(pfn) && is_error_pfn(pfn);
> +	return pfn == KVM_PFN_NOSLOT;
>  }
> 
>  #define KVM_HVA_ERR_BAD		(PAGE_OFFSET)
> diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
> index 037cb67..5534f46 100644
> --- a/virt/kvm/iommu.c
> +++ b/virt/kvm/iommu.c
> @@ -52,7 +52,7 @@ static pfn_t kvm_pin_pages(struct kvm_memory_slot *slot, gfn_t gfn,
>  	end_gfn = gfn + (size >> PAGE_SHIFT);
>  	gfn    += 1;
> 
> -	if (is_error_pfn(pfn))
> +	if (is_error_noslot_pfn(pfn))
>  		return pfn;
> 
>  	while (gfn < end_gfn)
> @@ -106,7 +106,7 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
>  		 * important because we unmap and unpin in 4kb steps later.
>  		 */
>  		pfn = kvm_pin_pages(slot, gfn, page_size);
> -		if (is_error_pfn(pfn)) {
> +		if (is_error_noslot_pfn(pfn)) {
>  			gfn += 1;
>  			continue;
>  		}
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index a65bc02..e26a55f 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -1208,7 +1208,7 @@ __gfn_to_pfn_memslot(struct kvm_memory_slot *slot, gfn_t gfn, bool atomic,
>  		return KVM_PFN_ERR_RO_FAULT;
> 
>  	if (kvm_is_error_hva(addr))
> -		return KVM_PFN_ERR_BAD;
> +		return KVM_PFN_NOSLOT;
> 
>  	/* Do not map writable pfn in the readonly memslot. */
>  	if (writable && memslot_is_readonly(slot)) {
> @@ -1290,7 +1290,7 @@ EXPORT_SYMBOL_GPL(gfn_to_page_many_atomic);
> 
>  static struct page *kvm_pfn_to_page(pfn_t pfn)
>  {
> -	if (is_error_pfn(pfn))
> +	if (is_error_noslot_pfn(pfn))
>  		return KVM_ERR_PTR_BAD_PAGE;
> 
>  	if (kvm_is_mmio_pfn(pfn)) {
> @@ -1322,7 +1322,7 @@ EXPORT_SYMBOL_GPL(kvm_release_page_clean);
> 
>  void kvm_release_pfn_clean(pfn_t pfn)
>  {
> -	if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn))
> +	if (!is_error_noslot_pfn(pfn) && !kvm_is_mmio_pfn(pfn))
>  		put_page(pfn_to_page(pfn));
>  }
>  EXPORT_SYMBOL_GPL(kvm_release_pfn_clean);
--
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


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux