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