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

Re: [Xen-devel] [RFC PATCH 8/8]: PVH: privcmd changes



On Thu, 2012-08-16 at 02:07 +0100, Mukesh Rathor wrote:
> ---
>  drivers/xen/privcmd.c |   68 +++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 66 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
> index ccee0f1..0a240ab 100644
> --- a/drivers/xen/privcmd.c
> +++ b/drivers/xen/privcmd.c
> @@ -33,6 +33,7 @@
>  #include <xen/features.h>
>  #include <xen/page.h>
>  #include <xen/xen-ops.h>
> +#include <xen/balloon.h>
>  
>  #include "privcmd.h"
>  
> @@ -199,6 +200,10 @@ static long privcmd_ioctl_mmap(void __user *udata)
>       if (!xen_initial_domain())
>               return -EPERM;
>  
> +     /* PVH: TBD/FIXME. For now we only support privcmd_ioctl_mmap_batch */
> +     if (xen_pvh_domain())
> +             return -ENOSYS;
> +
>       if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd)))
>               return -EFAULT;
>  
> @@ -251,6 +256,8 @@ struct mmap_batch_state {
>       xen_pfn_t __user *user;
>  };
>  
> +/* PVH dom0: if domU being created is PV, then mfn is mfn(addr on bus). If
> + * it's PVH then mfn is pfn (input to HAP). */
>  static int mmap_batch_fn(void *data, void *state)
>  {
>       xen_pfn_t *mfnp = data;
> @@ -274,6 +281,40 @@ static int mmap_return_errors(void *data, void *state)
>       return put_user(*mfnp, st->user++);
>  }
>  
> +/* Allocate pfns that are then mapped with gmfns from foreign domid. Update
> + * the vma with the page info to use later.
> + * Returns: 0 if success, otherwise -errno
> + */
> +static int pvh_privcmd_resv_pfns(struct vm_area_struct *vma, int numpgs)
> +{
> +     int rc;
> +     struct xen_pvh_sav_pfn_info *savp;
> +
> +     savp = kzalloc(sizeof(struct xen_pvh_sav_pfn_info), GFP_KERNEL);
> +     if (savp == NULL)
> +             return -ENOMEM;
> +
> +     savp->sp_paga = kcalloc(numpgs, sizeof(savp->sp_paga[0]), GFP_KERNEL);
> +     if (savp->sp_paga == NULL) {
> +             kfree(savp);
> +             return -ENOMEM;
> +     }
> +
> +     rc = alloc_xenballooned_pages(numpgs, savp->sp_paga, 0);
> +     if (rc != 0) {
> +             pr_warn("%s Could not alloc %d pfns rc:%d\n", __FUNCTION__,
> +                     numpgs, rc);
> +             kfree(savp->sp_paga);
> +             kfree(savp);
> +             return -ENOMEM;
> +     }

I've just been building on this patch to make proper mmap foreign
support on ARM and I was looking for the place which freed this, both
the pages back to the balloon and then the array itself. There is code
in privcmd_close which unmaps the P2M, but I can't find the code which
frees things back to the balloon. Have I missed something?

I think we also need to think about the layering / abstraction a bit
here too. Currently on setup the caller allocates the array iff pvh and
stores it in the opaque vma->vm_private, then calls
xen_remap_domain_mfn_range which iff pvh calls pvh_add_to_xen_p2m which
assumes that the caller has seeded the vm_private with the correct
struct. xen_remap_domain_mfn_range also sets up the stage 1 PT mappings.

On teardown the iff pvh is in the caller which calls pvh_rem_xen_p2m
directly (this API is unbalanced with the setup side). The stage 1 PT
mappings are torn down implicitly somewhere else (in generic code, I
think you said).

(BTW, the terminology I'm using is stage 1 == guest OS page tables,
stage 2 == HAP)

I think you can't rely on the implicit teardown here since you need to
unmap before you hand the page back to the balloon. The reason this
doesn't look necessary now is that you don't give the page back.

Also not ordering the stage 1 and stage 2 teardown correctly is
dangerous, depending on the eventual ordering you potentially turn an
erroneous access to a virtual address, which should result in a guest OS
level page fault (and e.g. a seg fault to the offending process) into a
hypervisor shoots the guest due to an unexpected stage 2 fault type
failure, which is somewhat undesirable ;-)

With that in mind I think you do in the end need to add
xen_unmap_domain_mfn_range which does the unmap from both stage 1 and
stage 2 -- that balances out the interface (making pvh_rem_xen_p2m
internal) too, which is nice. This function may turn out to be a nop
on !pvh, but that's ok (although maybe there would be no harm in doing
explicit unmaps, for consistency?).

WRT passing data between interfaces in vma->vm_private, which is pretty
subtle, can we push that whole thing down into
xen_{remap,unmap}_domain_mfn_range too? This would make the requirement
on the caller be simple "never use vm_private", as opposed to now where
the requirement is "sometimes you might have to allocate some stuff and
stick it in here". The downside is that it pushes code which could be
generic down into per-arch stuff, although with suitable generic helper
functions this isn't so bad (whatever happened to
{alloc,free}_empty_pages_and_pagevec from the classic kernels? Those did
exactly what we want here, I think)

Ian.


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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