xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: David Vrabel <david.vrabel@citrix.com>
To: Wei Liu <wei.liu2@citrix.com>
Cc: Wei Liu <liuw@liuw.name>, xen-devel@lists.xen.org
Subject: Re: [RFC PATCH 3/3] Implement 3-level event channel	routines.
Date: Wed, 2 Jan 2013 14:08:05 +0000	[thread overview]
Message-ID: <50E43F45.8080200@citrix.com> (raw)
In-Reply-To: <1356978155-18293-4-git-send-email-wei.liu2@citrix.com>

On 31/12/12 18:22, Wei Liu wrote:
> From: Wei Liu <liuw@liuw.name>
> 
> Add some fields in struct domain to hold pointer to 3-level shared arrays.
> Also add per-cpu second level selector in struct vcpu.
> 
> These structures are mapped by a new evtchn op. Guest should fall back to use
> 2-level event channel if mapping fails.
> 
> The routines are more or less as the 2-level ones.
> 
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>
[...]
> --- a/xen/common/event_channel.c
> +++ b/xen/common/event_channel.c
> @@ -27,6 +27,7 @@
>  #include <xen/guest_access.h>
>  #include <xen/keyhandler.h>
>  #include <asm/current.h>
> +#include <xen/paging.h>
>  
>  #include <public/xen.h>
>  #include <public/event_channel.h>
> @@ -413,6 +414,85 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
>      return rc;
>  }
>  
> +static inline int __evtchn_is_masked_l2(struct domain *d, int port)
> +{
> +    return test_bit(port, &shared_info(d, evtchn_mask));
> +}
> +
> +static inline int __evtchn_is_masked_l3(struct domain *d, int port)
> +{
> +    return test_bit(port % EVTCHNS_PER_PAGE,
> +                    d->evtchn_mask[port / EVTCHNS_PER_PAGE]);
> +}
> +
> +int evtchn_is_masked(struct domain *d, int port)
> +{
> +    switch ( d->evtchn_level )
> +    {
> +    case 2:
> +        return __evtchn_is_masked_l2(d, port);
> +    case 3:
> +        return __evtchn_is_masked_l3(d, port);
> +    default:
> +        printk(" %s: unknown event channel level %d for domain %d \n",
> +               __FUNCTION__, d->evtchn_level, d->domain_id);
> +        return 1;
> +    }

Drop the printk?  If d->evtchn_level is wrong this will spam the console
and it BUGs elsewhere anyway.

There are a bunch of other similar places.

> +static long __evtchn_register_3level(struct evtchn_register_3level *r)
> +{
> +    struct domain *d = current->domain;
> +    unsigned long mfns[r->nr_vcpus];
> +    unsigned long offsets[r->nr_vcpus];
> +    unsigned char was_up[r->nr_vcpus];
> +    int rc, i;
> +    struct vcpu *v;
> +
> +    if ( d->evtchn_level == 3 )
> +        return -EINVAL;
> +
> +    if ( r->nr_vcpus > d->max_vcpus )
> +        return -EINVAL;
> +
> +    for ( i = 0; i < MAX_L3_PAGES; i++ )
> +        if ( d->evtchn_pending[i] || d->evtchn_mask[i] )
> +            return -EINVAL;
> +
> +    for_each_vcpu ( d, v )
> +        if ( v->evtchn_pending_sel_l2 )
> +            return -EINVAL;
> +
> +    if ( copy_from_user(mfns, r->l2sel_mfn,
> +                        sizeof(unsigned long)*r->nr_vcpus) )
> +        return -EFAULT;
> +
> +    if ( copy_from_user(offsets, r->l2sel_offset,
> +                        sizeof(unsigned long)*r->nr_vcpus) )
> +        return -EFAULT;
> +
> +    /* put cpu offline */
> +    for_each_vcpu ( d, v )
> +    {
> +        if ( v == current )
> +            was_up[v->vcpu_id] = 1;
> +        else
> +            was_up[v->vcpu_id] = !test_and_set_bit(_VPF_down,
> +                                                   &v->pause_flags);
> +    }

Why offline the VCPUs?  I think there needs to be comment explaining why.

> +    /* map evtchn pending array and evtchn mask array */
> +    rc = __map_l3_arrays(d, r->evtchn_pending, r->evtchn_mask);
> +    if ( rc )
> +        goto out;
> +
> +    for_each_vcpu ( d, v )
> +    {
> +        if ( (rc = __map_l2_sel(v, mfns[v->vcpu_id], offsets[v->vcpu_id])) )
> +        {
> +            struct vcpu *v1;
> +            for_each_vcpu ( d, v1 )
> +                __unmap_l2_sel(v1);
> +            __unmap_l3_arrays(d);
> +            goto out;
> +        }
> +    }
> +
> +    /* Scan current bitmap and migrate all outstanding events to new bitmap */
> +    __evtchn_migrate_bitmap_l3(d);

This migrate seems racy.  Won't events after the migrate but before we
set the level below be lost?

Alternatively, if it's not racy because it's all protected with
d->event_lock, then the wmb() isn't required as the spin locks are
implicit barriers.

> +
> +    /* make sure all writes take effect before switching to new routines */
> +    wmb();
> +    d->evtchn_level = 3;
> +
> + out:
> +    /* bring cpus back online */
> +    for_each_vcpu ( d, v )
> +        if ( was_up[v->vcpu_id] &&
> +             test_and_clear_bit(_VPF_down, &v->pause_flags) )
> +            vcpu_wake(v);
> +
> +    return rc;
> +}
> +
> +static long evtchn_register_nlevel(evtchn_register_nlevel_t *r)
> +{
> +    struct domain *d = current->domain;
> +    int rc;
> +
> +    spin_lock(&d->event_lock);
> +
> +    switch ( r->level )
> +    {
> +    case 3:
> +        rc = __evtchn_register_3level(&r->u.l3);
> +        break;
> +    default:
> +        rc = -EINVAL;
> +    }
> +
> +    spin_unlock(&d->event_lock);
> +
> +    return rc;
> +}
>  
>  long do_event_channel_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
>  {
[...]
> --- a/xen/include/public/event_channel.h
> +++ b/xen/include/public/event_channel.h
> @@ -71,6 +71,7 @@
>  #define EVTCHNOP_bind_vcpu        8
>  #define EVTCHNOP_unmask           9
>  #define EVTCHNOP_reset           10
> +#define EVTCHNOP_register_nlevel 11
>  /* ` } */
>  
>  typedef uint32_t evtchn_port_t;
> @@ -258,6 +259,29 @@ struct evtchn_reset {
>  typedef struct evtchn_reset evtchn_reset_t;
>  
>  /*
> + * EVTCHNOP_register_nlevel: Register N level event channels.
> + * NOTES:
> + *   1. currently only 3-level is supported.
> + *   2. should fall back to basic 2-level if this call fails.
> + */
> +#define MAX_L3_PAGES 8

This is a public header so this needs to be prefixed. e.g.

#define EVTCHN_MAX_L3_PAGES 8

> +struct evtchn_register_3level {
> +    unsigned long evtchn_pending[MAX_L3_PAGES];
> +    unsigned long evtchn_mask[MAX_L3_PAGES];
> +    unsigned long *l2sel_mfn;
> +    unsigned long *l2sel_offset;

Should these unsigned longs be xen_pfn_t's?

> +    uint32_t nr_vcpus;
> +};
> +
> +struct evtchn_register_nlevel {
> +    uint32_t level;
> +    union {
> +        struct evtchn_register_3level l3;
> +    } u;
> +};
> +typedef struct evtchn_register_nlevel evtchn_register_nlevel_t;

Does there need to be compat handling for these structures?  As-is the
structures look like they do.

> +
> +/*
>   * ` enum neg_errnoval
>   * ` HYPERVISOR_event_channel_op_compat(struct evtchn_op *op)
>   * `
> diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
> index 5593066..1d4ef2d 100644
> --- a/xen/include/public/xen.h
> +++ b/xen/include/public/xen.h
> @@ -554,9 +554,24 @@ DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
>  
>  /*
>   * Event channel endpoints per domain:
> + * 2-level:
>   *  1024 if a long is 32 bits; 4096 if a long is 64 bits.
> + * 3-level:
> + *  32k if a long is 32 bits; 256k if a long is 64 bits;
>   */
> -#define NR_EVENT_CHANNELS (sizeof(unsigned long) * sizeof(unsigned long) * 64)
> +#define NR_EVENT_CHANNELS_L2 (sizeof(unsigned long) * sizeof(unsigned long) * 64)
> +#define NR_EVENT_CHANNELS_L3 (NR_EVENT_CHANNELS_L2 * 64)
> +#define NR_EVENT_CHANNELS(x) ({ unsigned int __v = 0;   \
> +            switch (x) {                                \
> +            case 2:                                     \
> +                __v = NR_EVENT_CHANNELS_L2; break;      \
> +            case 3:                                     \
> +                __v = NR_EVENT_CHANNELS_L3; break;      \
> +            default:                                    \
> +                BUG();                                  \
> +            }                                           \
> +            __v;})
> +

You've not documented what 'x' is in this macro.  Also name it 'level'.

David

  reply	other threads:[~2013-01-02 14:08 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-31 18:22 Implement 3-level event channels in Xen Wei Liu
2012-12-31 18:22 ` [RFC PATCH 1/3] Add a field in struct domain to indicate evtchn level Wei Liu
2013-01-02 11:11   ` David Vrabel
2013-01-02 14:28     ` Wei Liu
2012-12-31 18:22 ` [RFC PATCH 2/3] Dynamically allocate domain->evtchn, also bump EVTCHNS_PER_BUCKET to 512 Wei Liu
2013-01-02 13:38   ` David Vrabel
2013-01-02 14:27     ` Wei Liu
2013-01-03 10:36       ` Jan Beulich
2013-01-03 11:33         ` Wei Liu
2013-01-03 11:39           ` Jan Beulich
2012-12-31 18:22 ` [RFC PATCH 3/3] Implement 3-level event channel routines Wei Liu
2013-01-02 14:08   ` David Vrabel [this message]
2013-01-02 16:45   ` Ian Campbell
2013-01-03 10:46     ` Jan Beulich
2013-01-03 11:35   ` Jan Beulich
2013-01-08 17:33     ` Wei Liu
2013-01-09  8:38       ` Jan Beulich
2013-01-09 10:56         ` Ian Campbell
2013-01-09 11:24           ` Jan Beulich
2013-01-09 11:31             ` Ian Campbell
2013-01-09 11:41               ` Jan Beulich

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=50E43F45.8080200@citrix.com \
    --to=david.vrabel@citrix.com \
    --cc=liuw@liuw.name \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xen.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).