1 #ifndef HW_HYPERV_DYNMEM_PROTO_H 2 #define HW_HYPERV_DYNMEM_PROTO_H 3 4 /* 5 * Hyper-V Dynamic Memory Protocol definitions 6 * 7 * Copyright (C) 2020-2023 Oracle and/or its affiliates. 8 * 9 * Based on drivers/hv/hv_balloon.c from Linux kernel: 10 * Copyright (c) 2012, Microsoft Corporation. 11 * 12 * Author: K. Y. Srinivasan <kys@microsoft.com> 13 * 14 * This work is licensed under the terms of the GNU GPL, version 2. 15 * See the COPYING file in the top-level directory. 16 */ 17 18 /* 19 * Protocol versions. The low word is the minor version, the high word the major 20 * version. 21 * 22 * History: 23 * Initial version 1.0 24 * Changed to 0.1 on 2009/03/25 25 * Changes to 0.2 on 2009/05/14 26 * Changes to 0.3 on 2009/12/03 27 * Changed to 1.0 on 2011/04/05 28 * Changed to 2.0 on 2019/12/10 29 */ 30 31 #define DYNMEM_MAKE_VERSION(Major, Minor) ((uint32_t)(((Major) << 16) | (Minor))) 32 #define DYNMEM_MAJOR_VERSION(Version) ((uint32_t)(Version) >> 16) 33 #define DYNMEM_MINOR_VERSION(Version) ((uint32_t)(Version) & 0xff) 34 35 enum { 36 DYNMEM_PROTOCOL_VERSION_1 = DYNMEM_MAKE_VERSION(0, 3), 37 DYNMEM_PROTOCOL_VERSION_2 = DYNMEM_MAKE_VERSION(1, 0), 38 DYNMEM_PROTOCOL_VERSION_3 = DYNMEM_MAKE_VERSION(2, 0), 39 40 DYNMEM_PROTOCOL_VERSION_WIN7 = DYNMEM_PROTOCOL_VERSION_1, 41 DYNMEM_PROTOCOL_VERSION_WIN8 = DYNMEM_PROTOCOL_VERSION_2, 42 DYNMEM_PROTOCOL_VERSION_WIN10 = DYNMEM_PROTOCOL_VERSION_3, 43 44 DYNMEM_PROTOCOL_VERSION_CURRENT = DYNMEM_PROTOCOL_VERSION_WIN10 45 }; 46 47 48 49 /* 50 * Message Types 51 */ 52 53 enum dm_message_type { 54 /* 55 * Version 0.3 56 */ 57 DM_ERROR = 0, 58 DM_VERSION_REQUEST = 1, 59 DM_VERSION_RESPONSE = 2, 60 DM_CAPABILITIES_REPORT = 3, 61 DM_CAPABILITIES_RESPONSE = 4, 62 DM_STATUS_REPORT = 5, 63 DM_BALLOON_REQUEST = 6, 64 DM_BALLOON_RESPONSE = 7, 65 DM_UNBALLOON_REQUEST = 8, 66 DM_UNBALLOON_RESPONSE = 9, 67 DM_MEM_HOT_ADD_REQUEST = 10, 68 DM_MEM_HOT_ADD_RESPONSE = 11, 69 DM_VERSION_03_MAX = 11, 70 /* 71 * Version 1.0. 72 */ 73 DM_INFO_MESSAGE = 12, 74 DM_VERSION_1_MAX = 12, 75 76 /* 77 * Version 2.0 78 */ 79 DM_MEM_HOT_REMOVE_REQUEST = 13, 80 DM_MEM_HOT_REMOVE_RESPONSE = 14 81 }; 82 83 84 /* 85 * Structures defining the dynamic memory management 86 * protocol. 87 */ 88 89 union dm_version { 90 struct { 91 uint16_t minor_version; 92 uint16_t major_version; 93 }; 94 uint32_t version; 95 } QEMU_PACKED; 96 97 98 union dm_caps { 99 struct { 100 uint64_t balloon:1; 101 uint64_t hot_add:1; 102 /* 103 * To support guests that may have alignment 104 * limitations on hot-add, the guest can specify 105 * its alignment requirements; a value of n 106 * represents an alignment of 2^n in mega bytes. 107 */ 108 uint64_t hot_add_alignment:4; 109 uint64_t hot_remove:1; 110 uint64_t reservedz:57; 111 } cap_bits; 112 uint64_t caps; 113 } QEMU_PACKED; 114 115 union dm_mem_page_range { 116 struct { 117 /* 118 * The PFN number of the first page in the range. 119 * 40 bits is the architectural limit of a PFN 120 * number for AMD64. 121 */ 122 uint64_t start_page:40; 123 /* 124 * The number of pages in the range. 125 */ 126 uint64_t page_cnt:24; 127 } finfo; 128 uint64_t page_range; 129 } QEMU_PACKED; 130 131 132 133 /* 134 * The header for all dynamic memory messages: 135 * 136 * type: Type of the message. 137 * size: Size of the message in bytes; including the header. 138 * trans_id: The guest is responsible for manufacturing this ID. 139 */ 140 141 struct dm_header { 142 uint16_t type; 143 uint16_t size; 144 uint32_t trans_id; 145 } QEMU_PACKED; 146 147 /* 148 * A generic message format for dynamic memory. 149 * Specific message formats are defined later in the file. 150 */ 151 152 struct dm_message { 153 struct dm_header hdr; 154 uint8_t data[]; /* enclosed message */ 155 } QEMU_PACKED; 156 157 158 /* 159 * Specific message types supporting the dynamic memory protocol. 160 */ 161 162 /* 163 * Version negotiation message. Sent from the guest to the host. 164 * The guest is free to try different versions until the host 165 * accepts the version. 166 * 167 * dm_version: The protocol version requested. 168 * is_last_attempt: If TRUE, this is the last version guest will request. 169 * reservedz: Reserved field, set to zero. 170 */ 171 172 struct dm_version_request { 173 struct dm_header hdr; 174 union dm_version version; 175 uint32_t is_last_attempt:1; 176 uint32_t reservedz:31; 177 } QEMU_PACKED; 178 179 /* 180 * Version response message; Host to Guest and indicates 181 * if the host has accepted the version sent by the guest. 182 * 183 * is_accepted: If TRUE, host has accepted the version and the guest 184 * should proceed to the next stage of the protocol. FALSE indicates that 185 * guest should re-try with a different version. 186 * 187 * reservedz: Reserved field, set to zero. 188 */ 189 190 struct dm_version_response { 191 struct dm_header hdr; 192 uint64_t is_accepted:1; 193 uint64_t reservedz:63; 194 } QEMU_PACKED; 195 196 /* 197 * Message reporting capabilities. This is sent from the guest to the 198 * host. 199 */ 200 201 struct dm_capabilities { 202 struct dm_header hdr; 203 union dm_caps caps; 204 uint64_t min_page_cnt; 205 uint64_t max_page_number; 206 } QEMU_PACKED; 207 208 /* 209 * Response to the capabilities message. This is sent from the host to the 210 * guest. This message notifies if the host has accepted the guest's 211 * capabilities. If the host has not accepted, the guest must shutdown 212 * the service. 213 * 214 * is_accepted: Indicates if the host has accepted guest's capabilities. 215 * reservedz: Must be 0. 216 */ 217 218 struct dm_capabilities_resp_msg { 219 struct dm_header hdr; 220 uint64_t is_accepted:1; 221 uint64_t hot_remove:1; 222 uint64_t suppress_pressure_reports:1; 223 uint64_t reservedz:61; 224 } QEMU_PACKED; 225 226 /* 227 * This message is used to report memory pressure from the guest. 228 * This message is not part of any transaction and there is no 229 * response to this message. 230 * 231 * num_avail: Available memory in pages. 232 * num_committed: Committed memory in pages. 233 * page_file_size: The accumulated size of all page files 234 * in the system in pages. 235 * zero_free: The number of zero and free pages. 236 * page_file_writes: The writes to the page file in pages. 237 * io_diff: An indicator of file cache efficiency or page file activity, 238 * calculated as File Cache Page Fault Count - Page Read Count. 239 * This value is in pages. 240 * 241 * Some of these metrics are Windows specific and fortunately 242 * the algorithm on the host side that computes the guest memory 243 * pressure only uses num_committed value. 244 */ 245 246 struct dm_status { 247 struct dm_header hdr; 248 uint64_t num_avail; 249 uint64_t num_committed; 250 uint64_t page_file_size; 251 uint64_t zero_free; 252 uint32_t page_file_writes; 253 uint32_t io_diff; 254 } QEMU_PACKED; 255 256 257 /* 258 * Message to ask the guest to allocate memory - balloon up message. 259 * This message is sent from the host to the guest. The guest may not be 260 * able to allocate as much memory as requested. 261 * 262 * num_pages: number of pages to allocate. 263 */ 264 265 struct dm_balloon { 266 struct dm_header hdr; 267 uint32_t num_pages; 268 uint32_t reservedz; 269 } QEMU_PACKED; 270 271 272 /* 273 * Balloon response message; this message is sent from the guest 274 * to the host in response to the balloon message. 275 * 276 * reservedz: Reserved; must be set to zero. 277 * more_pages: If FALSE, this is the last message of the transaction. 278 * if TRUE there will be at least one more message from the guest. 279 * 280 * range_count: The number of ranges in the range array. 281 * 282 * range_array: An array of page ranges returned to the host. 283 * 284 */ 285 286 struct dm_balloon_response { 287 struct dm_header hdr; 288 uint32_t reservedz; 289 uint32_t more_pages:1; 290 uint32_t range_count:31; 291 union dm_mem_page_range range_array[]; 292 } QEMU_PACKED; 293 294 /* 295 * Un-balloon message; this message is sent from the host 296 * to the guest to give guest more memory. 297 * 298 * more_pages: If FALSE, this is the last message of the transaction. 299 * if TRUE there will be at least one more message from the guest. 300 * 301 * reservedz: Reserved; must be set to zero. 302 * 303 * range_count: The number of ranges in the range array. 304 * 305 * range_array: An array of page ranges returned to the host. 306 * 307 */ 308 309 struct dm_unballoon_request { 310 struct dm_header hdr; 311 uint32_t more_pages:1; 312 uint32_t reservedz:31; 313 uint32_t range_count; 314 union dm_mem_page_range range_array[]; 315 } QEMU_PACKED; 316 317 /* 318 * Un-balloon response message; this message is sent from the guest 319 * to the host in response to an unballoon request. 320 * 321 */ 322 323 struct dm_unballoon_response { 324 struct dm_header hdr; 325 } QEMU_PACKED; 326 327 328 /* 329 * Hot add request message. Message sent from the host to the guest. 330 * 331 * range: Memory range to hot add. 332 * region: Explicit hot add memory region for guest to use. Optional. 333 * 334 */ 335 336 struct dm_hot_add { 337 struct dm_header hdr; 338 union dm_mem_page_range range; 339 } QEMU_PACKED; 340 341 struct dm_hot_add_with_region { 342 struct dm_header hdr; 343 union dm_mem_page_range range; 344 union dm_mem_page_range region; 345 } QEMU_PACKED; 346 347 /* 348 * Hot add response message. 349 * This message is sent by the guest to report the status of a hot add request. 350 * If page_count is less than the requested page count, then the host should 351 * assume all further hot add requests will fail, since this indicates that 352 * the guest has hit an upper physical memory barrier. 353 * 354 * Hot adds may also fail due to low resources; in this case, the guest must 355 * not complete this message until the hot add can succeed, and the host must 356 * not send a new hot add request until the response is sent. 357 * If VSC fails to hot add memory DYNMEM_NUMBER_OF_UNSUCCESSFUL_HOTADD_ATTEMPTS 358 * times it fails the request. 359 * 360 * 361 * page_count: number of pages that were successfully hot added. 362 * 363 * result: result of the operation 1: success, 0: failure. 364 * 365 */ 366 367 struct dm_hot_add_response { 368 struct dm_header hdr; 369 uint32_t page_count; 370 uint32_t result; 371 } QEMU_PACKED; 372 373 struct dm_hot_remove { 374 struct dm_header hdr; 375 uint32_t virtual_node; 376 uint32_t page_count; 377 uint32_t qos_flags; 378 uint32_t reservedZ; 379 } QEMU_PACKED; 380 381 struct dm_hot_remove_response { 382 struct dm_header hdr; 383 uint32_t result; 384 uint32_t range_count; 385 uint64_t more_pages:1; 386 uint64_t reservedz:63; 387 union dm_mem_page_range range_array[]; 388 } QEMU_PACKED; 389 390 #define DM_REMOVE_QOS_LARGE (1 << 0) 391 #define DM_REMOVE_QOS_LOCAL (1 << 1) 392 #define DM_REMOVE_QOS_MASK (0x3) 393 394 /* 395 * Types of information sent from host to the guest. 396 */ 397 398 enum dm_info_type { 399 INFO_TYPE_MAX_PAGE_CNT = 0, 400 MAX_INFO_TYPE 401 }; 402 403 404 /* 405 * Header for the information message. 406 */ 407 408 struct dm_info_header { 409 enum dm_info_type type; 410 uint32_t data_size; 411 uint8_t data[]; 412 } QEMU_PACKED; 413 414 /* 415 * This message is sent from the host to the guest to pass 416 * some relevant information (win8 addition). 417 * 418 * reserved: no used. 419 * info_size: size of the information blob. 420 * info: information blob. 421 */ 422 423 struct dm_info_msg { 424 struct dm_header hdr; 425 uint32_t reserved; 426 uint32_t info_size; 427 uint8_t info[]; 428 }; 429 430 #endif 431