| 1 |
|
| 2 | |
| 3 | * Type definitions for the Microsoft hypervisor.
|
| 4 |
|
| 5 | #ifndef _HV_HVHDK_H
|
| 6 | #define _HV_HVHDK_H
|
| 7 |
|
| 8 | #include <linux/build_bug.h>
|
| 9 |
|
| 10 | #include "hvhdk_mini.h"
|
| 11 | #include "hvgdk.h"
|
| 12 |
|
| 13 | |
| 14 | * Hypervisor statistics page format
|
| 15 |
|
| 16 | struct hv_stats_page {
|
| 17 | u64 data[HV_HYP_PAGE_SIZE / sizeof(u64)];
|
| 18 | } __packed;
|
| 19 |
|
| 20 |
|
| 21 | #define HV_X64_REGISTER_CLASS_GENERAL 0
|
| 22 | #define HV_X64_REGISTER_CLASS_IP 1
|
| 23 | #define HV_X64_REGISTER_CLASS_XMM 2
|
| 24 | #define HV_X64_REGISTER_CLASS_SEGMENT 3
|
| 25 | #define HV_X64_REGISTER_CLASS_FLAGS 4
|
| 26 |
|
| 27 | #define HV_VP_REGISTER_PAGE_VERSION_1 1u
|
| 28 |
|
| 29 | #define HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT 7
|
| 30 |
|
| 31 | union hv_vp_register_page_interrupt_vectors {
|
| 32 | u64 as_uint64;
|
| 33 | struct {
|
| 34 | u8 vector_count;
|
| 35 | u8 vector[HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT];
|
| 36 | } __packed;
|
| 37 | };
|
| 38 |
|
| 39 | struct hv_vp_register_page {
|
| 40 | u16 version;
|
| 41 | u8 isvalid;
|
| 42 | u8 rsvdz;
|
| 43 | u32 dirty;
|
| 44 |
|
| 45 | #if IS_ENABLED(CONFIG_X86)
|
| 46 |
|
| 47 | union {
|
| 48 | struct {
|
| 49 | |
| 50 | * (HV_X64_REGISTER_CLASS_GENERAL)
|
| 51 |
|
| 52 | union {
|
| 53 | struct {
|
| 54 | u64 rax;
|
| 55 | u64 rcx;
|
| 56 | u64 rdx;
|
| 57 | u64 rbx;
|
| 58 | u64 rsp;
|
| 59 | u64 rbp;
|
| 60 | u64 rsi;
|
| 61 | u64 rdi;
|
| 62 | u64 r8;
|
| 63 | u64 r9;
|
| 64 | u64 r10;
|
| 65 | u64 r11;
|
| 66 | u64 r12;
|
| 67 | u64 r13;
|
| 68 | u64 r14;
|
| 69 | u64 r15;
|
| 70 | } __packed;
|
| 71 |
|
| 72 | u64 gp_registers[16];
|
| 73 | };
|
| 74 |
|
| 75 | u64 rip;
|
| 76 |
|
| 77 | u64 rflags;
|
| 78 | } __packed;
|
| 79 |
|
| 80 | u64 registers[18];
|
| 81 | };
|
| 82 | u8 reserved[8];
|
| 83 |
|
| 84 | union {
|
| 85 | struct {
|
| 86 | struct hv_u128 xmm0;
|
| 87 | struct hv_u128 xmm1;
|
| 88 | struct hv_u128 xmm2;
|
| 89 | struct hv_u128 xmm3;
|
| 90 | struct hv_u128 xmm4;
|
| 91 | struct hv_u128 xmm5;
|
| 92 | } __packed;
|
| 93 |
|
| 94 | struct hv_u128 xmm_registers[6];
|
| 95 | };
|
| 96 |
|
| 97 | union {
|
| 98 | struct {
|
| 99 | struct hv_x64_segment_register es;
|
| 100 | struct hv_x64_segment_register cs;
|
| 101 | struct hv_x64_segment_register ss;
|
| 102 | struct hv_x64_segment_register ds;
|
| 103 | struct hv_x64_segment_register fs;
|
| 104 | struct hv_x64_segment_register gs;
|
| 105 | } __packed;
|
| 106 |
|
| 107 | struct hv_x64_segment_register segment_registers[6];
|
| 108 | };
|
| 109 |
|
| 110 | u64 cr0;
|
| 111 | u64 cr3;
|
| 112 | u64 cr4;
|
| 113 | u64 cr8;
|
| 114 | u64 efer;
|
| 115 | u64 dr7;
|
| 116 | union hv_x64_pending_interruption_register pending_interruption;
|
| 117 | union hv_x64_interrupt_state_register interrupt_state;
|
| 118 | u64 instruction_emulation_hints;
|
| 119 | u64 xfem;
|
| 120 |
|
| 121 | |
| 122 | * Fields from this point are not included in the register page save chunk.
|
| 123 | * The reserved field is intended to maintain alignment for unsaved fields.
|
| 124 |
|
| 125 | u8 reserved1[0x100];
|
| 126 |
|
| 127 | |
| 128 | * Interrupts injected as part of HvCallDispatchVp.
|
| 129 |
|
| 130 | union hv_vp_register_page_interrupt_vectors interrupt_vectors;
|
| 131 |
|
| 132 | #elif IS_ENABLED(CONFIG_ARM64)
|
| 133 |
|
| 134 | #endif
|
| 135 | } __packed;
|
| 136 |
|
| 137 | #define HV_PARTITION_PROCESSOR_FEATURES_BANKS 2
|
| 138 |
|
| 139 | union hv_partition_processor_features {
|
| 140 | u64 as_uint64[HV_PARTITION_PROCESSOR_FEATURES_BANKS];
|
| 141 | struct {
|
| 142 | u64 sse3_support : 1;
|
| 143 | u64 lahf_sahf_support : 1;
|
| 144 | u64 ssse3_support : 1;
|
| 145 | u64 sse4_1_support : 1;
|
| 146 | u64 sse4_2_support : 1;
|
| 147 | u64 sse4a_support : 1;
|
| 148 | u64 xop_support : 1;
|
| 149 | u64 pop_cnt_support : 1;
|
| 150 | u64 cmpxchg16b_support : 1;
|
| 151 | u64 altmovcr8_support : 1;
|
| 152 | u64 lzcnt_support : 1;
|
| 153 | u64 mis_align_sse_support : 1;
|
| 154 | u64 mmx_ext_support : 1;
|
| 155 | u64 amd3dnow_support : 1;
|
| 156 | u64 extended_amd3dnow_support : 1;
|
| 157 | u64 page_1gb_support : 1;
|
| 158 | u64 aes_support : 1;
|
| 159 | u64 pclmulqdq_support : 1;
|
| 160 | u64 pcid_support : 1;
|
| 161 | u64 fma4_support : 1;
|
| 162 | u64 f16c_support : 1;
|
| 163 | u64 rd_rand_support : 1;
|
| 164 | u64 rd_wr_fs_gs_support : 1;
|
| 165 | u64 smep_support : 1;
|
| 166 | u64 enhanced_fast_string_support : 1;
|
| 167 | u64 bmi1_support : 1;
|
| 168 | u64 bmi2_support : 1;
|
| 169 | u64 hle_support_deprecated : 1;
|
| 170 | u64 rtm_support_deprecated : 1;
|
| 171 | u64 movbe_support : 1;
|
| 172 | u64 npiep1_support : 1;
|
| 173 | u64 dep_x87_fpu_save_support : 1;
|
| 174 | u64 rd_seed_support : 1;
|
| 175 | u64 adx_support : 1;
|
| 176 | u64 intel_prefetch_support : 1;
|
| 177 | u64 smap_support : 1;
|
| 178 | u64 hle_support : 1;
|
| 179 | u64 rtm_support : 1;
|
| 180 | u64 rdtscp_support : 1;
|
| 181 | u64 clflushopt_support : 1;
|
| 182 | u64 clwb_support : 1;
|
| 183 | u64 sha_support : 1;
|
| 184 | u64 x87_pointers_saved_support : 1;
|
| 185 | u64 invpcid_support : 1;
|
| 186 | u64 ibrs_support : 1;
|
| 187 | u64 stibp_support : 1;
|
| 188 | u64 ibpb_support: 1;
|
| 189 | u64 unrestricted_guest_support : 1;
|
| 190 | u64 mdd_support : 1;
|
| 191 | u64 fast_short_rep_mov_support : 1;
|
| 192 | u64 l1dcache_flush_support : 1;
|
| 193 | u64 rdcl_no_support : 1;
|
| 194 | u64 ibrs_all_support : 1;
|
| 195 | u64 skip_l1df_support : 1;
|
| 196 | u64 ssb_no_support : 1;
|
| 197 | u64 rsb_a_no_support : 1;
|
| 198 | u64 virt_spec_ctrl_support : 1;
|
| 199 | u64 rd_pid_support : 1;
|
| 200 | u64 umip_support : 1;
|
| 201 | u64 mbs_no_support : 1;
|
| 202 | u64 mb_clear_support : 1;
|
| 203 | u64 taa_no_support : 1;
|
| 204 | u64 tsx_ctrl_support : 1;
|
| 205 | |
| 206 | * N.B. The final processor feature bit in bank 0 is reserved to
|
| 207 | * simplify potential downlevel backports.
|
| 208 |
|
| 209 | u64 reserved_bank0 : 1;
|
| 210 |
|
| 211 |
|
| 212 | u64 acount_mcount_support : 1;
|
| 213 | u64 tsc_invariant_support : 1;
|
| 214 | u64 cl_zero_support : 1;
|
| 215 | u64 rdpru_support : 1;
|
| 216 | u64 la57_support : 1;
|
| 217 | u64 mbec_support : 1;
|
| 218 | u64 nested_virt_support : 1;
|
| 219 | u64 psfd_support : 1;
|
| 220 | u64 cet_ss_support : 1;
|
| 221 | u64 cet_ibt_support : 1;
|
| 222 | u64 vmx_exception_inject_support : 1;
|
| 223 | u64 enqcmd_support : 1;
|
| 224 | u64 umwait_tpause_support : 1;
|
| 225 | u64 movdiri_support : 1;
|
| 226 | u64 movdir64b_support : 1;
|
| 227 | u64 cldemote_support : 1;
|
| 228 | u64 serialize_support : 1;
|
| 229 | u64 tsc_deadline_tmr_support : 1;
|
| 230 | u64 tsc_adjust_support : 1;
|
| 231 | u64 fzlrep_movsb : 1;
|
| 232 | u64 fsrep_stosb : 1;
|
| 233 | u64 fsrep_cmpsb : 1;
|
| 234 | u64 reserved_bank1 : 42;
|
| 235 | } __packed;
|
| 236 | };
|
| 237 |
|
| 238 | union hv_partition_processor_xsave_features {
|
| 239 | struct {
|
| 240 | u64 xsave_support : 1;
|
| 241 | u64 xsaveopt_support : 1;
|
| 242 | u64 avx_support : 1;
|
| 243 | u64 reserved1 : 61;
|
| 244 | } __packed;
|
| 245 | u64 as_uint64;
|
| 246 | };
|
| 247 |
|
| 248 | struct hv_partition_creation_properties {
|
| 249 | union hv_partition_processor_features disabled_processor_features;
|
| 250 | union hv_partition_processor_xsave_features
|
| 251 | disabled_processor_xsave_features;
|
| 252 | } __packed;
|
| 253 |
|
| 254 | #define HV_PARTITION_SYNTHETIC_PROCESSOR_FEATURES_BANKS 1
|
| 255 |
|
| 256 | union hv_partition_synthetic_processor_features {
|
| 257 | u64 as_uint64[HV_PARTITION_SYNTHETIC_PROCESSOR_FEATURES_BANKS];
|
| 258 |
|
| 259 | struct {
|
| 260 | u64 hypervisor_present : 1;
|
| 261 |
|
| 262 | u64 hv1 : 1;
|
| 263 | u64 access_vp_run_time_reg : 1;
|
| 264 | u64 access_partition_reference_counter : 1;
|
| 265 | u64 access_synic_regs : 1;
|
| 266 | |
| 267 | * Access to HV_X64_MSR_STIMER0_CONFIG through
|
| 268 | * HV_X64_MSR_STIMER3_COUNT.
|
| 269 |
|
| 270 | u64 access_synthetic_timer_regs : 1;
|
| 271 | u64 access_intr_ctrl_regs : 1;
|
| 272 |
|
| 273 | u64 access_hypercall_regs : 1;
|
| 274 | u64 access_vp_index : 1;
|
| 275 | u64 access_partition_reference_tsc : 1;
|
| 276 | u64 access_guest_idle_reg : 1;
|
| 277 | u64 access_frequency_regs : 1;
|
| 278 | u64 reserved_z12 : 1;
|
| 279 | u64 reserved_z13 : 1;
|
| 280 | u64 reserved_z14 : 1;
|
| 281 | u64 enable_extended_gva_ranges_for_flush_virtual_address_list : 1;
|
| 282 | u64 reserved_z16 : 1;
|
| 283 | u64 reserved_z17 : 1;
|
| 284 |
|
| 285 | u64 fast_hypercall_output : 1;
|
| 286 | u64 reserved_z19 : 1;
|
| 287 | u64 start_virtual_processor : 1;
|
| 288 | u64 reserved_z21 : 1;
|
| 289 |
|
| 290 | u64 direct_synthetic_timers : 1;
|
| 291 | u64 reserved_z23 : 1;
|
| 292 | u64 extended_processor_masks : 1;
|
| 293 |
|
| 294 |
|
| 295 | u64 tb_flush_hypercalls : 1;
|
| 296 | u64 synthetic_cluster_ipi : 1;
|
| 297 | u64 notify_long_spin_wait : 1;
|
| 298 | u64 query_numa_distance : 1;
|
| 299 | u64 signal_events : 1;
|
| 300 | u64 retarget_device_interrupt : 1;
|
| 301 | u64 restore_time : 1;
|
| 302 |
|
| 303 |
|
| 304 | u64 enlightened_vmcs : 1;
|
| 305 | u64 reserved : 31;
|
| 306 | } __packed;
|
| 307 | };
|
| 308 |
|
| 309 | #define HV_MAKE_COMPATIBILITY_VERSION(major_, minor_) \
|
| 310 | ((u32)((major_) << 8 | (minor_)))
|
| 311 |
|
| 312 | #define HV_COMPATIBILITY_21_H2 HV_MAKE_COMPATIBILITY_VERSION(0X6, 0X9)
|
| 313 |
|
| 314 | union hv_partition_isolation_properties {
|
| 315 | u64 as_uint64;
|
| 316 | struct {
|
| 317 | u64 isolation_type: 5;
|
| 318 | u64 isolation_host_type : 2;
|
| 319 | u64 rsvd_z: 5;
|
| 320 | u64 shared_gpa_boundary_page_number: 52;
|
| 321 | } __packed;
|
| 322 | };
|
| 323 |
|
| 324 | |
| 325 | * Various isolation types supported by MSHV.
|
| 326 |
|
| 327 | #define HV_PARTITION_ISOLATION_TYPE_NONE 0
|
| 328 | #define HV_PARTITION_ISOLATION_TYPE_SNP 2
|
| 329 | #define HV_PARTITION_ISOLATION_TYPE_TDX 3
|
| 330 |
|
| 331 | |
| 332 | * Various host isolation types supported by MSHV.
|
| 333 |
|
| 334 | #define HV_PARTITION_ISOLATION_HOST_TYPE_NONE 0x0
|
| 335 | #define HV_PARTITION_ISOLATION_HOST_TYPE_HARDWARE 0x1
|
| 336 | #define HV_PARTITION_ISOLATION_HOST_TYPE_RESERVED 0x2
|
| 337 |
|
| 338 |
|
| 339 | #define HV_PARTITION_CREATION_FLAG_SMT_ENABLED_GUEST BIT(0)
|
| 340 | #define HV_PARTITION_CREATION_FLAG_NESTED_VIRTUALIZATION_CAPABLE BIT(1)
|
| 341 | #define HV_PARTITION_CREATION_FLAG_GPA_SUPER_PAGES_ENABLED BIT(4)
|
| 342 | #define HV_PARTITION_CREATION_FLAG_EXO_PARTITION BIT(8)
|
| 343 | #define HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED BIT(13)
|
| 344 | #define HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED BIT(19)
|
| 345 | #define HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE BIT(22)
|
| 346 |
|
| 347 | struct hv_input_create_partition {
|
| 348 | u64 flags;
|
| 349 | struct hv_proximity_domain_info proximity_domain_info;
|
| 350 | u32 compatibility_version;
|
| 351 | u32 padding;
|
| 352 | struct hv_partition_creation_properties partition_creation_properties;
|
| 353 | union hv_partition_isolation_properties isolation_properties;
|
| 354 | } __packed;
|
| 355 |
|
| 356 | struct hv_output_create_partition {
|
| 357 | u64 partition_id;
|
| 358 | } __packed;
|
| 359 |
|
| 360 | struct hv_input_initialize_partition {
|
| 361 | u64 partition_id;
|
| 362 | } __packed;
|
| 363 |
|
| 364 | struct hv_input_finalize_partition {
|
| 365 | u64 partition_id;
|
| 366 | } __packed;
|
| 367 |
|
| 368 | struct hv_input_delete_partition {
|
| 369 | u64 partition_id;
|
| 370 | } __packed;
|
| 371 |
|
| 372 | struct hv_input_get_partition_property {
|
| 373 | u64 partition_id;
|
| 374 | u32 property_code;
|
| 375 | u32 padding;
|
| 376 | } __packed;
|
| 377 |
|
| 378 | struct hv_output_get_partition_property {
|
| 379 | u64 property_value;
|
| 380 | } __packed;
|
| 381 |
|
| 382 | struct hv_input_set_partition_property {
|
| 383 | u64 partition_id;
|
| 384 | u32 property_code;
|
| 385 | u32 padding;
|
| 386 | u64 property_value;
|
| 387 | } __packed;
|
| 388 |
|
| 389 | union hv_partition_property_arg {
|
| 390 | u64 as_uint64;
|
| 391 | struct {
|
| 392 | union {
|
| 393 | u32 arg;
|
| 394 | u32 vp_index;
|
| 395 | };
|
| 396 | u16 reserved0;
|
| 397 | u8 reserved1;
|
| 398 | u8 object_type;
|
| 399 | } __packed;
|
| 400 | };
|
| 401 |
|
| 402 | struct hv_input_get_partition_property_ex {
|
| 403 | u64 partition_id;
|
| 404 | u32 property_code;
|
| 405 | u32 padding;
|
| 406 | union {
|
| 407 | union hv_partition_property_arg arg_data;
|
| 408 | u64 arg;
|
| 409 | };
|
| 410 | } __packed;
|
| 411 |
|
| 412 | |
| 413 | * NOTE: Should use hv_input_set_partition_property_ex_header to compute this
|
| 414 | * size, but hv_input_get_partition_property_ex is identical so it suffices
|
| 415 |
|
| 416 | #define HV_PARTITION_PROPERTY_EX_MAX_VAR_SIZE \
|
| 417 | (HV_HYP_PAGE_SIZE - sizeof(struct hv_input_get_partition_property_ex))
|
| 418 |
|
| 419 | union hv_partition_property_ex {
|
| 420 | u8 buffer[HV_PARTITION_PROPERTY_EX_MAX_VAR_SIZE];
|
| 421 | struct hv_partition_property_vmm_capabilities vmm_capabilities;
|
| 422 |
|
| 423 | };
|
| 424 |
|
| 425 | struct hv_output_get_partition_property_ex {
|
| 426 | union hv_partition_property_ex property_value;
|
| 427 | } __packed;
|
| 428 |
|
| 429 | enum hv_vp_state_page_type {
|
| 430 | HV_VP_STATE_PAGE_REGISTERS = 0,
|
| 431 | HV_VP_STATE_PAGE_INTERCEPT_MESSAGE = 1,
|
| 432 | HV_VP_STATE_PAGE_GHCB = 2,
|
| 433 | HV_VP_STATE_PAGE_COUNT
|
| 434 | };
|
| 435 |
|
| 436 | struct hv_input_map_vp_state_page {
|
| 437 | u64 partition_id;
|
| 438 | u32 vp_index;
|
| 439 | u16 type;
|
| 440 | union hv_input_vtl input_vtl;
|
| 441 | union {
|
| 442 | u8 as_uint8;
|
| 443 | struct {
|
| 444 | u8 map_location_provided : 1;
|
| 445 | u8 reserved : 7;
|
| 446 | };
|
| 447 | } flags;
|
| 448 | u64 requested_map_location;
|
| 449 | } __packed;
|
| 450 |
|
| 451 | struct hv_output_map_vp_state_page {
|
| 452 | u64 map_location;
|
| 453 | } __packed;
|
| 454 |
|
| 455 | struct hv_input_unmap_vp_state_page {
|
| 456 | u64 partition_id;
|
| 457 | u32 vp_index;
|
| 458 | u16 type;
|
| 459 | union hv_input_vtl input_vtl;
|
| 460 | u8 reserved0;
|
| 461 | } __packed;
|
| 462 |
|
| 463 | struct hv_x64_apic_eoi_message {
|
| 464 | u32 vp_index;
|
| 465 | u32 interrupt_vector;
|
| 466 | } __packed;
|
| 467 |
|
| 468 | struct hv_opaque_intercept_message {
|
| 469 | u32 vp_index;
|
| 470 | } __packed;
|
| 471 |
|
| 472 | enum hv_port_type {
|
| 473 | HV_PORT_TYPE_MESSAGE = 1,
|
| 474 | HV_PORT_TYPE_EVENT = 2,
|
| 475 | HV_PORT_TYPE_MONITOR = 3,
|
| 476 | HV_PORT_TYPE_DOORBELL = 4
|
| 477 | };
|
| 478 |
|
| 479 | struct hv_port_info {
|
| 480 | u32 port_type;
|
| 481 | u32 padding;
|
| 482 | union {
|
| 483 | struct {
|
| 484 | u32 target_sint;
|
| 485 | u32 target_vp;
|
| 486 | u64 rsvdz;
|
| 487 | } message_port_info;
|
| 488 | struct {
|
| 489 | u32 target_sint;
|
| 490 | u32 target_vp;
|
| 491 | u16 base_flag_number;
|
| 492 | u16 flag_count;
|
| 493 | u32 rsvdz;
|
| 494 | } event_port_info;
|
| 495 | struct {
|
| 496 | u64 monitor_address;
|
| 497 | u64 rsvdz;
|
| 498 | } monitor_port_info;
|
| 499 | struct {
|
| 500 | u32 target_sint;
|
| 501 | u32 target_vp;
|
| 502 | u64 rsvdz;
|
| 503 | } doorbell_port_info;
|
| 504 | };
|
| 505 | } __packed;
|
| 506 |
|
| 507 | struct hv_connection_info {
|
| 508 | u32 port_type;
|
| 509 | u32 padding;
|
| 510 | union {
|
| 511 | struct {
|
| 512 | u64 rsvdz;
|
| 513 | } message_connection_info;
|
| 514 | struct {
|
| 515 | u64 rsvdz;
|
| 516 | } event_connection_info;
|
| 517 | struct {
|
| 518 | u64 monitor_address;
|
| 519 | } monitor_connection_info;
|
| 520 | struct {
|
| 521 | u64 gpa;
|
| 522 | u64 trigger_value;
|
| 523 | u64 flags;
|
| 524 | } doorbell_connection_info;
|
| 525 | };
|
| 526 | } __packed;
|
| 527 |
|
| 528 |
|
| 529 | #define HV_EVENT_FLAGS_COUNT (256 * 8)
|
| 530 | #define HV_EVENT_FLAGS_BYTE_COUNT (256)
|
| 531 | #define HV_EVENT_FLAGS32_COUNT (256 / sizeof(u32))
|
| 532 |
|
| 533 |
|
| 534 | #define HV_EVENT_FLAGS_UL_COUNT (256 / sizeof(ulong))
|
| 535 |
|
| 536 |
|
| 537 | union hv_synic_event_flags {
|
| 538 | unsigned char flags8[HV_EVENT_FLAGS_BYTE_COUNT];
|
| 539 | u32 flags32[HV_EVENT_FLAGS32_COUNT];
|
| 540 | ulong flags[HV_EVENT_FLAGS_UL_COUNT];
|
| 541 | };
|
| 542 |
|
| 543 | struct hv_synic_event_flags_page {
|
| 544 | volatile union hv_synic_event_flags event_flags[HV_SYNIC_SINT_COUNT];
|
| 545 | };
|
| 546 |
|
| 547 | #define HV_SYNIC_EVENT_RING_MESSAGE_COUNT 63
|
| 548 |
|
| 549 | struct hv_synic_event_ring {
|
| 550 | u8 signal_masked;
|
| 551 | u8 ring_full;
|
| 552 | u16 reserved_z;
|
| 553 | u32 data[HV_SYNIC_EVENT_RING_MESSAGE_COUNT];
|
| 554 | } __packed;
|
| 555 |
|
| 556 | struct hv_synic_event_ring_page {
|
| 557 | struct hv_synic_event_ring sint_event_ring[HV_SYNIC_SINT_COUNT];
|
| 558 | };
|
| 559 |
|
| 560 |
|
| 561 | union hv_synic_scontrol {
|
| 562 | u64 as_uint64;
|
| 563 | struct {
|
| 564 | u64 enable : 1;
|
| 565 | u64 reserved : 63;
|
| 566 | } __packed;
|
| 567 | };
|
| 568 |
|
| 569 |
|
| 570 | union hv_synic_siefp {
|
| 571 | u64 as_uint64;
|
| 572 | struct {
|
| 573 | u64 siefp_enabled : 1;
|
| 574 | u64 preserved : 11;
|
| 575 | u64 base_siefp_gpa : 52;
|
| 576 | } __packed;
|
| 577 | };
|
| 578 |
|
| 579 | union hv_synic_sirbp {
|
| 580 | u64 as_uint64;
|
| 581 | struct {
|
| 582 | u64 sirbp_enabled : 1;
|
| 583 | u64 preserved : 11;
|
| 584 | u64 base_sirbp_gpa : 52;
|
| 585 | } __packed;
|
| 586 | };
|
| 587 |
|
| 588 | union hv_interrupt_control {
|
| 589 | u64 as_uint64;
|
| 590 | struct {
|
| 591 | u32 interrupt_type;
|
| 592 | #if IS_ENABLED(CONFIG_X86)
|
| 593 | u32 level_triggered : 1;
|
| 594 | u32 logical_dest_mode : 1;
|
| 595 | u32 rsvd : 30;
|
| 596 | #elif IS_ENABLED(CONFIG_ARM64)
|
| 597 | u32 rsvd1 : 2;
|
| 598 | u32 asserted : 1;
|
| 599 | u32 rsvd2 : 29;
|
| 600 | #endif
|
| 601 | } __packed;
|
| 602 | };
|
| 603 |
|
| 604 | struct hv_stimer_state {
|
| 605 | struct {
|
| 606 | u32 undelivered_msg_pending : 1;
|
| 607 | u32 reserved : 31;
|
| 608 | } __packed flags;
|
| 609 | u32 resvd;
|
| 610 | u64 config;
|
| 611 | u64 count;
|
| 612 | u64 adjustment;
|
| 613 | u64 undelivered_exp_time;
|
| 614 | } __packed;
|
| 615 |
|
| 616 | struct hv_synthetic_timers_state {
|
| 617 | struct hv_stimer_state timers[HV_SYNIC_STIMER_COUNT];
|
| 618 | u64 reserved[5];
|
| 619 | } __packed;
|
| 620 |
|
| 621 | struct hv_async_completion_message_payload {
|
| 622 | u64 partition_id;
|
| 623 | u32 status;
|
| 624 | u32 completion_count;
|
| 625 | u64 sub_status;
|
| 626 | } __packed;
|
| 627 |
|
| 628 | union hv_input_delete_vp {
|
| 629 | u64 as_uint64[2];
|
| 630 | struct {
|
| 631 | u64 partition_id;
|
| 632 | u32 vp_index;
|
| 633 | u8 reserved[4];
|
| 634 | } __packed;
|
| 635 | } __packed;
|
| 636 |
|
| 637 | struct hv_input_assert_virtual_interrupt {
|
| 638 | u64 partition_id;
|
| 639 | union hv_interrupt_control control;
|
| 640 | u64 dest_addr;
|
| 641 | u32 vector;
|
| 642 | u8 target_vtl;
|
| 643 | u8 rsvd_z0;
|
| 644 | u16 rsvd_z1;
|
| 645 | } __packed;
|
| 646 |
|
| 647 | struct hv_input_create_port {
|
| 648 | u64 port_partition_id;
|
| 649 | union hv_port_id port_id;
|
| 650 | u8 port_vtl;
|
| 651 | u8 min_connection_vtl;
|
| 652 | u16 padding;
|
| 653 | u64 connection_partition_id;
|
| 654 | struct hv_port_info port_info;
|
| 655 | struct hv_proximity_domain_info proximity_domain_info;
|
| 656 | } __packed;
|
| 657 |
|
| 658 | union hv_input_delete_port {
|
| 659 | u64 as_uint64[2];
|
| 660 | struct {
|
| 661 | u64 port_partition_id;
|
| 662 | union hv_port_id port_id;
|
| 663 | u32 reserved;
|
| 664 | };
|
| 665 | } __packed;
|
| 666 |
|
| 667 | struct hv_input_connect_port {
|
| 668 | u64 connection_partition_id;
|
| 669 | union hv_connection_id connection_id;
|
| 670 | u8 connection_vtl;
|
| 671 | u8 rsvdz0;
|
| 672 | u16 rsvdz1;
|
| 673 | u64 port_partition_id;
|
| 674 | union hv_port_id port_id;
|
| 675 | u32 reserved2;
|
| 676 | struct hv_connection_info connection_info;
|
| 677 | struct hv_proximity_domain_info proximity_domain_info;
|
| 678 | } __packed;
|
| 679 |
|
| 680 | union hv_input_disconnect_port {
|
| 681 | u64 as_uint64[2];
|
| 682 | struct {
|
| 683 | u64 connection_partition_id;
|
| 684 | union hv_connection_id connection_id;
|
| 685 | u32 is_doorbell: 1;
|
| 686 | u32 reserved: 31;
|
| 687 | } __packed;
|
| 688 | } __packed;
|
| 689 |
|
| 690 | union hv_input_notify_port_ring_empty {
|
| 691 | u64 as_uint64;
|
| 692 | struct {
|
| 693 | u32 sint_index;
|
| 694 | u32 reserved;
|
| 695 | };
|
| 696 | } __packed;
|
| 697 |
|
| 698 | struct hv_vp_state_data_xsave {
|
| 699 | u64 flags;
|
| 700 | union hv_x64_xsave_xfem_register states;
|
| 701 | } __packed;
|
| 702 |
|
| 703 | |
| 704 | * For getting and setting VP state, there are two options based on the state type:
|
| 705 | *
|
| 706 | * 1.) Data that is accessed by PFNs in the input hypercall page. This is used
|
| 707 | * for state which may not fit into the hypercall pages.
|
| 708 | * 2.) Data that is accessed directly in the input\output hypercall pages.
|
| 709 | * This is used for state that will always fit into the hypercall pages.
|
| 710 | *
|
| 711 | * In the future this could be dynamic based on the size if needed.
|
| 712 | *
|
| 713 | * Note these hypercalls have an 8-byte aligned variable header size as per the tlfs
|
| 714 |
|
| 715 |
|
| 716 | #define HV_GET_SET_VP_STATE_TYPE_PFN BIT(31)
|
| 717 |
|
| 718 | enum hv_get_set_vp_state_type {
|
| 719 |
|
| 720 | HV_GET_SET_VP_STATE_LAPIC_STATE = 0 | HV_GET_SET_VP_STATE_TYPE_PFN,
|
| 721 | HV_GET_SET_VP_STATE_XSAVE = 1 | HV_GET_SET_VP_STATE_TYPE_PFN,
|
| 722 | HV_GET_SET_VP_STATE_SIM_PAGE = 2 | HV_GET_SET_VP_STATE_TYPE_PFN,
|
| 723 | HV_GET_SET_VP_STATE_SIEF_PAGE = 3 | HV_GET_SET_VP_STATE_TYPE_PFN,
|
| 724 | HV_GET_SET_VP_STATE_SYNTHETIC_TIMERS = 4,
|
| 725 | };
|
| 726 |
|
| 727 | struct hv_vp_state_data {
|
| 728 | u32 type;
|
| 729 | u32 rsvd;
|
| 730 | struct hv_vp_state_data_xsave xsave;
|
| 731 | } __packed;
|
| 732 |
|
| 733 | struct hv_input_get_vp_state {
|
| 734 | u64 partition_id;
|
| 735 | u32 vp_index;
|
| 736 | u8 input_vtl;
|
| 737 | u8 rsvd0;
|
| 738 | u16 rsvd1;
|
| 739 | struct hv_vp_state_data state_data;
|
| 740 | u64 output_data_pfns[];
|
| 741 | } __packed;
|
| 742 |
|
| 743 | union hv_output_get_vp_state {
|
| 744 | struct hv_synthetic_timers_state synthetic_timers_state;
|
| 745 | } __packed;
|
| 746 |
|
| 747 | union hv_input_set_vp_state_data {
|
| 748 | u64 pfns;
|
| 749 | u8 bytes;
|
| 750 | } __packed;
|
| 751 |
|
| 752 | struct hv_input_set_vp_state {
|
| 753 | u64 partition_id;
|
| 754 | u32 vp_index;
|
| 755 | u8 input_vtl;
|
| 756 | u8 rsvd0;
|
| 757 | u16 rsvd1;
|
| 758 | struct hv_vp_state_data state_data;
|
| 759 | union hv_input_set_vp_state_data data[];
|
| 760 | } __packed;
|
| 761 |
|
| 762 | union hv_x64_vp_execution_state {
|
| 763 | u16 as_uint16;
|
| 764 | struct {
|
| 765 | u16 cpl:2;
|
| 766 | u16 cr0_pe:1;
|
| 767 | u16 cr0_am:1;
|
| 768 | u16 efer_lma:1;
|
| 769 | u16 debug_active:1;
|
| 770 | u16 interruption_pending:1;
|
| 771 | u16 vtl:4;
|
| 772 | u16 enclave_mode:1;
|
| 773 | u16 interrupt_shadow:1;
|
| 774 | u16 virtualization_fault_active:1;
|
| 775 | u16 reserved:2;
|
| 776 | } __packed;
|
| 777 | };
|
| 778 |
|
| 779 | struct hv_x64_intercept_message_header {
|
| 780 | u32 vp_index;
|
| 781 | u8 instruction_length:4;
|
| 782 | u8 cr8:4;
|
| 783 | u8 intercept_access_type;
|
| 784 | union hv_x64_vp_execution_state execution_state;
|
| 785 | struct hv_x64_segment_register cs_segment;
|
| 786 | u64 rip;
|
| 787 | u64 rflags;
|
| 788 | } __packed;
|
| 789 |
|
| 790 | union hv_x64_memory_access_info {
|
| 791 | u8 as_uint8;
|
| 792 | struct {
|
| 793 | u8 gva_valid:1;
|
| 794 | u8 gva_gpa_valid:1;
|
| 795 | u8 hypercall_output_pending:1;
|
| 796 | u8 tlb_locked_no_overlay:1;
|
| 797 | u8 reserved:4;
|
| 798 | } __packed;
|
| 799 | };
|
| 800 |
|
| 801 | struct hv_x64_memory_intercept_message {
|
| 802 | struct hv_x64_intercept_message_header header;
|
| 803 | u32 cache_type;
|
| 804 | u8 instruction_byte_count;
|
| 805 | union hv_x64_memory_access_info memory_access_info;
|
| 806 | u8 tpr_priority;
|
| 807 | u8 reserved1;
|
| 808 | u64 guest_virtual_address;
|
| 809 | u64 guest_physical_address;
|
| 810 | u8 instruction_bytes[16];
|
| 811 | } __packed;
|
| 812 |
|
| 813 | #if IS_ENABLED(CONFIG_ARM64)
|
| 814 | union hv_arm64_vp_execution_state {
|
| 815 | u16 as_uint16;
|
| 816 | struct {
|
| 817 | u16 cpl:2;
|
| 818 | u16 debug_active:1;
|
| 819 | u16 interruption_pending:1;
|
| 820 | u16 vtl:4;
|
| 821 | u16 virtualization_fault_active:1;
|
| 822 | u16 reserved:7;
|
| 823 | } __packed;
|
| 824 | };
|
| 825 |
|
| 826 | struct hv_arm64_intercept_message_header {
|
| 827 | u32 vp_index;
|
| 828 | u8 instruction_length;
|
| 829 | u8 intercept_access_type;
|
| 830 | union hv_arm64_vp_execution_state execution_state;
|
| 831 | u64 pc;
|
| 832 | u64 cpsr;
|
| 833 | } __packed;
|
| 834 |
|
| 835 | union hv_arm64_memory_access_info {
|
| 836 | u8 as_uint8;
|
| 837 | struct {
|
| 838 | u8 gva_valid:1;
|
| 839 | u8 gva_gpa_valid:1;
|
| 840 | u8 hypercall_output_pending:1;
|
| 841 | u8 reserved:5;
|
| 842 | } __packed;
|
| 843 | };
|
| 844 |
|
| 845 | struct hv_arm64_memory_intercept_message {
|
| 846 | struct hv_arm64_intercept_message_header header;
|
| 847 | u32 cache_type;
|
| 848 | u8 instruction_byte_count;
|
| 849 | union hv_arm64_memory_access_info memory_access_info;
|
| 850 | u16 reserved1;
|
| 851 | u8 instruction_bytes[4];
|
| 852 | u32 reserved2;
|
| 853 | u64 guest_virtual_address;
|
| 854 | u64 guest_physical_address;
|
| 855 | u64 syndrome;
|
| 856 | } __packed;
|
| 857 |
|
| 858 | #endif
|
| 859 |
|
| 860 | |
| 861 | * Dispatch state for the VP communicated by the hypervisor to the
|
| 862 | * VP-dispatching thread in the root on return from HVCALL_DISPATCH_VP.
|
| 863 |
|
| 864 | enum hv_vp_dispatch_state {
|
| 865 | HV_VP_DISPATCH_STATE_INVALID = 0,
|
| 866 | HV_VP_DISPATCH_STATE_BLOCKED = 1,
|
| 867 | HV_VP_DISPATCH_STATE_READY = 2,
|
| 868 | };
|
| 869 |
|
| 870 | |
| 871 | * Dispatch event that caused the current dispatch state on return from
|
| 872 | * HVCALL_DISPATCH_VP.
|
| 873 |
|
| 874 | enum hv_vp_dispatch_event {
|
| 875 | HV_VP_DISPATCH_EVENT_INVALID = 0x00000000,
|
| 876 | HV_VP_DISPATCH_EVENT_SUSPEND = 0x00000001,
|
| 877 | HV_VP_DISPATCH_EVENT_INTERCEPT = 0x00000002,
|
| 878 | };
|
| 879 |
|
| 880 | #define HV_ROOT_SCHEDULER_MAX_VPS_PER_CHILD_PARTITION 1024
|
| 881 |
|
| 882 | #define HV_GENERIC_SET_QWORD_COUNT(max) (((((max) - 1) >> 6) + 1) + 2)
|
| 883 |
|
| 884 | struct hv_vp_signal_bitset_scheduler_message {
|
| 885 | u64 partition_id;
|
| 886 | u32 overflow_count;
|
| 887 | u16 vp_count;
|
| 888 | u16 reserved;
|
| 889 |
|
| 890 | #define BITSET_BUFFER_SIZE \
|
| 891 | HV_GENERIC_SET_QWORD_COUNT(HV_ROOT_SCHEDULER_MAX_VPS_PER_CHILD_PARTITION)
|
| 892 | union {
|
| 893 | struct hv_vpset bitset;
|
| 894 | u64 bitset_buffer[BITSET_BUFFER_SIZE];
|
| 895 | } vp_bitset;
|
| 896 | #undef BITSET_BUFFER_SIZE
|
| 897 | } __packed;
|
| 898 |
|
| 899 | static_assert(sizeof(struct hv_vp_signal_bitset_scheduler_message) <=
|
| 900 | (sizeof(struct hv_message) - sizeof(struct hv_message_header)));
|
| 901 |
|
| 902 | #define HV_MESSAGE_MAX_PARTITION_VP_PAIR_COUNT \
|
| 903 | (((sizeof(struct hv_message) - sizeof(struct hv_message_header)) / \
|
| 904 | (sizeof(u64 ) + sizeof(u32 ))) - 1)
|
| 905 |
|
| 906 | struct hv_vp_signal_pair_scheduler_message {
|
| 907 | u32 overflow_count;
|
| 908 | u8 vp_count;
|
| 909 | u8 reserved1[3];
|
| 910 |
|
| 911 | u64 partition_ids[HV_MESSAGE_MAX_PARTITION_VP_PAIR_COUNT];
|
| 912 | u32 vp_indexes[HV_MESSAGE_MAX_PARTITION_VP_PAIR_COUNT];
|
| 913 |
|
| 914 | u8 reserved2[4];
|
| 915 | } __packed;
|
| 916 |
|
| 917 | static_assert(sizeof(struct hv_vp_signal_pair_scheduler_message) ==
|
| 918 | (sizeof(struct hv_message) - sizeof(struct hv_message_header)));
|
| 919 |
|
| 920 |
|
| 921 | #define HV_DISPATCH_VP_FLAG_CLEAR_INTERCEPT_SUSPEND 0x1
|
| 922 | #define HV_DISPATCH_VP_FLAG_ENABLE_CALLER_INTERRUPTS 0x2
|
| 923 | #define HV_DISPATCH_VP_FLAG_SET_CALLER_SPEC_CTRL 0x4
|
| 924 | #define HV_DISPATCH_VP_FLAG_SKIP_VP_SPEC_FLUSH 0x8
|
| 925 | #define HV_DISPATCH_VP_FLAG_SKIP_CALLER_SPEC_FLUSH 0x10
|
| 926 | #define HV_DISPATCH_VP_FLAG_SKIP_CALLER_USER_SPEC_FLUSH 0x20
|
| 927 | #define HV_DISPATCH_VP_FLAG_SCAN_INTERRUPT_INJECTION 0x40
|
| 928 |
|
| 929 | struct hv_input_dispatch_vp {
|
| 930 | u64 partition_id;
|
| 931 | u32 vp_index;
|
| 932 | u32 flags;
|
| 933 | u64 time_slice;
|
| 934 | u64 spec_ctrl;
|
| 935 | } __packed;
|
| 936 |
|
| 937 | struct hv_output_dispatch_vp {
|
| 938 | u32 dispatch_state;
|
| 939 | u32 dispatch_event;
|
| 940 | } __packed;
|
| 941 |
|
| 942 | struct hv_input_modify_sparse_spa_page_host_access {
|
| 943 | u32 host_access : 2;
|
| 944 | u32 reserved : 30;
|
| 945 | u32 flags;
|
| 946 | u64 partition_id;
|
| 947 | u64 spa_page_list[];
|
| 948 | } __packed;
|
| 949 |
|
| 950 |
|
| 951 | #define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE 0x1
|
| 952 | #define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_SHARED 0x2
|
| 953 | #define HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE 0x4
|
| 954 | #define HV_MODIFY_SPA_PAGE_HOST_ACCESS_HUGE_PAGE 0x8
|
| 955 |
|
| 956 | #endif
|