Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103355
  • 博文数量: 41
  • 博客积分: 2520
  • 博客等级: 少校
  • 技术积分: 440
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-22 16:25
文章分类

全部博文(41)

文章存档

2010年(41)

我的朋友

分类: LINUX

2010-01-27 10:19:56

static int evtchn_set_pending(struct vcpu *v, int port)

{

    struct domain *d = v->domain;                     // 通过VCPU找到对应的dom

    int vcpuid;

 

    /*

     * The following bit operations must happen in strict order.

     * NB. On x86, the atomic bit operations also act as memory barriers.

     * There is therefore sufficiently strict ordering for this architecture --

     * others may require explicit memory barriers.

     */

 

    if ( test_and_set_bit(port, &shared_info(d, evtchn_pending)) )  // 设置domshared_info里面

        return 1;                                   // evtchn_pending数组中对于元素的对应位(根据port)为1

evtchnpending位都被置1表明此evtchn需要/正在被某个VCPU处理。

    if ( !test_bit        (port, &shared_info(d, evtchn_mask)) &&

         !test_and_set_bit(port / BITS_PER_EVTCHN_WORD(d),

                           &vcpu_info(v, evtchn_pending_sel)) )

如果此evtchnmask位没有设置,则设置对应的VCPUevtchn_pending_sel位(evtchn_pending_selevtchn_pending关联)。使该VCPU可以感知正在处理哪个event,即定位pending状态的evtchn

    {

        vcpu_mark_events_pending(v);

同时,如果evtchn_pending_sel设置成功,则设置VCPUevtchn_upcall_pending表明本VCPU需要/正在处理event

    }

   

    /* Check if some VCPU might be polling for this event. */

    if ( likely(bitmap_empty(d->poll_mask, d->max_vcpus)) )

        return 0;

 

    /* Wake any interested (or potentially interested) pollers. */

    for ( vcpuid = find_first_bit(d->poll_mask, d->max_vcpus);

          vcpuid < d->max_vcpus;

          vcpuid = find_next_bit(d->poll_mask, d->max_vcpus, vcpuid+1) )

    {

        v = d->vcpu[vcpuid];

        if ( ((v->poll_evtchn <= 0) || (v->poll_evtchn == port)) &&

             test_and_clear_bit(vcpuid, d->poll_mask) )

        {

            v->poll_evtchn = 0;

            vcpu_unblock(v);

        }

    }

 

    return 0;

}

 

#define shared_info(d, field)      __shared_info(d, (d)->shared_info, field)

#define __shared_info(d, s, field) ((s)->field)

 

void vcpu_mark_events_pending(struct vcpu *v)

{

    int already_pending = test_and_set_bit(

        0, (unsigned long *)&vcpu_info(v, evtchn_upcall_pending));

 

    if ( already_pending )

        return;

 

    if ( is_hvm_vcpu(v) )

        hvm_assert_evtchn_irq(v);

    else

        vcpu_kick(v);

}


void mask_evtchn(int port)

{

           shared_info_t *s = HYPERVISOR_shared_info;      // 获得shared_info

           synch_set_bit(port, s->evtchn_mask);                         // 设置里面的evtchn_mask

}

EXPORT_SYMBOL_GPL(mask_evtchn);

 

void unmask_evtchn(int port)

{

           shared_info_t *s = HYPERVISOR_shared_info;     // 获得shared_info

           unsigned int cpu = smp_processor_id();

           vcpu_info_t *vcpu_info = &s->vcpu_info[cpu];          // 获得当前的VCPU

 

           BUG_ON(!irqs_disabled());

 

           /* Slow path (hypercall) if this is a non-local port. */

           if (unlikely(cpu != cpu_from_evtchn(port))) {                                // 如果本evtchn没有绑定到本VCPU

                             struct evtchn_unmask unmask = { .port = port };

                             VOID(HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask)); // hypercall处理

                             return;

           }

 

           synch_clear_bit(port, s->evtchn_mask);                                        // 取消mask

 

           /* Did we miss an interrupt 'edge'? Re-fire if so. */

           if (synch_test_bit(port, s->evtchn_pending) &&                          // 如果存在未决evtchn

               !synch_test_and_set_bit(port / BITS_PER_LONG,

                                                                       &vcpu_info->evtchn_pending_sel))

                             vcpu_info->evtchn_upcall_pending = 1;                       // 设置VCPUevtchn_upcall_pending

}

EXPORT_SYMBOL_GPL(unmask_evtchn);


结构体:

struct evtchn_op {

    uint32_t cmd; /* EVTCHNOP_* */

    union {

        struct evtchn_alloc_unbound    alloc_unbound;

        struct evtchn_bind_interdomain bind_interdomain;

        struct evtchn_bind_virq        bind_virq;

        struct evtchn_bind_pirq        bind_pirq;

        struct evtchn_bind_ipi         bind_ipi;

        struct evtchn_close            close;

        struct evtchn_send             send;

        struct evtchn_status           status;

        struct evtchn_bind_vcpu        bind_vcpu;

        struct evtchn_unmask           unmask;

    } u;

};

typedef struct evtchn_op evtchn_op_t;

 

struct shared_info {

    struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];

 

    unsigned long evtchn_pending[sizeof(unsigned long) * 8];                   // 32long,有32*32=1024

    unsigned long evtchn_mask[sizeof(unsigned long) * 8];

 

    uint32_t wc_version;      /* Version counter: see vcpu_time_info_t. */

    uint32_t wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */

    uint32_t wc_nsec;         /* Nsecs 00:00:00 UTC, Jan 1, 1970.  */

 

    struct arch_shared_info arch;

 

}

 

struct vcpu_info {

    uint8_t evtchn_upcall_pending;         // 针对所有evtchn

    uint8_t evtchn_upcall_mask;             // 设置为1,则此VCPU将屏蔽所有的evtchn

    unsigned long evtchn_pending_sel;   // 每一位对应evtchn_pinding中一组32evtchn。设置方法

    struct arch_vcpu_info arch;

    struct vcpu_time_info time;

}; /* 64 bytes (x86) */

 

/*

 * EVTCHNOP_alloc_unbound: Allocate a port in domain and mark as

 * accepting interdomain bindings from domain . A fresh port

 * is allocated in and returned as .

 * NOTES:

 *  1. If the caller is unprivileged then must be DOMID_SELF.

 *  2. may be DOMID_SELF, allowing loopback connections.

 */

#define EVTCHNOP_alloc_unbound    6

struct evtchn_alloc_unbound {

    /* IN parameters */

    domid_t dom, remote_dom;

    /* OUT parameters */

    evtchn_port_t port;                                // 用于通信的port

};

typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t;

 

/*

 * EVTCHNOP_bind_interdomain: Construct an interdomain event channel between

 * the calling domain and . must identify

 * a port that is unbound and marked as accepting bindings from the calling         // 参考EVTCHNOP_alloc_unbound

 * domain. A fresh port is allocated in the calling domain and returned as

 * .

 * NOTES:

 *  2. may be DOMID_SELF, allowing loopback connections.

 */

#define EVTCHNOP_bind_interdomain 0

struct evtchn_bind_interdomain {

    /* IN parameters. */

    domid_t remote_dom;

    evtchn_port_t remote_port;

    /* OUT parameters. */

    evtchn_port_t local_port;

};

typedef struct evtchn_bind_interdomain evtchn_bind_interdomain_t;

 

/*

 * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ on specified

 * vcpu.

 * NOTES:

 *  1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list

 *     in xen.h for the classification of each VIRQ.

 *  2. Global VIRQs must be allocated on VCPU0 but can subsequently be

 *     re-bound via EVTCHNOP_bind_vcpu.

 *  3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu.

 *     The allocated event channel is bound to the specified vcpu and the

 *     binding cannot be changed.

 */

#define EVTCHNOP_bind_virq        1

struct evtchn_bind_virq {

    /* IN parameters. */

    uint32_t virq;

    uint32_t vcpu;

    /* OUT parameters. */

    evtchn_port_t port;

};

typedef struct evtchn_bind_virq evtchn_bind_virq_t;

 

/*

 * EVTCHNOP_bind_pirq: Bind a local event channel to PIRQ .

 * NOTES:

 *  1. A physical IRQ may be bound to at most one event channel per domain.

 *  2. Only a sufficiently-privileged domain may bind to a physical IRQ.

 */

#define EVTCHNOP_bind_pirq        2

struct evtchn_bind_pirq {

    /* IN parameters. */

    uint32_t pirq;

#define BIND_PIRQ__WILL_SHARE 1

    uint32_t flags; /* BIND_PIRQ__* */

    /* OUT parameters. */

    evtchn_port_t port;

};

typedef struct evtchn_bind_pirq evtchn_bind_pirq_t;

 

/*

 * EVTCHNOP_bind_ipi: Bind a local event channel to receive events.

 * NOTES:

 *  1. The allocated event channel is bound to the specified vcpu. The binding

 *     may not be changed.

 */

#define EVTCHNOP_bind_ipi         7

struct evtchn_bind_ipi {

    uint32_t vcpu;

    /* OUT parameters. */

    evtchn_port_t port;

};

typedef struct evtchn_bind_ipi evtchn_bind_ipi_t;

 

/*

 * EVTCHNOP_close: Close a local event channel . If the channel is

 * interdomain then the remote end is placed in the unbound state

 * (EVTCHNSTAT_unbound), awaiting a new connection.

 */

#define EVTCHNOP_close            3

struct evtchn_close {

    /* IN parameters. */

    evtchn_port_t port;

};

typedef struct evtchn_close evtchn_close_t;

 

/*

 * EVTCHNOP_send: Send an event to the remote end of the channel whose local

 * endpoint is .

 */

#define EVTCHNOP_send             4

struct evtchn_send {

    /* IN parameters. */

    evtchn_port_t port;

};

typedef struct evtchn_send evtchn_send_t;

 

/*

 * EVTCHNOP_status: Get the current status of the communication channel which

 * has an endpoint at .

 * NOTES:

 *  1. may be specified as DOMID_SELF.

 *  2. Only a sufficiently-privileged domain may obtain the status of an event

 *     channel for which is not DOMID_SELF.

 */

#define EVTCHNOP_status           5

struct evtchn_status {

    /* IN parameters */

    domid_t  dom;

    evtchn_port_t port;

    /* OUT parameters */

#define EVTCHNSTAT_closed       0  /* Channel is not in use.                 */

#define EVTCHNSTAT_unbound      1  /* Channel is waiting interdom connection.*/

#define EVTCHNSTAT_interdomain  2  /* Channel is connected to remote domain. */

#define EVTCHNSTAT_pirq         3  /* Channel is bound to a phys IRQ line.   */

#define EVTCHNSTAT_virq         4  /* Channel is bound to a virtual IRQ line */

#define EVTCHNSTAT_ipi          5  /* Channel is bound to a virtual IPI line */

    uint32_t status;

    uint32_t vcpu;                 /* VCPU to which this channel is bound.   */

    union {

        struct {

            domid_t dom;

        } unbound; /* EVTCHNSTAT_unbound */  // 如果是unbound状态,那么此port开放给哪个dom

        struct {

            domid_t dom;

            evtchn_port_t port;

        } interdomain; /* EVTCHNSTAT_interdomain */       // 如果是interdomain状态,那么连接的远程domport

        uint32_t pirq;      /* EVTCHNSTAT_pirq        */

        uint32_t virq;      /* EVTCHNSTAT_virq        */

    } u;

};

typedef struct evtchn_status evtchn_status_t;

 

/*

 * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an

 * event is pending.

 * NOTES:

 *  1. IPI-bound channels always notify the vcpu specified at bind time.

 *     This binding cannot be changed.

 *  2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time.

 *     This binding cannot be changed.

 *  3. All other channels notify vcpu0 by default. This default is set when

 *     the channel is allocated (a port that is freed and subsequently reused

 *     has its binding reset to vcpu0).

 */

#define EVTCHNOP_bind_vcpu        8

struct evtchn_bind_vcpu {

    /* IN parameters. */

    evtchn_port_t port;

    uint32_t vcpu;

};

typedef struct evtchn_bind_vcpu evtchn_bind_vcpu_t;

 

/*

 * EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver

 * a notification to the appropriate VCPU if an event is pending.

 */

#define EVTCHNOP_unmask           9

struct evtchn_unmask {

    /* IN parameters. */

    evtchn_port_t port;

};

typedef struct evtchn_unmask evtchn_unmask_t;

 

/*

 * EVTCHNOP_reset: Close all event channels associated with specified domain.

 * NOTES:

 *  1. may be specified as DOMID_SELF.

 *  2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.

 */

#define EVTCHNOP_reset           10

struct evtchn_reset {

    /* IN parameters. */

    domid_t dom;

};

typedef struct evtchn_reset evtchn_reset_t;
阅读(854) | 评论(0) | 转发(0) |
0

上一篇:Xen Event Channel (2)

下一篇:Xenbus (1)

给主人留下些什么吧!~~