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

Re: [Xen-devel] [PATCH 09/14] xen: Introduce HAS_M2P config and use to protect mfn_to_gmfn call



On Tue, 7 May 2019, Julien Grall wrote:
> While Arm never had a M2P, the implementation of mfn_to_gmfn is pretty
> bogus as we directly return the MFN passed in parameter.
> 
> Thankfully, the use of mfn_to_gmfn is pretty limited on Arm today. There
> are only 3 callers:
>     - iommu_hwdom_init: mfn_to_gmfn is used for creating IOMMU
>     page-tables when the P2M is not shared with the IOMMU. No issues so
>     far as Arm does not yet support non-shared P2M case.
>     - memory_exchange: Arm cannot not use it because steal_page is not
>     implemented.
>     - getdomaininfo: Toolstack may map the shared page. It looks like
>     this is mostly used for mapping the P2M of PV guest. Therefore the
>     issue might be minor.
> 
> Implementing the M2P on Arm is not planned. The M2P would require significant
> amount of VA address (very tough on 32-bit) that can hardly be justified with
> the current use of mfn_to_gmfn.
>     - iommu_hwdom_init: mfn_to_gmfn is used because the creating of the
>     IOMMU page-tables is delayed until the first device is assigned.
>     In the embedded case, we will known in most of the times what
>     devices are assigned during the domain creation. So it is possible
>     to take to enable the IOMMU from start. See [1] for the patch.
>     - memory_exchange: This does not work and I haven't seen any
>     request for it so far.
>     - getdomaininfo: The structure on Arm does not seem to contain a lot
>     of useful information on Arm. It is unclear whether we want to
>     allow the toolstack mapping it on Arm.
> 
> This patch introduces a config option HAS_M2P to tell whether an
> architecture implements the M2P.
>     - iommu_hwdom_init: For now, we require the M2P support when the IOMMU
>     is not sharing the P2M.
>     - memory_exchange: The hypercall is marked as not supported when the
>     M2P does not exist.
>     - getdomaininfo: A new helper is introduced to wrap the call to
>     mfn_to_gfn/mfn_to_gmfn. For Arm, it returns an invalid GFN so the mapping
>     will fail.
> 
> [1] https://patchwork.kernel.org/patch/9719913/
> 
> Signed-off-by Julien Grall <julien.grall@xxxxxxx>
> 
> ---
> 
> Cc: oleksandr_tyshchenko@xxxxxxxx
> Cc: andrii_anisov@xxxxxxxx
> 
>     Changes in v2:
>         - Add a warning in public headers
>         - Constify local variable in domain_shared_info_gfn
>         - Invert the naming (_d / d) in domain_shared_info_gfn
>         - Use -EOPNOTSUPP rather than -ENOSYS
>         - Rework how the memory_exchange hypercall is removed from Arm
> ---
>  xen/arch/x86/Kconfig            | 1 +
>  xen/common/Kconfig              | 3 +++
>  xen/common/domctl.c             | 2 +-
>  xen/common/memory.c             | 4 ++++
>  xen/drivers/passthrough/iommu.c | 6 +++++-
>  xen/include/asm-arm/domain.h    | 5 +++++
>  xen/include/public/domctl.h     | 4 ++++
>  xen/include/xen/domain.h        | 8 ++++++++
>  8 files changed, 31 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
> index 4b8b07b549..52922a87e7 100644
> --- a/xen/arch/x86/Kconfig
> +++ b/xen/arch/x86/Kconfig
> @@ -16,6 +16,7 @@ config X86
>       select HAS_IOPORTS
>       select HAS_KEXEC
>       select MEM_ACCESS_ALWAYS_ON
> +     select HAS_M2P
>       select HAS_MEM_PAGING
>       select HAS_MEM_SHARING
>       select HAS_NS16550
> diff --git a/xen/common/Kconfig b/xen/common/Kconfig
> index c838506241..df871adc8f 100644
> --- a/xen/common/Kconfig
> +++ b/xen/common/Kconfig
> @@ -63,6 +63,9 @@ config HAS_GDBSX
>  config HAS_IOPORTS
>       bool
>  
> +config HAS_M2P
> +     bool
> +
>  config NEEDS_LIBELF
>       bool
>  
> diff --git a/xen/common/domctl.c b/xen/common/domctl.c
> index bade9a63b1..29940fdea5 100644
> --- a/xen/common/domctl.c
> +++ b/xen/common/domctl.c
> @@ -205,7 +205,7 @@ void getdomaininfo(struct domain *d, struct 
> xen_domctl_getdomaininfo *info)
>      info->outstanding_pages = d->outstanding_pages;
>      info->shr_pages         = atomic_read(&d->shr_pages);
>      info->paged_pages       = atomic_read(&d->paged_pages);
> -    info->shared_info_frame = mfn_to_gmfn(d, virt_to_mfn(d->shared_info));
> +    info->shared_info_frame = gfn_x(domain_shared_info_gfn(d));
>      BUG_ON(SHARED_M2P(info->shared_info_frame));
>  
>      info->cpupool = d->cpupool ? d->cpupool->cpupool_id : CPUPOOLID_NONE;
> diff --git a/xen/common/memory.c b/xen/common/memory.c
> index 86567e6117..d6a580da31 100644
> --- a/xen/common/memory.c
> +++ b/xen/common/memory.c
> @@ -512,6 +512,7 @@ static bool propagate_node(unsigned int xmf, unsigned int 
> *memflags)
>  
>  static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) 
> arg)
>  {
> +#ifdef CONFIG_M2P
>      struct xen_memory_exchange exch;
>      PAGE_LIST_HEAD(in_chunk_list);
>      PAGE_LIST_HEAD(out_chunk_list);
> @@ -806,6 +807,9 @@ static long 
> memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
>      if ( __copy_field_to_guest(arg, &exch, nr_exchanged) )
>          rc = -EFAULT;
>      return rc;
> +#else /* !CONFIG_M2P */
> +    return -EOPNOTSUPP;
> +#endif
>  }
>  
>  int xenmem_add_to_physmap(struct domain *d, struct xen_add_to_physmap *xatp,
> diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
> index a6697d58fb..dbb64b13bc 100644
> --- a/xen/drivers/passthrough/iommu.c
> +++ b/xen/drivers/passthrough/iommu.c
> @@ -188,9 +188,10 @@ void __hwdom_init iommu_hwdom_init(struct domain *d)
>      hd->need_sync = iommu_hwdom_strict && !iommu_use_hap_pt(d);
>      if ( need_iommu_pt_sync(d) )
>      {
> +        int rc = 0;
> +#ifdef CONFIG_HAS_M2P
>          struct page_info *page;
>          unsigned int i = 0, flush_flags = 0;
> -        int rc = 0;
>  
>          page_list_for_each ( page, &d->page_list )
>          {
> @@ -217,6 +218,9 @@ void __hwdom_init iommu_hwdom_init(struct domain *d)
>          /* Use while-break to avoid compiler warning */
>          while ( iommu_iotlb_flush_all(d, flush_flags) )
>              break;
> +#else
> +        rc = -EOPNOTSUPP;
> +#endif
>  
>          if ( rc )
>              printk(XENLOG_WARNING "d%d: IOMMU mapping failed: %d\n",
> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
> index 312fec8932..d61b0188da 100644
> --- a/xen/include/asm-arm/domain.h
> +++ b/xen/include/asm-arm/domain.h
> @@ -267,6 +267,11 @@ static inline void free_vcpu_guest_context(struct 
> vcpu_guest_context *vgc)
>  
>  static inline void arch_vcpu_block(struct vcpu *v) {}
>  
> +static inline gfn_t domain_shared_info_gfn(struct domain *d)
> +{
> +    return INVALID_GFN;
> +}
> +
>  #endif /* __ASM_DOMAIN_H__ */
>  
>  /*
> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
> index 19486d5e32..cac8ffffe9 100644
> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -118,6 +118,10 @@ struct xen_domctl_getdomaininfo {
>      uint64_aligned_t outstanding_pages;
>      uint64_aligned_t shr_pages;
>      uint64_aligned_t paged_pages;
> +    /*
> +     * GFN of shared_info struct. Some architectures (e.g Arm) may not
> +     * provide a valid GFN.
> +     */
>      uint64_aligned_t shared_info_frame; /* GMFN of shared_info struct */
>      uint64_aligned_t cpu_time;
>      uint32_t nr_online_vcpus;    /* Number of VCPUs currently online. */
> diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
> index d1bfc82f57..f1761fe183 100644
> --- a/xen/include/xen/domain.h
> +++ b/xen/include/xen/domain.h
> @@ -118,4 +118,12 @@ struct vnuma_info {
>  
>  void vnuma_destroy(struct vnuma_info *vnuma);
>  
> +#ifdef CONFIG_HAS_M2P
> +#define domain_shared_info_gfn(d) ({                            \
> +    const struct domain *d_ = (d);                              \
> +                                                                \
> +    mfn_to_gfn(d_, _mfn(__virt_to_mfn(d_->shared_info)));       \

Aren't you missing a _gfn here?

  _gfn(mfn_to_gfn(d, _mfn(__virt_to_mfn(d->shared_info))));


> +})
> +#endif
> +
>  #endif /* __XEN_DOMAIN_H__ */


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.