All of lore.kernel.org
 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 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.