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

Re: [Xen-devel] [PATCH v3 09/13] xen: move VCPUOP_register_vcpu_info to common code



On Wed, 2013-04-24 at 20:07 +0100, Stefano Stabellini wrote:
> Move the implementation of VCPUOP_register_vcpu_info from x86 specific
> to commmon code.
> 
> Move vcpu_info_mfn from an arch specific vcpu sub-field to the common
> vcpu struct.
> Move the initialization of vcpu_info_mfn to common code.
> 
> Move unmap_vcpu_info and the call to unmap_vcpu_info at domain
> destruction time to common code.
> 
> Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
> CC: keir@xxxxxxx
> CC: JBeulich@xxxxxxxx

My ack isn't worth much here, but FWIW looks good to me, assuming the
bulk of it really is just code motion...

Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>

> ---
>  xen/arch/x86/domain.c        |  113 
> ------------------------------------------
>  xen/common/domain.c          |  111 +++++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-x86/domain.h |    3 -
>  xen/include/xen/domain.h     |    3 +
>  xen/include/xen/sched.h      |    3 +
>  5 files changed, 117 insertions(+), 116 deletions(-)
> 
> diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
> index 14b6d13..d1b6c64 100644
> --- a/xen/arch/x86/domain.c
> +++ b/xen/arch/x86/domain.c
> @@ -387,8 +387,6 @@ int vcpu_initialise(struct vcpu *v)
>  
>      vmce_init_vcpu(v);
>  
> -    v->arch.vcpu_info_mfn = INVALID_MFN;
> -
>      if ( is_hvm_domain(d) )
>      {
>          rc = hvm_vcpu_initialise(v);
> @@ -954,99 +952,6 @@ void arch_vcpu_reset(struct vcpu *v)
>      }
>  }
>  
> -/* 
> - * Unmap the vcpu info page if the guest decided to place it somewhere
> - * else.  This is only used from arch_domain_destroy, so there's no
> - * need to do anything clever.
> - */
> -static void
> -unmap_vcpu_info(struct vcpu *v)
> -{
> -    unsigned long mfn;
> -
> -    if ( v->arch.vcpu_info_mfn == INVALID_MFN )
> -        return;
> -
> -    mfn = v->arch.vcpu_info_mfn;
> -    unmap_domain_page_global(v->vcpu_info);
> -
> -    v->vcpu_info = &dummy_vcpu_info;
> -    v->arch.vcpu_info_mfn = INVALID_MFN;
> -
> -    put_page_and_type(mfn_to_page(mfn));
> -}
> -
> -/* 
> - * Map a guest page in and point the vcpu_info pointer at it.  This
> - * makes sure that the vcpu_info is always pointing at a valid piece
> - * of memory, and it sets a pending event to make sure that a pending
> - * event doesn't get missed.
> - */
> -static int
> -map_vcpu_info(struct vcpu *v, unsigned long gfn, unsigned offset)
> -{
> -    struct domain *d = v->domain;
> -    void *mapping;
> -    vcpu_info_t *new_info;
> -    struct page_info *page;
> -    int i;
> -
> -    if ( offset > (PAGE_SIZE - sizeof(vcpu_info_t)) )
> -        return -EINVAL;
> -
> -    if ( v->arch.vcpu_info_mfn != INVALID_MFN )
> -        return -EINVAL;
> -
> -    /* Run this command on yourself or on other offline VCPUS. */
> -    if ( (v != current) && !test_bit(_VPF_down, &v->pause_flags) )
> -        return -EINVAL;
> -
> -    page = get_page_from_gfn(d, gfn, NULL, P2M_ALLOC);
> -    if ( !page )
> -        return -EINVAL;
> -
> -    if ( !get_page_type(page, PGT_writable_page) )
> -    {
> -        put_page(page);
> -        return -EINVAL;
> -    }
> -
> -    mapping = __map_domain_page_global(page);
> -    if ( mapping == NULL )
> -    {
> -        put_page_and_type(page);
> -        return -ENOMEM;
> -    }
> -
> -    new_info = (vcpu_info_t *)(mapping + offset);
> -
> -    if ( v->vcpu_info == &dummy_vcpu_info )
> -    {
> -        memset(new_info, 0, sizeof(*new_info));
> -        __vcpu_info(v, new_info, evtchn_upcall_mask) = 1;
> -    }
> -    else
> -    {
> -        memcpy(new_info, v->vcpu_info, sizeof(*new_info));
> -    }
> -
> -    v->vcpu_info = new_info;
> -    v->arch.vcpu_info_mfn = page_to_mfn(page);
> -
> -    /* Set new vcpu_info pointer /before/ setting pending flags. */
> -    wmb();
> -
> -    /*
> -     * Mark everything as being pending just to make sure nothing gets
> -     * lost.  The domain will get a spurious event, but it can cope.
> -     */
> -    vcpu_info(v, evtchn_upcall_pending) = 1;
> -    for ( i = 0; i < BITS_PER_EVTCHN_WORD(d); i++ )
> -        set_bit(i, &vcpu_info(v, evtchn_pending_sel));
> -
> -    return 0;
> -}
> -
>  long
>  arch_do_vcpu_op(
>      int cmd, struct vcpu *v, XEN_GUEST_HANDLE_PARAM(void) arg)
> @@ -1083,22 +988,6 @@ arch_do_vcpu_op(
>          break;
>      }
>  
> -    case VCPUOP_register_vcpu_info:
> -    {
> -        struct domain *d = v->domain;
> -        struct vcpu_register_vcpu_info info;
> -
> -        rc = -EFAULT;
> -        if ( copy_from_guest(&info, arg, 1) )
> -            break;
> -
> -        domain_lock(d);
> -        rc = map_vcpu_info(v, info.mfn, info.offset);
> -        domain_unlock(d);
> -
> -        break;
> -    }
> -
>      /*
>       * XXX Disable for 4.0.0: __update_vcpu_system_time() writes to the given
>       * virtual address even when running in another domain's address space.
> @@ -2025,8 +1914,6 @@ int domain_relinquish_resources(struct domain *d)
>                   * mappings.
>                   */
>                  destroy_gdt(v);
> -
> -                unmap_vcpu_info(v);
>              }
>  
>              if ( d->arch.pv_domain.pirq_eoi_map != NULL )
> diff --git a/xen/common/domain.c b/xen/common/domain.c
> index ce45d66..d21909f 100644
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -33,6 +33,7 @@
>  #include <xen/xenoprof.h>
>  #include <xen/irq.h>
>  #include <asm/debugger.h>
> +#include <asm/p2m.h>
>  #include <asm/processor.h>
>  #include <public/sched.h>
>  #include <public/sysctl.h>
> @@ -142,6 +143,7 @@ struct vcpu *alloc_vcpu(
>          v->vcpu_info = ((vcpu_id < XEN_LEGACY_MAX_VCPUS)
>                          ? (vcpu_info_t *)&shared_info(d, vcpu_info[vcpu_id])
>                          : &dummy_vcpu_info);
> +        v->vcpu_info_mfn = INVALID_MFN;
>          init_waitqueue_vcpu(v);
>      }
>  
> @@ -547,6 +549,7 @@ int rcu_lock_live_remote_domain_by_id(domid_t dom, struct 
> domain **d)
>  int domain_kill(struct domain *d)
>  {
>      int rc = 0;
> +    struct vcpu *v;
>  
>      if ( d == current->domain )
>          return -EINVAL;
> @@ -571,6 +574,8 @@ int domain_kill(struct domain *d)
>              BUG_ON(rc != -EAGAIN);
>              break;
>          }
> +        for_each_vcpu ( d, v )
> +            unmap_vcpu_info(v);
>          d->is_dying = DOMDYING_dead;
>          /* Mem event cleanup has to go here because the rings 
>           * have to be put before we call put_domain. */
> @@ -896,6 +901,96 @@ void vcpu_reset(struct vcpu *v)
>      vcpu_unpause(v);
>  }
>  
> +/* 
> + * Map a guest page in and point the vcpu_info pointer at it.  This
> + * makes sure that the vcpu_info is always pointing at a valid piece
> + * of memory, and it sets a pending event to make sure that a pending
> + * event doesn't get missed.
> + */
> +int map_vcpu_info(struct vcpu *v, unsigned long gfn, unsigned offset)
> +{
> +    struct domain *d = v->domain;
> +    void *mapping;
> +    vcpu_info_t *new_info;
> +    struct page_info *page;
> +    int i;
> +
> +    if ( offset > (PAGE_SIZE - sizeof(vcpu_info_t)) )
> +        return -EINVAL;
> +
> +    if ( v->vcpu_info_mfn != INVALID_MFN )
> +        return -EINVAL;
> +
> +    /* Run this command on yourself or on other offline VCPUS. */
> +    if ( (v != current) && !test_bit(_VPF_down, &v->pause_flags) )
> +        return -EINVAL;
> +
> +    page = get_page_from_gfn(d, gfn, NULL, P2M_ALLOC);
> +    if ( !page )
> +        return -EINVAL;
> +
> +    if ( !get_page_type(page, PGT_writable_page) )
> +    {
> +        put_page(page);
> +        return -EINVAL;
> +    }
> +
> +    mapping = __map_domain_page_global(page);
> +    if ( mapping == NULL )
> +    {
> +        put_page_and_type(page);
> +        return -ENOMEM;
> +    }
> +
> +    new_info = (vcpu_info_t *)(mapping + offset);
> +
> +    if ( v->vcpu_info == &dummy_vcpu_info )
> +    {
> +        memset(new_info, 0, sizeof(*new_info));
> +        __vcpu_info(v, new_info, evtchn_upcall_mask) = 1;
> +    }
> +    else
> +    {
> +        memcpy(new_info, v->vcpu_info, sizeof(*new_info));
> +    }
> +
> +    v->vcpu_info = new_info;
> +    v->vcpu_info_mfn = page_to_mfn(page);
> +
> +    /* Set new vcpu_info pointer /before/ setting pending flags. */
> +    wmb();
> +
> +    /*
> +     * Mark everything as being pending just to make sure nothing gets
> +     * lost.  The domain will get a spurious event, but it can cope.
> +     */
> +    vcpu_info(v, evtchn_upcall_pending) = 1;
> +    for ( i = 0; i < BITS_PER_EVTCHN_WORD(d); i++ )
> +        set_bit(i, &vcpu_info(v, evtchn_pending_sel));
> +
> +    return 0;
> +}
> +
> +/* 
> + * Unmap the vcpu info page if the guest decided to place it somewhere
> + * else.  This is only used from arch_domain_destroy, so there's no
> + * need to do anything clever.
> + */
> +void unmap_vcpu_info(struct vcpu *v)
> +{
> +    unsigned long mfn;
> +
> +    if ( v->vcpu_info_mfn == INVALID_MFN )
> +        return;
> +
> +    mfn = v->vcpu_info_mfn;
> +    unmap_domain_page_global(v->vcpu_info);
> +
> +    v->vcpu_info = &dummy_vcpu_info;
> +    v->vcpu_info_mfn = INVALID_MFN;
> +
> +    put_page_and_type(mfn_to_page(mfn));
> +}
>  
>  long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg)
>  {
> @@ -1015,6 +1110,22 @@ long do_vcpu_op(int cmd, int vcpuid, 
> XEN_GUEST_HANDLE_PARAM(void) arg)
>  
>          break;
>  
> +    case VCPUOP_register_vcpu_info:
> +    {
> +        struct domain *d = v->domain;
> +        struct vcpu_register_vcpu_info info;
> +
> +        rc = -EFAULT;
> +        if ( copy_from_guest(&info, arg, 1) )
> +            break;
> +
> +        domain_lock(d);
> +        rc = map_vcpu_info(v, info.mfn, info.offset);
> +        domain_unlock(d);
> +
> +        break;
> +    }
> +
>  #ifdef VCPU_TRAP_NMI
>      case VCPUOP_send_nmi:
>          if ( !guest_handle_is_null(arg) )
> diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
> index bdaf714..e7ed7c3 100644
> --- a/xen/include/asm-x86/domain.h
> +++ b/xen/include/asm-x86/domain.h
> @@ -435,9 +435,6 @@ struct arch_vcpu
>  
>      struct paging_vcpu paging;
>  
> -    /* Guest-specified relocation of vcpu_info. */
> -    unsigned long vcpu_info_mfn;
> -
>      uint32_t gdbsx_vcpu_event;
>  
>      /* A secondary copy of the vcpu time info. */
> diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
> index d4ac50f..d0263a9 100644
> --- a/xen/include/xen/domain.h
> +++ b/xen/include/xen/domain.h
> @@ -52,6 +52,9 @@ void free_pirq_struct(void *);
>  int  vcpu_initialise(struct vcpu *v);
>  void vcpu_destroy(struct vcpu *v);
>  
> +int map_vcpu_info(struct vcpu *v, unsigned long gfn, unsigned offset);
> +void unmap_vcpu_info(struct vcpu *v);
> +
>  int arch_domain_create(struct domain *d, unsigned int domcr_flags);
>  
>  void arch_domain_destroy(struct domain *d);
> diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
> index beadc42..7e129d9 100644
> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -192,6 +192,9 @@ struct vcpu
>  
>      struct waitqueue_vcpu *waitqueue_vcpu;
>  
> +    /* Guest-specified relocation of vcpu_info. */
> +    unsigned long vcpu_info_mfn;
> +
>      struct arch_vcpu arch;
>  };
>  



_______________________________________________
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®.