1 /* SPDX-License-Identifier: MIT */
2 
3 /******************************************************************************
4  * grant_table.h
5  *
6  * Interface for granting foreign access to page frames, and receiving
7  * page-ownership transfers.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to
11  * deal in the Software without restriction, including without limitation the
12  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13  * sell copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26  *
27  * Copyright (c) 2004, K A Fraser
28  */
29 
30 #ifndef __XEN_PUBLIC_GRANT_TABLE_H__
31 #define __XEN_PUBLIC_GRANT_TABLE_H__
32 
33 #include "xen.h"
34 
35 /*
36  * `incontents 150 gnttab Grant Tables
37  *
38  * Xen's grant tables provide a generic mechanism to memory sharing
39  * between domains. This shared memory interface underpins the split
40  * device drivers for block and network IO.
41  *
42  * Each domain has its own grant table. This is a data structure that
43  * is shared with Xen; it allows the domain to tell Xen what kind of
44  * permissions other domains have on its pages. Entries in the grant
45  * table are identified by grant references. A grant reference is an
46  * integer, which indexes into the grant table. It acts as a
47  * capability which the grantee can use to perform operations on the
48  * granter's memory.
49  *
50  * This capability-based system allows shared-memory communications
51  * between unprivileged domains. A grant reference also encapsulates
52  * the details of a shared page, removing the need for a domain to
53  * know the real machine address of a page it is sharing. This makes
54  * it possible to share memory correctly with domains running in
55  * fully virtualised memory.
56  */
57 
58 /***********************************
59  * GRANT TABLE REPRESENTATION
60  */
61 
62 /* Some rough guidelines on accessing and updating grant-table entries
63  * in a concurrency-safe manner. For more information, Linux contains a
64  * reference implementation for guest OSes (drivers/xen/grant_table.c, see
65  * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/xen/grant-table.c;hb=HEAD
66  *
67  * NB. WMB is a no-op on current-generation x86 processors. However, a
68  *     compiler barrier will still be required.
69  *
70  * Introducing a valid entry into the grant table:
71  *  1. Write ent->domid.
72  *  2. Write ent->frame:
73  *      GTF_permit_access:   Frame to which access is permitted.
74  *      GTF_accept_transfer: Pseudo-phys frame slot being filled by new
75  *                           frame, or zero if none.
76  *  3. Write memory barrier (WMB).
77  *  4. Write ent->flags, inc. valid type.
78  *
79  * Invalidating an unused GTF_permit_access entry:
80  *  1. flags = ent->flags.
81  *  2. Observe that !(flags & (GTF_reading|GTF_writing)).
82  *  3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
83  *  NB. No need for WMB as reuse of entry is control-dependent on success of
84  *      step 3, and all architectures guarantee ordering of ctrl-dep writes.
85  *
86  * Invalidating an in-use GTF_permit_access entry:
87  *  This cannot be done directly. Request assistance from the domain controller
88  *  which can set a timeout on the use of a grant entry and take necessary
89  *  action. (NB. This is not yet implemented!).
90  *
91  * Invalidating an unused GTF_accept_transfer entry:
92  *  1. flags = ent->flags.
93  *  2. Observe that !(flags & GTF_transfer_committed). [*]
94  *  3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
95  *  NB. No need for WMB as reuse of entry is control-dependent on success of
96  *      step 3, and all architectures guarantee ordering of ctrl-dep writes.
97  *  [*] If GTF_transfer_committed is set then the grant entry is 'committed'.
98  *      The guest must /not/ modify the grant entry until the address of the
99  *      transferred frame is written. It is safe for the guest to spin waiting
100  *      for this to occur (detect by observing GTF_transfer_completed in
101  *      ent->flags).
102  *
103  * Invalidating a committed GTF_accept_transfer entry:
104  *  1. Wait for (ent->flags & GTF_transfer_completed).
105  *
106  * Changing a GTF_permit_access from writable to read-only:
107  *  Use SMP-safe CMPXCHG to set GTF_readonly, while checking !GTF_writing.
108  *
109  * Changing a GTF_permit_access from read-only to writable:
110  *  Use SMP-safe bit-setting instruction.
111  */
112 
113 /*
114  * Reference to a grant entry in a specified domain's grant table.
115  */
116 typedef uint32_t grant_ref_t;
117 
118 /*
119  * A grant table comprises a packed array of grant entries in one or more
120  * page frames shared between Xen and a guest.
121  * [XEN]: This field is written by Xen and read by the sharing guest.
122  * [GST]: This field is written by the guest and read by Xen.
123  */
124 
125 /*
126  * Version 1 of the grant table entry structure is maintained purely
127  * for backwards compatibility.  New guests should use version 2.
128  */
129 #if CONFIG_XEN_INTERFACE_VERSION < 0x0003020a
130 #define grant_entry_v1 grant_entry
131 #define grant_entry_v1_t grant_entry_t
132 #endif
133 struct grant_entry_v1 {
134 	/* GTF_xxx: various type and flag information.  [XEN,GST] */
135 	uint16_t flags;
136 	/* The domain being granted foreign privileges. [GST] */
137 	domid_t  domid;
138 	/*
139 	 * GTF_permit_access: GFN that @domid is allowed to map and access. [GST]
140 	 * GTF_accept_transfer: GFN that @domid is allowed to transfer into. [GST]
141 	 * GTF_transfer_completed: MFN whose ownership transferred by @domid
142 	 * (non-translated guests only). [XEN]
143 	 */
144 	uint32_t frame;
145 };
146 typedef struct grant_entry_v1 grant_entry_v1_t;
147 
148 /* The first few grant table entries will be preserved across grant table
149  * version changes and may be pre-populated at domain creation by tools.
150  */
151 #define GNTTAB_NR_RESERVED_ENTRIES		8
152 #define GNTTAB_RESERVED_CONSOLE			0
153 #define GNTTAB_RESERVED_XENSTORE		1
154 
155 /*
156  * Type of grant entry.
157  *  GTF_invalid: This grant entry grants no privileges.
158  *  GTF_permit_access: Allow @domid to map/access @frame.
159  *  GTF_accept_transfer: Allow @domid to transfer ownership of one page frame
160  *                       to this guest. Xen writes the page number to @frame.
161  *  GTF_transitive: Allow @domid to transitively access a subrange of
162  *                  @trans_grant in @trans_domid.  No mappings are allowed.
163  */
164 #define GTF_invalid				(0U << 0)
165 #define GTF_permit_access			(1U << 0)
166 #define GTF_accept_transfer			(2U << 0)
167 #define GTF_transitive				(3U << 0)
168 #define GTF_type_mask				(3U << 0)
169 
170 /*
171  * Subflags for GTF_permit_access and GTF_transitive.
172  *  GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
173  *  GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
174  *  GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
175  * Further subflags for GTF_permit_access only.
176  *  GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags to be used for
177  *                             mappings of the grant [GST]
178  *  GTF_sub_page: Grant access to only a subrange of the page.  @domid
179  *                will only be allowed to copy from the grant, and not
180  *                map it. [GST]
181  */
182 #define _GTF_readonly				(2)
183 #define GTF_readonly				(1U << _GTF_readonly)
184 #define _GTF_reading				(3)
185 #define GTF_reading				(1U << _GTF_reading)
186 #define _GTF_writing				(4)
187 #define GTF_writing				(1U << _GTF_writing)
188 #define _GTF_PWT				(5)
189 #define GTF_PWT					(1U << _GTF_PWT)
190 #define _GTF_PCD				(6)
191 #define GTF_PCD					(1U << _GTF_PCD)
192 #define _GTF_PAT				(7)
193 #define GTF_PAT					(1U << _GTF_PAT)
194 #define _GTF_sub_page				(8)
195 #define GTF_sub_page				(1U << _GTF_sub_page)
196 
197 /*
198  * Subflags for GTF_accept_transfer:
199  *  GTF_transfer_committed: Xen sets this flag to indicate that it is committed
200  *      to transferring ownership of a page frame. When a guest sees this flag
201  *      it must /not/ modify the grant entry until GTF_transfer_completed is
202  *      set by Xen.
203  *  GTF_transfer_completed: It is safe for the guest to spin-wait on this flag
204  *      after reading GTF_transfer_committed. Xen will always write the frame
205  *      address, followed by ORing this flag, in a timely manner.
206  */
207 #define _GTF_transfer_committed			(2)
208 #define GTF_transfer_committed			(1U << _GTF_transfer_committed)
209 #define _GTF_transfer_completed			(3)
210 #define GTF_transfer_completed			(1U << _GTF_transfer_completed)
211 
212 /***********************************
213  * GRANT TABLE QUERIES AND USES
214  */
215 
216 /* ` enum neg_errnoval
217  * ` HYPERVISOR_grant_table_op(enum grant_table_op cmd,
218  * `                           void *args,
219  * `                           unsigned int count)
220  * `
221  *
222  * @args points to an array of a per-command data structure. The array
223  * has @count members
224  */
225 
226 /* ` enum grant_table_op { // GNTTABOP_* => struct gnttab_* */
227 #define GNTTABOP_map_grant_ref			0
228 #define GNTTABOP_unmap_grant_ref		1
229 #define GNTTABOP_setup_table			2
230 #define GNTTABOP_dump_table			3
231 #define GNTTABOP_transfer			4
232 #define GNTTABOP_copy				5
233 #define GNTTABOP_query_size			6
234 #define GNTTABOP_unmap_and_replace		7
235 #if CONFIG_XEN_INTERFACE_VERSION >= 0x0003020a
236 #define GNTTABOP_set_version			8
237 #define GNTTABOP_get_status_frames		9
238 #define GNTTABOP_get_version			10
239 #define GNTTABOP_swap_grant_ref			11
240 #define GNTTABOP_cache_flush			12
241 #endif /* CONFIG_XEN_INTERFACE_VERSION */
242 /* ` } */
243 
244 /*
245  * Handle to track a mapping created via a grant reference.
246  */
247 typedef uint32_t grant_handle_t;
248 
249 /*
250  * GNTTABOP_map_grant_ref: Map the grant entry (<dom>,<ref>) for access
251  * by devices and/or host CPUs. If successful, <handle> is a tracking number
252  * that must be presented later to destroy the mapping(s). On error, <status>
253  * is a negative status code.
254  * NOTES:
255  *  1. If GNTMAP_device_map is specified then <dev_bus_addr> is the address
256  *     via which I/O devices may access the granted frame.
257  *  2. If GNTMAP_host_map is specified then a mapping will be added at
258  *     either a host virtual address in the current address space, or at
259  *     a PTE at the specified machine address.  The type of mapping to
260  *     perform is selected through the GNTMAP_contains_pte flag, and the
261  *     address is specified in <host_addr>.
262  *  3. Mappings should only be destroyed via GNTTABOP_unmap_grant_ref. If a
263  *     host mapping is destroyed by other means then it is *NOT* guaranteed
264  *     to be accounted to the correct grant reference!
265  */
266 struct gnttab_map_grant_ref {
267 	/* IN parameters. */
268 	uint64_t host_addr;
269 	uint32_t flags;		/* GNTMAP_* */
270 	grant_ref_t ref;
271 	domid_t  dom;
272 	/* OUT parameters. */
273 	int16_t  status;	/* => enum grant_status */
274 	grant_handle_t handle;
275 	uint64_t dev_bus_addr;
276 };
277 typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t;
278 DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t);
279 
280 /*
281  * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
282  * tracked by <handle>. If <host_addr> or <dev_bus_addr> is zero, that
283  * field is ignored. If non-zero, they must refer to a device/host mapping
284  * that is tracked by <handle>
285  * NOTES:
286  *  1. The call may fail in an undefined manner if either mapping is not
287  *     tracked by <handle>.
288  *  3. After executing a batch of unmaps, it is guaranteed that no stale
289  *     mappings will remain in the device or host TLBs.
290  */
291 struct gnttab_unmap_grant_ref {
292 	/* IN parameters. */
293 	uint64_t host_addr;
294 	uint64_t dev_bus_addr;
295 	grant_handle_t handle;
296 	/* OUT parameters. */
297 	int16_t  status;	/* => enum grant_status */
298 };
299 typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t;
300 DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
301 
302 /*
303  * GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
304  * <nr_frames> pages. The frame addresses are written to the <frame_list>.
305  * Only <nr_frames> addresses are written, even if the table is larger.
306  * NOTES:
307  *  1. <dom> may be specified as DOMID_SELF.
308  *  2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
309  *  3. Xen may not support more than a single grant-table page per domain.
310  */
311 struct gnttab_setup_table {
312 	/* IN parameters. */
313 	domid_t  dom;
314 	uint32_t nr_frames;
315 
316 	/* OUT parameters. */
317 	int16_t status; /* => enum grant_status */
318 #if CONFIG_XEN_INTERFACE_VERSION < 0x00040300
319 	XEN_GUEST_HANDLE(ulong) frame_list;
320 #else
321 	XEN_GUEST_HANDLE(xen_pfn_t) frame_list;
322 #endif
323 };
324 typedef struct gnttab_setup_table gnttab_setup_table_t;
325 DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_t);
326 
327 
328 
329 /*
330  * Bitfield values for gnttab_map_grant_ref.flags.
331  */
332  /* Map the grant entry for access by I/O devices. */
333 #define _GNTMAP_device_map	(0)
334 #define GNTMAP_device_map	(1<<_GNTMAP_device_map)
335  /* Map the grant entry for access by host CPUs. */
336 #define _GNTMAP_host_map	(1)
337 #define GNTMAP_host_map		(1<<_GNTMAP_host_map)
338  /* Accesses to the granted frame will be restricted to read-only access. */
339 #define _GNTMAP_readonly	(2)
340 #define GNTMAP_readonly		(1<<_GNTMAP_readonly)
341  /*
342   * GNTMAP_host_map subflag:
343   *  0 => The host mapping is usable only by the guest OS.
344   *  1 => The host mapping is usable by guest OS + current application.
345   */
346 #define _GNTMAP_application_map	(3)
347 #define GNTMAP_application_map	(1<<_GNTMAP_application_map)
348 
349  /*
350   * GNTMAP_contains_pte subflag:
351   *  0 => This map request contains a host virtual address.
352   *  1 => This map request contains the machine address of the PTE to update.
353   */
354 #define _GNTMAP_contains_pte	(4)
355 #define GNTMAP_contains_pte	(1<<_GNTMAP_contains_pte)
356 
357 /*
358  * Bits to be placed in guest kernel available PTE bits (architecture
359  * dependent; only supported when XENFEAT_gnttab_map_avail_bits is set).
360  */
361 #define _GNTMAP_guest_avail0	(16)
362 #define GNTMAP_guest_avail_mask	((uint32_t)~0 << _GNTMAP_guest_avail0)
363 
364 /*
365  * Values for error status returns. All errors are -ve.
366  */
367 /* ` enum grant_status { */
368 #define GNTST_okay		(0)  /* Normal return */
369 #define GNTST_general_error	(-1) /* General undefined error */
370 #define GNTST_bad_domain	(-2) /* Unrecognsed domain id */
371 #define GNTST_bad_gntref	(-3) /* Unrecognised or inappropriate gntref */
372 #define GNTST_bad_handle	(-4) /* Unrecognised or inappropriate handle */
373 #define GNTST_bad_virt_addr	(-5) /* Inappropriate virtual address to map */
374 #define GNTST_bad_dev_addr	(-6) /* Inappropriate device address to unmap */
375 #define GNTST_no_device_space	(-7) /* Out of space in I/O MMU */
376 #define GNTST_permission_denied	(-8) /* Not enough privilege for operation */
377 #define GNTST_bad_page		(-9) /* Specified page was invalid for op */
378 #define GNTST_bad_copy_arg	(-10) /* copy arguments cross page boundary */
379 #define GNTST_address_too_big	(-11) /* transfer page address too large */
380 #define GNTST_eagain		(-12) /* Operation not done; try again */
381 /* ` } */
382 
383 #define GNTTABOP_error_msgs {				\
384 	"okay",						\
385 	"undefined error",				\
386 	"unrecognised domain id",			\
387 	"invalid grant reference",			\
388 	"invalid mapping handle",			\
389 	"invalid virtual address",			\
390 	"invalid device address",			\
391 	"no spare translation slot in the I/O MMU",	\
392 	"permission denied",				\
393 	"bad page",					\
394 	"copy arguments cross page boundary",		\
395 	"page address size too large",			\
396 	"operation not done; try again"			\
397 }
398 
399 #endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
400