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