xref: /freebsd/sys/contrib/xen/argo.h (revision 3a9fd8242b35884921dfc4e886f284a75870a536)
1*3a9fd824SRoger Pau Monné /******************************************************************************
2*3a9fd824SRoger Pau Monné  * Argo : Hypervisor-Mediated data eXchange
3*3a9fd824SRoger Pau Monné  *
4*3a9fd824SRoger Pau Monné  * Derived from v4v, the version 2 of v2v.
5*3a9fd824SRoger Pau Monné  *
6*3a9fd824SRoger Pau Monné  * Copyright (c) 2010, Citrix Systems
7*3a9fd824SRoger Pau Monné  * Copyright (c) 2018-2019, BAE Systems
8*3a9fd824SRoger Pau Monné  *
9*3a9fd824SRoger Pau Monné  * Permission is hereby granted, free of charge, to any person obtaining a copy
10*3a9fd824SRoger Pau Monné  * of this software and associated documentation files (the "Software"), to
11*3a9fd824SRoger Pau Monné  * deal in the Software without restriction, including without limitation the
12*3a9fd824SRoger Pau Monné  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13*3a9fd824SRoger Pau Monné  * sell copies of the Software, and to permit persons to whom the Software is
14*3a9fd824SRoger Pau Monné  * furnished to do so, subject to the following conditions:
15*3a9fd824SRoger Pau Monné  *
16*3a9fd824SRoger Pau Monné  * The above copyright notice and this permission notice shall be included in
17*3a9fd824SRoger Pau Monné  * all copies or substantial portions of the Software.
18*3a9fd824SRoger Pau Monné  *
19*3a9fd824SRoger Pau Monné  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20*3a9fd824SRoger Pau Monné  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21*3a9fd824SRoger Pau Monné  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22*3a9fd824SRoger Pau Monné  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23*3a9fd824SRoger Pau Monné  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24*3a9fd824SRoger Pau Monné  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25*3a9fd824SRoger Pau Monné  * DEALINGS IN THE SOFTWARE.
26*3a9fd824SRoger Pau Monné  *
27*3a9fd824SRoger Pau Monné  */
28*3a9fd824SRoger Pau Monné 
29*3a9fd824SRoger Pau Monné #ifndef __XEN_PUBLIC_ARGO_H__
30*3a9fd824SRoger Pau Monné #define __XEN_PUBLIC_ARGO_H__
31*3a9fd824SRoger Pau Monné 
32*3a9fd824SRoger Pau Monné #include "xen.h"
33*3a9fd824SRoger Pau Monné 
34*3a9fd824SRoger Pau Monné #define XEN_ARGO_DOMID_ANY       DOMID_INVALID
35*3a9fd824SRoger Pau Monné 
36*3a9fd824SRoger Pau Monné /* The maximum size of an Argo ring is defined to be: 16MB (0x1000000 bytes). */
37*3a9fd824SRoger Pau Monné #define XEN_ARGO_MAX_RING_SIZE  (0x1000000ULL)
38*3a9fd824SRoger Pau Monné 
39*3a9fd824SRoger Pau Monné /* Fixed-width type for "argo port" number. Nothing to do with evtchns. */
40*3a9fd824SRoger Pau Monné typedef uint32_t xen_argo_port_t;
41*3a9fd824SRoger Pau Monné 
42*3a9fd824SRoger Pau Monné /* gfn type: 64-bit fixed-width on all architectures */
43*3a9fd824SRoger Pau Monné typedef uint64_t xen_argo_gfn_t;
44*3a9fd824SRoger Pau Monné 
45*3a9fd824SRoger Pau Monné /*
46*3a9fd824SRoger Pau Monné  * XEN_ARGO_MAXIOV : maximum number of iovs accepted in a single sendv.
47*3a9fd824SRoger Pau Monné  * Caution is required if this value is increased: this determines the size of
48*3a9fd824SRoger Pau Monné  * an array of xen_argo_iov_t structs on the hypervisor stack, so could cause
49*3a9fd824SRoger Pau Monné  * stack overflow if the value is too large.
50*3a9fd824SRoger Pau Monné  * The Linux Argo driver never passes more than two iovs.
51*3a9fd824SRoger Pau Monné */
52*3a9fd824SRoger Pau Monné #define XEN_ARGO_MAXIOV          8U
53*3a9fd824SRoger Pau Monné 
54*3a9fd824SRoger Pau Monné typedef struct xen_argo_iov
55*3a9fd824SRoger Pau Monné {
56*3a9fd824SRoger Pau Monné     XEN_GUEST_HANDLE(uint8) iov_hnd;
57*3a9fd824SRoger Pau Monné     uint32_t iov_len;
58*3a9fd824SRoger Pau Monné     uint32_t pad;
59*3a9fd824SRoger Pau Monné } xen_argo_iov_t;
60*3a9fd824SRoger Pau Monné 
61*3a9fd824SRoger Pau Monné typedef struct xen_argo_addr
62*3a9fd824SRoger Pau Monné {
63*3a9fd824SRoger Pau Monné     xen_argo_port_t aport;
64*3a9fd824SRoger Pau Monné     domid_t domain_id;
65*3a9fd824SRoger Pau Monné     uint16_t pad;
66*3a9fd824SRoger Pau Monné } xen_argo_addr_t;
67*3a9fd824SRoger Pau Monné 
68*3a9fd824SRoger Pau Monné typedef struct xen_argo_send_addr
69*3a9fd824SRoger Pau Monné {
70*3a9fd824SRoger Pau Monné     xen_argo_addr_t src;
71*3a9fd824SRoger Pau Monné     xen_argo_addr_t dst;
72*3a9fd824SRoger Pau Monné } xen_argo_send_addr_t;
73*3a9fd824SRoger Pau Monné 
74*3a9fd824SRoger Pau Monné typedef struct xen_argo_ring
75*3a9fd824SRoger Pau Monné {
76*3a9fd824SRoger Pau Monné     /* Guests should use atomic operations to access rx_ptr */
77*3a9fd824SRoger Pau Monné     uint32_t rx_ptr;
78*3a9fd824SRoger Pau Monné     /* Guests should use atomic operations to access tx_ptr */
79*3a9fd824SRoger Pau Monné     uint32_t tx_ptr;
80*3a9fd824SRoger Pau Monné     /*
81*3a9fd824SRoger Pau Monné      * Header space reserved for later use. Align the start of the ring to a
82*3a9fd824SRoger Pau Monné      * multiple of the message slot size.
83*3a9fd824SRoger Pau Monné      */
84*3a9fd824SRoger Pau Monné     uint8_t reserved[56];
85*3a9fd824SRoger Pau Monné     uint8_t ring[XEN_FLEX_ARRAY_DIM];
86*3a9fd824SRoger Pau Monné } xen_argo_ring_t;
87*3a9fd824SRoger Pau Monné 
88*3a9fd824SRoger Pau Monné typedef struct xen_argo_register_ring
89*3a9fd824SRoger Pau Monné {
90*3a9fd824SRoger Pau Monné     xen_argo_port_t aport;
91*3a9fd824SRoger Pau Monné     domid_t partner_id;
92*3a9fd824SRoger Pau Monné     uint16_t pad;
93*3a9fd824SRoger Pau Monné     uint32_t len;
94*3a9fd824SRoger Pau Monné } xen_argo_register_ring_t;
95*3a9fd824SRoger Pau Monné 
96*3a9fd824SRoger Pau Monné typedef struct xen_argo_unregister_ring
97*3a9fd824SRoger Pau Monné {
98*3a9fd824SRoger Pau Monné     xen_argo_port_t aport;
99*3a9fd824SRoger Pau Monné     domid_t partner_id;
100*3a9fd824SRoger Pau Monné     uint16_t pad;
101*3a9fd824SRoger Pau Monné } xen_argo_unregister_ring_t;
102*3a9fd824SRoger Pau Monné 
103*3a9fd824SRoger Pau Monné /* Messages on the ring are padded to a multiple of this size. */
104*3a9fd824SRoger Pau Monné #define XEN_ARGO_MSG_SLOT_SIZE 0x10
105*3a9fd824SRoger Pau Monné 
106*3a9fd824SRoger Pau Monné /*
107*3a9fd824SRoger Pau Monné  * Notify flags
108*3a9fd824SRoger Pau Monné  */
109*3a9fd824SRoger Pau Monné /* Ring exists */
110*3a9fd824SRoger Pau Monné #define XEN_ARGO_RING_EXISTS            (1U << 0)
111*3a9fd824SRoger Pau Monné /* Ring is shared, not unicast */
112*3a9fd824SRoger Pau Monné #define XEN_ARGO_RING_SHARED            (1U << 1)
113*3a9fd824SRoger Pau Monné /* Ring is empty */
114*3a9fd824SRoger Pau Monné #define XEN_ARGO_RING_EMPTY             (1U << 2)
115*3a9fd824SRoger Pau Monné /* Sufficient space to queue space_required bytes might exist */
116*3a9fd824SRoger Pau Monné #define XEN_ARGO_RING_SUFFICIENT        (1U << 3)
117*3a9fd824SRoger Pau Monné /* Insufficient ring size for space_required bytes */
118*3a9fd824SRoger Pau Monné #define XEN_ARGO_RING_EMSGSIZE          (1U << 4)
119*3a9fd824SRoger Pau Monné /* Too many domains waiting for available space signals for this ring */
120*3a9fd824SRoger Pau Monné #define XEN_ARGO_RING_EBUSY             (1U << 5)
121*3a9fd824SRoger Pau Monné 
122*3a9fd824SRoger Pau Monné typedef struct xen_argo_ring_data_ent
123*3a9fd824SRoger Pau Monné {
124*3a9fd824SRoger Pau Monné     xen_argo_addr_t ring;
125*3a9fd824SRoger Pau Monné     uint16_t flags;
126*3a9fd824SRoger Pau Monné     uint16_t pad;
127*3a9fd824SRoger Pau Monné     uint32_t space_required;
128*3a9fd824SRoger Pau Monné     uint32_t max_message_size;
129*3a9fd824SRoger Pau Monné } xen_argo_ring_data_ent_t;
130*3a9fd824SRoger Pau Monné 
131*3a9fd824SRoger Pau Monné typedef struct xen_argo_ring_data
132*3a9fd824SRoger Pau Monné {
133*3a9fd824SRoger Pau Monné     uint32_t nent;
134*3a9fd824SRoger Pau Monné     uint32_t pad;
135*3a9fd824SRoger Pau Monné     xen_argo_ring_data_ent_t data[XEN_FLEX_ARRAY_DIM];
136*3a9fd824SRoger Pau Monné } xen_argo_ring_data_t;
137*3a9fd824SRoger Pau Monné 
138*3a9fd824SRoger Pau Monné struct xen_argo_ring_message_header
139*3a9fd824SRoger Pau Monné {
140*3a9fd824SRoger Pau Monné     uint32_t len;
141*3a9fd824SRoger Pau Monné     xen_argo_addr_t source;
142*3a9fd824SRoger Pau Monné     uint32_t message_type;
143*3a9fd824SRoger Pau Monné     uint8_t data[XEN_FLEX_ARRAY_DIM];
144*3a9fd824SRoger Pau Monné };
145*3a9fd824SRoger Pau Monné 
146*3a9fd824SRoger Pau Monné /*
147*3a9fd824SRoger Pau Monné  * Hypercall operations
148*3a9fd824SRoger Pau Monné  */
149*3a9fd824SRoger Pau Monné 
150*3a9fd824SRoger Pau Monné /*
151*3a9fd824SRoger Pau Monné  * XEN_ARGO_OP_register_ring
152*3a9fd824SRoger Pau Monné  *
153*3a9fd824SRoger Pau Monné  * Register a ring using the guest-supplied memory pages.
154*3a9fd824SRoger Pau Monné  * Also used to reregister an existing ring (eg. after resume from hibernate).
155*3a9fd824SRoger Pau Monné  *
156*3a9fd824SRoger Pau Monné  * The first argument struct indicates the port number for the ring to register
157*3a9fd824SRoger Pau Monné  * and the partner domain, if any, that is to be allowed to send to the ring.
158*3a9fd824SRoger Pau Monné  * A wildcard (XEN_ARGO_DOMID_ANY) may be supplied instead of a partner domid,
159*3a9fd824SRoger Pau Monné  * and if the hypervisor has wildcard sender rings enabled, this will allow
160*3a9fd824SRoger Pau Monné  * any domain (XSM notwithstanding) to send to the ring.
161*3a9fd824SRoger Pau Monné  *
162*3a9fd824SRoger Pau Monné  * The second argument is an array of guest frame numbers and the third argument
163*3a9fd824SRoger Pau Monné  * indicates the size of the array. This operation only supports 4K-sized pages.
164*3a9fd824SRoger Pau Monné  *
165*3a9fd824SRoger Pau Monné  * arg1: XEN_GUEST_HANDLE(xen_argo_register_ring_t)
166*3a9fd824SRoger Pau Monné  * arg2: XEN_GUEST_HANDLE(xen_argo_gfn_t)
167*3a9fd824SRoger Pau Monné  * arg3: unsigned long npages
168*3a9fd824SRoger Pau Monné  * arg4: unsigned long flags (32-bit value)
169*3a9fd824SRoger Pau Monné  */
170*3a9fd824SRoger Pau Monné #define XEN_ARGO_OP_register_ring     1
171*3a9fd824SRoger Pau Monné 
172*3a9fd824SRoger Pau Monné /* Register op flags */
173*3a9fd824SRoger Pau Monné /*
174*3a9fd824SRoger Pau Monné  * Fail exist:
175*3a9fd824SRoger Pau Monné  * If set, reject attempts to (re)register an existing established ring.
176*3a9fd824SRoger Pau Monné  * If clear, reregistration occurs if the ring exists, with the new ring
177*3a9fd824SRoger Pau Monné  * taking the place of the old, preserving tx_ptr if it remains valid.
178*3a9fd824SRoger Pau Monné  */
179*3a9fd824SRoger Pau Monné #define XEN_ARGO_REGISTER_FLAG_FAIL_EXIST  0x1
180*3a9fd824SRoger Pau Monné 
181*3a9fd824SRoger Pau Monné #ifdef __XEN__
182*3a9fd824SRoger Pau Monné /* Mask for all defined flags. */
183*3a9fd824SRoger Pau Monné #define XEN_ARGO_REGISTER_FLAG_MASK XEN_ARGO_REGISTER_FLAG_FAIL_EXIST
184*3a9fd824SRoger Pau Monné #endif
185*3a9fd824SRoger Pau Monné 
186*3a9fd824SRoger Pau Monné /*
187*3a9fd824SRoger Pau Monné  * XEN_ARGO_OP_unregister_ring
188*3a9fd824SRoger Pau Monné  *
189*3a9fd824SRoger Pau Monné  * Unregister a previously-registered ring, ending communication.
190*3a9fd824SRoger Pau Monné  *
191*3a9fd824SRoger Pau Monné  * arg1: XEN_GUEST_HANDLE(xen_argo_unregister_ring_t)
192*3a9fd824SRoger Pau Monné  * arg2: NULL
193*3a9fd824SRoger Pau Monné  * arg3: 0 (ZERO)
194*3a9fd824SRoger Pau Monné  * arg4: 0 (ZERO)
195*3a9fd824SRoger Pau Monné  */
196*3a9fd824SRoger Pau Monné #define XEN_ARGO_OP_unregister_ring     2
197*3a9fd824SRoger Pau Monné 
198*3a9fd824SRoger Pau Monné /*
199*3a9fd824SRoger Pau Monné  * XEN_ARGO_OP_sendv
200*3a9fd824SRoger Pau Monné  *
201*3a9fd824SRoger Pau Monné  * Send a list of buffers contained in iovs.
202*3a9fd824SRoger Pau Monné  *
203*3a9fd824SRoger Pau Monné  * The send address struct specifies the source and destination addresses
204*3a9fd824SRoger Pau Monné  * for the message being sent, which are used to find the destination ring:
205*3a9fd824SRoger Pau Monné  * Xen first looks for a most-specific match with a registered ring with
206*3a9fd824SRoger Pau Monné  *  (id.addr == dst) and (id.partner == sending_domain) ;
207*3a9fd824SRoger Pau Monné  * if that fails, it then looks for a wildcard match (aka multicast receiver)
208*3a9fd824SRoger Pau Monné  * where (id.addr == dst) and (id.partner == DOMID_ANY).
209*3a9fd824SRoger Pau Monné  *
210*3a9fd824SRoger Pau Monné  * For each iov entry, send iov_len bytes from iov_base to the destination ring.
211*3a9fd824SRoger Pau Monné  * If insufficient space exists in the destination ring, it will return -EAGAIN
212*3a9fd824SRoger Pau Monné  * and Xen will notify the caller when sufficient space becomes available.
213*3a9fd824SRoger Pau Monné  *
214*3a9fd824SRoger Pau Monné  * The message type is a 32-bit data field available to communicate message
215*3a9fd824SRoger Pau Monné  * context data (eg. kernel-to-kernel, rather than application layer).
216*3a9fd824SRoger Pau Monné  *
217*3a9fd824SRoger Pau Monné  * arg1: XEN_GUEST_HANDLE(xen_argo_send_addr_t) source and dest addresses
218*3a9fd824SRoger Pau Monné  * arg2: XEN_GUEST_HANDLE(xen_argo_iov_t) iovs
219*3a9fd824SRoger Pau Monné  * arg3: unsigned long niov
220*3a9fd824SRoger Pau Monné  * arg4: unsigned long message type (32-bit value)
221*3a9fd824SRoger Pau Monné  */
222*3a9fd824SRoger Pau Monné #define XEN_ARGO_OP_sendv               3
223*3a9fd824SRoger Pau Monné 
224*3a9fd824SRoger Pau Monné /*
225*3a9fd824SRoger Pau Monné  * XEN_ARGO_OP_notify
226*3a9fd824SRoger Pau Monné  *
227*3a9fd824SRoger Pau Monné  * Asks Xen for information about other rings in the system.
228*3a9fd824SRoger Pau Monné  *
229*3a9fd824SRoger Pau Monné  * ent->ring is the xen_argo_addr_t of the ring you want information on.
230*3a9fd824SRoger Pau Monné  * Uses the same ring matching rules as XEN_ARGO_OP_sendv.
231*3a9fd824SRoger Pau Monné  *
232*3a9fd824SRoger Pau Monné  * ent->space_required : if this field is not null then Xen will check
233*3a9fd824SRoger Pau Monné  * that there is space in the destination ring for this many bytes of payload.
234*3a9fd824SRoger Pau Monné  * If the ring is too small for the requested space_required, it will set the
235*3a9fd824SRoger Pau Monné  * XEN_ARGO_RING_EMSGSIZE flag on return.
236*3a9fd824SRoger Pau Monné  * If sufficient space is available, it will set XEN_ARGO_RING_SUFFICIENT
237*3a9fd824SRoger Pau Monné  * and CANCEL any pending notification for that ent->ring; otherwise it
238*3a9fd824SRoger Pau Monné  * will schedule a notification event and the flag will not be set.
239*3a9fd824SRoger Pau Monné  *
240*3a9fd824SRoger Pau Monné  * These flags are set by Xen when notify replies:
241*3a9fd824SRoger Pau Monné  * XEN_ARGO_RING_EXISTS     ring exists
242*3a9fd824SRoger Pau Monné  * XEN_ARGO_RING_SHARED     ring is registered for wildcard partner
243*3a9fd824SRoger Pau Monné  * XEN_ARGO_RING_EMPTY      ring is empty
244*3a9fd824SRoger Pau Monné  * XEN_ARGO_RING_SUFFICIENT sufficient space for space_required is there
245*3a9fd824SRoger Pau Monné  * XEN_ARGO_RING_EMSGSIZE   space_required is too large for the ring size
246*3a9fd824SRoger Pau Monné  * XEN_ARGO_RING_EBUSY      too many domains waiting for available space signals
247*3a9fd824SRoger Pau Monné  *
248*3a9fd824SRoger Pau Monné  * arg1: XEN_GUEST_HANDLE(xen_argo_ring_data_t) ring_data (may be NULL)
249*3a9fd824SRoger Pau Monné  * arg2: NULL
250*3a9fd824SRoger Pau Monné  * arg3: 0 (ZERO)
251*3a9fd824SRoger Pau Monné  * arg4: 0 (ZERO)
252*3a9fd824SRoger Pau Monné  */
253*3a9fd824SRoger Pau Monné #define XEN_ARGO_OP_notify              4
254*3a9fd824SRoger Pau Monné 
255*3a9fd824SRoger Pau Monné #endif
256