All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Vitaly Kuznetsov <vkuznets@redhat.com>, xen-devel@lists.xenproject.org
Cc: Andrew Jones <drjones@redhat.com>,
	David Vrabel <david.vrabel@citrix.com>,
	Jan Beulich <JBeulich@suse.com>
Subject: Re: [PATCH v3 1/1] Introduce VCPUOP_reset_vcpu_info
Date: Tue, 19 Aug 2014 11:21:34 +0100	[thread overview]
Message-ID: <53F3252E.4010100@citrix.com> (raw)
In-Reply-To: <1408442683-12125-2-git-send-email-vkuznets@redhat.com>

On 19/08/14 11:04, Vitaly Kuznetsov wrote:
> When an SMP guest performs kexec/kdump it tries issuing VCPUOP_register_vcpu_info.
> This fails due to vcpu_info already being registered. Introduce new vcpu operation
> to reset vcpu_info to its default state.
>
> Based on the original patch by Konrad Rzeszutek Wilk.
>
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
> ---
> Changes from RFCv2:
> - modify unmap_vcpu_info() to match both needs [Jan Beulich]
> - support VCPUOP_reset_vcpu_info for current VCPU [Jan Beulich]
> - improve description in public/vcpu.h [Jan Beulich]
>
> Changes from RFCv1:
> - Don't use unsuitable unmap_vcpu_info(), rewrite [Jan Beulich]
> - Require FIFO ABI being in 2-level mode
> - Describe limitations in include/public/vcpu.h [Jan Beulich]
> ---
>  xen/arch/x86/hvm/hvm.c    |  1 +
>  xen/common/domain.c       | 73 +++++++++++++++++++++++++++++++++++++++++------
>  xen/include/public/vcpu.h | 19 ++++++++++++
>  3 files changed, 85 insertions(+), 8 deletions(-)
>
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 216c3f2..7917272 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -3332,6 +3332,7 @@ static long hvm_vcpu_op(
>      case VCPUOP_set_singleshot_timer:
>      case VCPUOP_stop_singleshot_timer:
>      case VCPUOP_register_vcpu_info:
> +    case VCPUOP_reset_vcpu_info:
>      case VCPUOP_register_vcpu_time_memory_area:
>          rc = do_vcpu_op(cmd, vcpuid, arg);
>          break;
> diff --git a/xen/common/domain.c b/xen/common/domain.c
> index 44e5cbe..9e10e1e 100644
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -956,25 +956,52 @@ int map_vcpu_info(struct vcpu *v, unsigned long gfn, unsigned offset)
>  }
>  
>  /*
> - * 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.
> + * Unmap the vcpu info page if the guest decided to place it somewhere else.
> + * There's no need to do anything clever when the domain is dying (when called
> + * from arch_domain_destroy) and we need to prepare for rebinding when it is not
> + * (in case VCPUOP_reset_vcpu_info was called).
>   */
>  void unmap_vcpu_info(struct vcpu *v)
>  {
> +    struct domain *d = v->domain;
>      unsigned long mfn;
> +    vcpu_info_t *old_info;
> +    unsigned int i;
> +
> +    mfn = v->vcpu_info_mfn;
> +    old_info = v->vcpu_info;
>  
> -    if ( v->vcpu_info_mfn == INVALID_MFN )
> +    if ( mfn == INVALID_MFN )
>          return;
>  
> -    mfn = v->vcpu_info_mfn;
> +    if ( (!d->is_dying) && (v->vcpu_id < XEN_LEGACY_MAX_VCPUS) )
> +    {
> +        memcpy(&shared_info(d, vcpu_info[v->vcpu_id]), v->vcpu_info,
> +               sizeof(vcpu_info_t));
> +        v->vcpu_info = (vcpu_info_t *)&shared_info(d, vcpu_info[v->vcpu_id]);
> +    }
> +    else
> +        v->vcpu_info = &dummy_vcpu_info;
>      unmap_domain_page_global((void *)
> -                             ((unsigned long)v->vcpu_info & PAGE_MASK));
> +                             ((unsigned long)old_info & PAGE_MASK));
>  
> -    v->vcpu_info = &dummy_vcpu_info;
> +    put_page_and_type(mfn_to_page(mfn));
>      v->vcpu_info_mfn = INVALID_MFN;
>  
> -    put_page_and_type(mfn_to_page(mfn));
> +    if ( (!d->is_dying) && (v->vcpu_id < XEN_LEGACY_MAX_VCPUS) &&
> +         (test_bit(_VPF_down, &v->pause_flags)) )
> +    {
> +        /* Make sure vcpu_info was set */
> +        smp_wmb();
> +
> +        /*
> +         * Mark everything as being pending for all offline VCPUs to make sure
> +         * nothing gets lost when this VCPU goes online again.
> +         */
> +        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));
> +    }
>  }
>  
>  long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg)
> @@ -1116,6 +1143,36 @@ long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg)
>          break;
>      }
>  
> +    case VCPUOP_reset_vcpu_info:
> +    {
> +
> +        if ( (v != current) && !test_bit(_VPF_down, &v->pause_flags) )
> +        {
> +            printk(XENLOG_G_WARNING "%pv: VCPU is up or not current,"
> +                   "refusing to reset vcpu_info!\n", v);
> +            return -EBUSY;
> +        }
> +
> +        if ( v->evtchn_fifo )
> +        {
> +            printk(XENLOG_G_WARNING "%pv: FIFO evtchn ABI is being used,"
> +                   "refusing to reset vcpu_info!\n", v);
> +            return -EBUSY;
> +        }

These two checks should be in unmap_vcpu_info() similar to
map_vcpu_info(), and unmap_vcpu_info() should return an int.  I am not
sure whether the printks are really needed; a buggy/malicious guest is
very capable of causing logspam with them.

> +
> +        if ( v->vcpu_info_mfn == INVALID_MFN )
> +        {
> +            rc = 0;
> +            break;
> +        }

This check is not safe without the domain lock held.  Drop it entirely,
as the head of unmap_vcpu_info() already does it.

~Andrew

> +
> +        domain_lock(d);
> +        unmap_vcpu_info(v);
> +        domain_unlock(d);
> +        rc = 0;
> +        break;
> +    }
> +
>      case VCPUOP_register_runstate_memory_area:
>      {
>          struct vcpu_register_runstate_memory_area area;
> diff --git a/xen/include/public/vcpu.h b/xen/include/public/vcpu.h
> index e888daf..c4d166c 100644
> --- a/xen/include/public/vcpu.h
> +++ b/xen/include/public/vcpu.h
> @@ -227,6 +227,25 @@ struct vcpu_register_time_memory_area {
>  typedef struct vcpu_register_time_memory_area vcpu_register_time_memory_area_t;
>  DEFINE_XEN_GUEST_HANDLE(vcpu_register_time_memory_area_t);
>  
> +/*
> + * Reset all of the vcpu_info information from their previous location
> + * to the default one used at bootup. The following prerequisites should be met:
> + *  1. Domain should be using 2-level event channel ABI. In case another
> + *     non-default ABI is in use the domain is supposed to switch back to
> + *     2-level ABI with EVTCHNOP_reset.
> + *  2. The operation is unsupported for non-current online VCPUs. If performed
> + *     during shutdown/kexec/... a guest domain is supposed to behave in the
> + *     following sequence:
> + *     - Choose special 'shutdown' VCPU, bring all other VCPUs down;
> + *     - Issue VCPUOP_reset_vcpu_info for all offline VCPUs;
> + *     - Issue VCPUOP_reset_vcpu_info for the 'shutdown' VCPU.
> + *
> + * After the call vcpu_info is reset to its default state: first
> + * XEN_LEGACY_MAX_VCPUS VCPUs will get it switched to shared_info and all other
> + * VCPUs will get dummy_vcpu_info.
> + */
> +#define VCPUOP_reset_vcpu_info   14
> +
>  #endif /* __XEN_PUBLIC_VCPU_H__ */
>  
>  /*

  reply	other threads:[~2014-08-19 10:21 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-19 10:04 [PATCH v3 0/1] Introduce VCPUOP_reset_vcpu_info Vitaly Kuznetsov
2014-08-19 10:04 ` [PATCH v3 1/1] " Vitaly Kuznetsov
2014-08-19 10:21   ` Andrew Cooper [this message]
2014-08-19 23:22   ` Jan Beulich
2014-08-19 18:59 ` [PATCH v3 0/1] " David Vrabel
2014-08-20  8:43   ` Vitaly Kuznetsov
2014-08-20 13:37   ` Konrad Rzeszutek Wilk
2014-08-20 21:57     ` Konrad Rzeszutek Wilk
2014-08-21 10:35       ` Vitaly Kuznetsov
2014-08-22  2:27         ` Konrad Rzeszutek Wilk
2014-08-22  9:08           ` Jan Beulich
2014-08-22 12:41             ` David Vrabel
2014-08-22 13:23               ` Jan Beulich
2014-08-25 13:50           ` Vitaly Kuznetsov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=53F3252E.4010100@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=JBeulich@suse.com \
    --cc=david.vrabel@citrix.com \
    --cc=drjones@redhat.com \
    --cc=vkuznets@redhat.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.