...
Table of Contents | ||||||
---|---|---|---|---|---|---|
|
Taxonomy
Xen: the Xen Project hypervisor |
VM: Virtual Machine |
OS: Operating System |
Dom0: privileged VM, booted directly from Xen |
DomU: regular unprivileged VM, started from Dom0 using the “xl” tool |
Dom0less DomU: regular unprivilehed VM started from Xen at boot (in parallel with Dom0) |
Introduction
A simple, yet effective, way to setup VM-to-VM communication between Xen guests is plain shared memory and notifications. Shared memory can be used to setup a ring buffer and exchange data, while notifications can be used to avoid having to poll for updates on the ring.
...
Xen events are delivered as GUEST_EVTCHN_PPI
, statically defined as interrupt 31. Firstly, register a handler in your OS for PPI 31.
...
Information about event channels is provided on a memory page called “sharedshared_
info” info
because it is shared between the VM and Xen. In order to access the shared_info page it is necessary to register it:
...
Allocating and Binding Event Channels
The previous chapter section described how to receive event channels in general. This chapter describes how to allocate and bind one event channel so that it can be used for notifications between domains.
...
The receiver domain allocates a new unbound event channel by calling
EVTCHNOP_alloc_unbound
.Code Block language c struct evtchn_alloc_unbound alloc; alloc.dom = DOMID_SELF; alloc.remote_dom = remote_domid; alloc.port = 0; ret = xen_hypercall(EVTCHNOP_alloc_unbound, (unsigned long)&alloc, 0, 0, HYPERVISOR_event_channel_op);
The sender domain needs to know the remote event channel number, typically refer to as “port”
port
, to bind to it. As the remote port number is dynamically allocated by theEVTCHNOP_alloc_unbound
hypercall, it is best if the port number is passed over shared memory from the receiver to the sender.Code Block language c /* wait for readiness signal */ while (1) { if (strcmp(shared_mem, "go") == 0) break; mb(); } mb(); /* read port number of the other domain */ memcpy(&remote_port, shared_mem + 4, sizeof(remote_port));
The sender domain issues an
EVTCHNOP_bind_interdomain
call to bind to the remote port.Code Block language c struct evtchn_bind_interdomain bind; bind.remote_dom = remote_domid; bind.remote_port = remote_port; bind.local_port = 0; ret = xen_hypercall(EVTCHNOP_bind_interdomain, (unsigned long)&bind, 0, 0, HYPERVISOR_event_channel_op);
The sender domain can start sending notifications to the receiver domain by issuing
EVTCHNOP_send hypercalls
Code Block language c struct evtchn_send send; send.port = bind.local_port; xen_hypercall(EVTCHNOP_send, (unsigned long)&send, 0, 0, HYPERVISOR_event_channel_op);
...