3、事件通道的操作
Dom与事件通道相关的操作都需要通过Xen提供的超级调用HYPERVISOR_event_channel_op或HYPERVISOR_event_channel_op_compat来完成。其中HYPERVISOR_event_channel_op_compat被用来兼容Xen 3.0.2以前的超级调用方式。在早期的版本中,系统定义了与该超级调用对应的操作结构体evtchn_op,其中包含两个成员:cmd为操作码,联合体u中保存与操作码对应的结构体,用以保存操作的输入输出参数。
//xen\include\public\event_channel.h 232-251
typedef struct evtchn_op {
uint32_t cmd;
/*
*事件通道分配但未绑定 // #define EVTCHNOP_alloc_unbound 6
*事件通道绑定域间通信 // #define EVTCHNOP_bind_interdomain 0
*事件通道绑定虚拟中断 // #define EVTCHNOP_bind_virq 1
*事件通道绑定物理中断 // #define EVTCHNOP_bind_pirq 2
*事件通道绑定ipi // #define EVTCHNOP_bind_ipi 7
*事件通道关闭 // #define EVTCHNOP_close 3
*发送事件 // #define EVTCHNOP_send 4
*事件通道状态查询 // #define EVTCHNOP_status 5
*绑定vcpu // #define EVTCHNOP_bind_vcpu 8
*清除MASK位 // #define EVTCHNOP_unmask 9
*重置所有事件通道 // #define EVTCHNOP_reset 10
*/
union {
evtchn_alloc_unbound_t alloc_unbound;
evtchn_bind_interdomain_t bind_interdomain;
evtchn_bind_virq_t bind_virq;
evtchn_bind_pirq_t bind_pirq;
evtchn_bind_ipi_t bind_ipi;
evtchn_close_t close;
evtchn_send_t send;
evtchn_status_t status;
evtchn_bind_vcpu_t bind_vcpu;
evtchn_unmask_t unmask;
} u;
} evtchn_op_t;
之后的版本中,超级调用舍弃以evtchn_op结构体为参数的方式,改为直接调用其中的两个成员,即操作码和与操作码对应的结构体参数。
//xen/arch/X86/compat.c 29-38
/* 原始超级调用 (版本号:0x00030202). */
long do_event_channel_op_compat(Xen_GUEST_HANDLE(evtchn_op_t) uop)
{
struct evtchn_op op;
if ( unlikely(copy_from_guest(&op, uop, 1) != 0) )
return -EFAULT;
/*超级调用服务例程*/
return do_event_channel_op(op.cmd, guest_handle_from_ptr(&uop.p->u, void));
}
目前,系统定义了11种事件通道操作,其中包括事件通道的绑定、关闭和重置操作、发送事件通知和事件通道状态查询操作(如表3-1所示)
表 31 事件通道操作
操作码(cmd) |
值 |
结构体参数 |
说明 |
EVTCHNOP_alloc_unbound |
6 |
evtchn_alloc_unbound |
分配端口并处于未绑定状态 |
EVTCHNOP_bind_interdomain |
0 |
evtchn_bind_interdomain |
域间绑定 |
EVTCHNOP_bind_virq |
1 |
evtchn_bind_virq |
绑定虚拟中断(vIRQ) |
EVTCHNOP_bind_pirq |
2 |
evtchn_bind_pirq |
绑定物理中断(pIRQ) |
EVTCHNOP_bind_ipi |
7 |
evtchn_bind_ipi |
绑定IPI中断 |
EVTCHNOP_close |
3 |
evtchn_close |
关闭事件通道端口 |
EVTCHNOP_send |
4 |
evtchn_send |
发送事件通知消息 |
EVTCHNOP_status |
5 |
evtchn_status |
查看事件通道状态 |
EVTCHNOP_bind_vcpu |
8 |
evtchn_bind_vcpu |
绑定VCPU |
EVTCHNOP_unmask |
9 |
evtchn_unmask |
清除MASK位 |
EVTCHNOP_reset |
10 |
evtchn_reset |
关闭所有事件通道 |
上述操作的处理代码都定义在该超级调用的服务例程do_event_channel_op()中。在调用时,根据操作码cmd的值选择相对应的操作。每个操作都拥有自己的结构体参数,其中包含必要的输入参数和输出参数。例如,域间绑定操作的结构体参数为evtchn_bind_interdomain。这些结构体参数都定义在文件xen/include/public/event_channel.h中。
//xen\include\public\Event_channel.c 769-881
long do_event_channel_op(int cmd, Xen_GUEST_HANDLE(void) arg)
{
long rc;
switch ( cmd )
{
case EVTCHNOP_alloc_unbound: {
struct evtchn_alloc_unbound alloc_unbound;
if ( copy_from_guest(&alloc_unbound, arg, 1) != 0 )
return -EFAULT;
rc = evtchn_alloc_unbound(&alloc_unbound);
if ( (rc == 0) && (copy_to_guest(arg, &alloc_unbound, 1) != 0) )
rc = -EFAULT; /* Cleaning up here would be a mess! */
break;
}
case EVTCHNOP_bind_interdomain: {
struct evtchn_bind_interdomain bind_interdomain;
if ( copy_from_guest(&bind_interdomain, arg, 1) != 0 )
return -EFAULT;
rc = evtchn_bind_interdomain(&bind_interdomain);
if ( (rc == 0) && (copy_to_guest(arg, &bind_interdomain, 1) != 0) )
rc = -EFAULT; /* Cleaning up here would be a mess! */
break;
}
……
default:
rc = -ENOSYS;
break;
}
return rc;
}
值得注意的是,在超级调用HYPERVISOR_event_channel_op的服务例程中,是利用函数copy_from_guest()和copy_to_guest()来实现Xen空间与Guest OS空间数据的拷贝。在执行操作前,copy_from_guest()将结构体参数拷贝到Xen空间;操作完成后,copy_to_guest()再将其拷贝回Guest OS空间。若结构体参数中没有输出参数,则不用调用copy_to_guest()执行拷贝回操作。这在其它超级调用中也有应用。
3.1 绑定事件通道
在事件通道初始化完成后,需要对事件通道进行绑定才能够使用。是事件通道相关的绑定操作主要包括:VCPU绑定(EVTCHNOP_bind_vcpu)、域间绑定(EVTCHNOP_bind_interdomain)、虚拟中断绑定(EVTCHNOP_bind_virq)、物理中断绑定(EVTCHNOP_bind_pirq)以及虚拟IPI中断绑定(EVTCHNOP_bind_ipi)。
3.1.1 VCPU绑定(EVTCHNOP_bind_vcpu)
在Dom接收到来之Xen或其它Dom的事件通知后,需要将其送到该Dom的VCPU进行处理。因此,在事件通道使用前需要将其与特定的<