diff options
Diffstat (limited to 'include/hyperv')
| -rw-r--r-- | include/hyperv/hvgdk.h | 2 | ||||
| -rw-r--r-- | include/hyperv/hvgdk_mini.h | 277 | ||||
| -rw-r--r-- | include/hyperv/hvhdk.h | 234 | ||||
| -rw-r--r-- | include/hyperv/hvhdk_mini.h | 239 |
4 files changed, 704 insertions, 48 deletions
diff --git a/include/hyperv/hvgdk.h b/include/hyperv/hvgdk.h index dd6d4939ea29..384c3f3ff4a5 100644 --- a/include/hyperv/hvgdk.h +++ b/include/hyperv/hvgdk.h @@ -281,7 +281,7 @@ struct hv_vmcb_enlightenments { #define HV_VMCB_NESTED_ENLIGHTENMENTS 31 /* Synthetic VM-Exit */ -#define HV_SVM_EXITCODE_ENL 0xf0000000 +#define HV_SVM_EXITCODE_ENL 0xf0000000ull #define HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH (1) /* VM_PARTITION_ASSIST_PAGE */ diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h index 155615175965..6a4e8b9d570f 100644 --- a/include/hyperv/hvgdk_mini.h +++ b/include/hyperv/hvgdk_mini.h @@ -13,34 +13,37 @@ struct hv_u128 { u64 high_part; } __packed; -/* NOTE: when adding below, update hv_status_to_string() */ -#define HV_STATUS_SUCCESS 0x0 -#define HV_STATUS_INVALID_HYPERCALL_CODE 0x2 -#define HV_STATUS_INVALID_HYPERCALL_INPUT 0x3 -#define HV_STATUS_INVALID_ALIGNMENT 0x4 -#define HV_STATUS_INVALID_PARAMETER 0x5 -#define HV_STATUS_ACCESS_DENIED 0x6 -#define HV_STATUS_INVALID_PARTITION_STATE 0x7 -#define HV_STATUS_OPERATION_DENIED 0x8 -#define HV_STATUS_UNKNOWN_PROPERTY 0x9 -#define HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE 0xA -#define HV_STATUS_INSUFFICIENT_MEMORY 0xB -#define HV_STATUS_INVALID_PARTITION_ID 0xD -#define HV_STATUS_INVALID_VP_INDEX 0xE -#define HV_STATUS_NOT_FOUND 0x10 -#define HV_STATUS_INVALID_PORT_ID 0x11 -#define HV_STATUS_INVALID_CONNECTION_ID 0x12 -#define HV_STATUS_INSUFFICIENT_BUFFERS 0x13 -#define HV_STATUS_NOT_ACKNOWLEDGED 0x14 -#define HV_STATUS_INVALID_VP_STATE 0x15 -#define HV_STATUS_NO_RESOURCES 0x1D -#define HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED 0x20 -#define HV_STATUS_INVALID_LP_INDEX 0x41 -#define HV_STATUS_INVALID_REGISTER_VALUE 0x50 -#define HV_STATUS_OPERATION_FAILED 0x71 -#define HV_STATUS_TIME_OUT 0x78 -#define HV_STATUS_CALL_PENDING 0x79 -#define HV_STATUS_VTL_ALREADY_ENABLED 0x86 +/* NOTE: when adding below, update hv_result_to_string() */ +#define HV_STATUS_SUCCESS 0x0 +#define HV_STATUS_INVALID_HYPERCALL_CODE 0x2 +#define HV_STATUS_INVALID_HYPERCALL_INPUT 0x3 +#define HV_STATUS_INVALID_ALIGNMENT 0x4 +#define HV_STATUS_INVALID_PARAMETER 0x5 +#define HV_STATUS_ACCESS_DENIED 0x6 +#define HV_STATUS_INVALID_PARTITION_STATE 0x7 +#define HV_STATUS_OPERATION_DENIED 0x8 +#define HV_STATUS_UNKNOWN_PROPERTY 0x9 +#define HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE 0xA +#define HV_STATUS_INSUFFICIENT_MEMORY 0xB +#define HV_STATUS_INVALID_PARTITION_ID 0xD +#define HV_STATUS_INVALID_VP_INDEX 0xE +#define HV_STATUS_NOT_FOUND 0x10 +#define HV_STATUS_INVALID_PORT_ID 0x11 +#define HV_STATUS_INVALID_CONNECTION_ID 0x12 +#define HV_STATUS_INSUFFICIENT_BUFFERS 0x13 +#define HV_STATUS_NOT_ACKNOWLEDGED 0x14 +#define HV_STATUS_INVALID_VP_STATE 0x15 +#define HV_STATUS_NO_RESOURCES 0x1D +#define HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED 0x20 +#define HV_STATUS_INVALID_LP_INDEX 0x41 +#define HV_STATUS_INVALID_REGISTER_VALUE 0x50 +#define HV_STATUS_OPERATION_FAILED 0x71 +#define HV_STATUS_INSUFFICIENT_ROOT_MEMORY 0x73 +#define HV_STATUS_INSUFFICIENT_CONTIGUOUS_MEMORY 0x75 +#define HV_STATUS_TIME_OUT 0x78 +#define HV_STATUS_CALL_PENDING 0x79 +#define HV_STATUS_INSUFFICIENT_CONTIGUOUS_ROOT_MEMORY 0x83 +#define HV_STATUS_VTL_ALREADY_ENABLED 0x86 /* * The Hyper-V TimeRefCount register and the TSC @@ -51,6 +54,7 @@ struct hv_u128 { #define HV_HYP_PAGE_SHIFT 12 #define HV_HYP_PAGE_SIZE BIT(HV_HYP_PAGE_SHIFT) #define HV_HYP_PAGE_MASK (~(HV_HYP_PAGE_SIZE - 1)) +#define HV_HYP_LARGE_PAGE_SHIFT 21 #define HV_PARTITION_ID_INVALID ((u64)0) #define HV_PARTITION_ID_SELF ((u64)-1) @@ -182,7 +186,7 @@ struct hv_tsc_emulation_control { /* HV_TSC_INVARIANT_CONTROL */ #endif /* CONFIG_X86 */ -struct hv_get_partition_id { /* HV_OUTPUT_GET_PARTITION_ID */ +struct hv_output_get_partition_id { u64 partition_id; } __packed; @@ -204,7 +208,14 @@ union hv_reference_tsc_msr { /* The number of vCPUs in one sparse bank */ #define HV_VCPUS_PER_SPARSE_BANK (64) -/* Some of Hyper-V structs do not use hv_vpset where linux uses them */ +/* + * Some of Hyper-V structs do not use hv_vpset where linux uses them. + * + * struct hv_vpset is usually used as part of hypercall input. The portion + * that counts as "fixed size input header" vs. "variable size input header" + * varies per hypercall. See comments at relevant hypercall call sites as to + * how the "valid_bank_mask" field should be accounted. + */ struct hv_vpset { /* HV_VP_SET */ u64 format; u64 valid_bank_mask; @@ -252,6 +263,7 @@ union hv_hypervisor_version_info { #define HYPERV_CPUID_VIRT_STACK_PROPERTIES 0x40000082 /* Support for the extended IOAPIC RTE format */ #define HYPERV_VS_PROPERTIES_EAX_EXTENDED_IOAPIC_RTE BIT(2) +#define HYPERV_VS_PROPERTIES_EAX_CONFIDENTIAL_VMBUS_AVAILABLE BIT(3) #define HYPERV_HYPERVISOR_PRESENT_BIT 0x80000000 #define HYPERV_CPUID_MIN 0x40000005 @@ -374,6 +386,10 @@ union hv_hypervisor_version_info { #define HV_SHARED_GPA_BOUNDARY_ACTIVE BIT(5) #define HV_SHARED_GPA_BOUNDARY_BITS GENMASK(11, 6) +/* HYPERV_CPUID_FEATURES.ECX bits. */ +#define HV_VP_DISPATCH_INTERRUPT_INJECTION_AVAILABLE BIT(9) +#define HV_VP_GHCB_ROOT_MAPPING_AVAILABLE BIT(10) + enum hv_isolation_type { HV_ISOLATION_TYPE_NONE = 0, /* HV_PARTITION_ISOLATION_TYPE_NONE */ HV_ISOLATION_TYPE_VBS = 1, @@ -419,6 +435,7 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */ /* HV_CALL_CODE */ #define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE 0x0002 #define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST 0x0003 +#define HVCALL_GET_LOGICAL_PROCESSOR_RUN_TIME 0x0004 #define HVCALL_NOTIFY_LONG_SPIN_WAIT 0x0008 #define HVCALL_SEND_IPI 0x000b #define HVCALL_ENABLE_VP_VTL 0x000f @@ -436,10 +453,13 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */ #define HVCALL_WITHDRAW_MEMORY 0x0049 #define HVCALL_MAP_GPA_PAGES 0x004b #define HVCALL_UNMAP_GPA_PAGES 0x004c +#define HVCALL_INSTALL_INTERCEPT 0x004d #define HVCALL_CREATE_VP 0x004e #define HVCALL_DELETE_VP 0x004f #define HVCALL_GET_VP_REGISTERS 0x0050 #define HVCALL_SET_VP_REGISTERS 0x0051 +#define HVCALL_TRANSLATE_VIRTUAL_ADDRESS 0x0052 +#define HVCALL_CLEAR_VIRTUAL_INTERRUPT 0x0056 #define HVCALL_DELETE_PORT 0x0058 #define HVCALL_DISCONNECT_PORT 0x005b #define HVCALL_POST_MESSAGE 0x005c @@ -447,27 +467,42 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */ #define HVCALL_POST_DEBUG_DATA 0x0069 #define HVCALL_RETRIEVE_DEBUG_DATA 0x006a #define HVCALL_RESET_DEBUG_SESSION 0x006b +#define HVCALL_MAP_STATS_PAGE 0x006c +#define HVCALL_UNMAP_STATS_PAGE 0x006d +#define HVCALL_SET_SYSTEM_PROPERTY 0x006f #define HVCALL_ADD_LOGICAL_PROCESSOR 0x0076 #define HVCALL_GET_SYSTEM_PROPERTY 0x007b #define HVCALL_MAP_DEVICE_INTERRUPT 0x007c #define HVCALL_UNMAP_DEVICE_INTERRUPT 0x007d #define HVCALL_RETARGET_INTERRUPT 0x007e +#define HVCALL_NOTIFY_PARTITION_EVENT 0x0087 +#define HVCALL_ENTER_SLEEP_STATE 0x0084 #define HVCALL_NOTIFY_PORT_RING_EMPTY 0x008b +#define HVCALL_REGISTER_INTERCEPT_RESULT 0x0091 #define HVCALL_ASSERT_VIRTUAL_INTERRUPT 0x0094 #define HVCALL_CREATE_PORT 0x0095 #define HVCALL_CONNECT_PORT 0x0096 #define HVCALL_START_VP 0x0099 -#define HVCALL_GET_VP_ID_FROM_APIC_ID 0x009a +#define HVCALL_GET_VP_INDEX_FROM_APIC_ID 0x009a #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0 +#define HVCALL_SIGNAL_EVENT_DIRECT 0x00c0 +#define HVCALL_POST_MESSAGE_DIRECT 0x00c1 #define HVCALL_DISPATCH_VP 0x00c2 +#define HVCALL_GET_GPA_PAGES_ACCESS_STATES 0x00c9 +#define HVCALL_ACQUIRE_SPARSE_SPA_PAGE_HOST_ACCESS 0x00d7 +#define HVCALL_RELEASE_SPARSE_SPA_PAGE_HOST_ACCESS 0x00d8 #define HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY 0x00db #define HVCALL_MAP_VP_STATE_PAGE 0x00e1 #define HVCALL_UNMAP_VP_STATE_PAGE 0x00e2 #define HVCALL_GET_VP_STATE 0x00e3 #define HVCALL_SET_VP_STATE 0x00e4 +#define HVCALL_GET_VP_CPUID_VALUES 0x00f4 +#define HVCALL_GET_PARTITION_PROPERTY_EX 0x0101 #define HVCALL_MMIO_READ 0x0106 #define HVCALL_MMIO_WRITE 0x0107 +#define HVCALL_DISABLE_HYP_EX 0x010f +#define HVCALL_MAP_STATS_PAGE2 0x0131 /* HV_HYPERCALL_INPUT */ #define HV_HYPERCALL_RESULT_MASK GENMASK_ULL(15, 0) @@ -547,9 +582,12 @@ struct hv_tlb_flush { /* HV_INPUT_FLUSH_VIRTUAL_ADDRESS_LIST */ struct hv_tlb_flush_ex { u64 address_space; u64 flags; - struct hv_vpset hv_vp_set; - u64 gva_list[]; + __TRAILING_OVERLAP(struct hv_vpset, hv_vp_set, bank_contents, __packed, + u64 gva_list[]; + ); } __packed; +static_assert(offsetof(struct hv_tlb_flush_ex, hv_vp_set.bank_contents) == + offsetof(struct hv_tlb_flush_ex, gva_list)); struct ms_hyperv_tsc_page { /* HV_REFERENCE_TSC_PAGE */ volatile u32 tsc_sequence; @@ -573,8 +611,6 @@ struct ms_hyperv_tsc_page { /* HV_REFERENCE_TSC_PAGE */ #define HV_SYNIC_SINT_AUTO_EOI (1ULL << 17) #define HV_SYNIC_SINT_VECTOR_MASK (0xFF) -# - /* Hyper-V defined statically assigned SINTs */ #define HV_SYNIC_INTERCEPTION_SINT_INDEX 0x00000000 #define HV_SYNIC_IOMMU_FAULT_SINT_INDEX 0x00000001 @@ -775,10 +811,10 @@ struct hv_message_page { /* Define timer message payload structure. */ struct hv_timer_message_payload { - __u32 timer_index; - __u32 reserved; - __u64 expiration_time; /* When the timer expired */ - __u64 delivery_time; /* When the message was delivered */ + u32 timer_index; + u32 reserved; + u64 expiration_time; /* When the timer expired */ + u64 delivery_time; /* When the message was delivered */ } __packed; struct hv_x64_segment_register { @@ -807,6 +843,8 @@ struct hv_x64_table_register { u64 base; } __packed; +#define HV_NORMAL_VTL 0 + union hv_input_vtl { u8 as_uint8; struct { @@ -856,6 +894,48 @@ struct hv_get_vp_from_apic_id_in { u32 apic_ids[]; } __packed; +union hv_register_vsm_partition_config { + u64 as_uint64; + struct { + u64 enable_vtl_protection : 1; + u64 default_vtl_protection_mask : 4; + u64 zero_memory_on_reset : 1; + u64 deny_lower_vtl_startup : 1; + u64 intercept_acceptance : 1; + u64 intercept_enable_vtl_protection : 1; + u64 intercept_vp_startup : 1; + u64 intercept_cpuid_unimplemented : 1; + u64 intercept_unrecoverable_exception : 1; + u64 intercept_page : 1; + u64 mbz : 51; + } __packed; +}; + +union hv_register_vsm_capabilities { + u64 as_uint64; + struct { + u64 dr6_shared: 1; + u64 mbec_vtl_mask: 16; + u64 deny_lower_vtl_startup: 1; + u64 supervisor_shadow_stack: 1; + u64 hardware_hvpt_available: 1; + u64 software_hvpt_available: 1; + u64 hardware_hvpt_range_bits: 6; + u64 intercept_page_available: 1; + u64 return_action_available: 1; + u64 reserved: 35; + } __packed; +}; + +union hv_register_vsm_page_offsets { + struct { + u64 vtl_call_offset : 12; + u64 vtl_return_offset : 12; + u64 reserved_mbz : 40; + } __packed; + u64 as_uint64; +}; + struct hv_nested_enlightenments_control { struct { u32 directhypercall : 1; @@ -978,6 +1058,72 @@ enum hv_register_name { /* VSM */ HV_REGISTER_VSM_VP_STATUS = 0x000D0003, + + /* Synthetic VSM registers */ + HV_REGISTER_VSM_CODE_PAGE_OFFSETS = 0x000D0002, + HV_REGISTER_VSM_CAPABILITIES = 0x000D0006, + HV_REGISTER_VSM_PARTITION_CONFIG = 0x000D0007, + +#if defined(CONFIG_X86) + /* X64 Debug Registers */ + HV_X64_REGISTER_DR0 = 0x00050000, + HV_X64_REGISTER_DR1 = 0x00050001, + HV_X64_REGISTER_DR2 = 0x00050002, + HV_X64_REGISTER_DR3 = 0x00050003, + HV_X64_REGISTER_DR6 = 0x00050004, + HV_X64_REGISTER_DR7 = 0x00050005, + + /* X64 Cache control MSRs */ + HV_X64_REGISTER_MSR_MTRR_CAP = 0x0008000D, + HV_X64_REGISTER_MSR_MTRR_DEF_TYPE = 0x0008000E, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE0 = 0x00080010, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE1 = 0x00080011, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE2 = 0x00080012, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE3 = 0x00080013, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE4 = 0x00080014, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE5 = 0x00080015, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE6 = 0x00080016, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE7 = 0x00080017, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE8 = 0x00080018, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASE9 = 0x00080019, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEA = 0x0008001A, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEB = 0x0008001B, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEC = 0x0008001C, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASED = 0x0008001D, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEE = 0x0008001E, + HV_X64_REGISTER_MSR_MTRR_PHYS_BASEF = 0x0008001F, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK0 = 0x00080040, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK1 = 0x00080041, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK2 = 0x00080042, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK3 = 0x00080043, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK4 = 0x00080044, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK5 = 0x00080045, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK6 = 0x00080046, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK7 = 0x00080047, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK8 = 0x00080048, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASK9 = 0x00080049, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKA = 0x0008004A, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKB = 0x0008004B, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKC = 0x0008004C, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKD = 0x0008004D, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKE = 0x0008004E, + HV_X64_REGISTER_MSR_MTRR_PHYS_MASKF = 0x0008004F, + HV_X64_REGISTER_MSR_MTRR_FIX64K00000 = 0x00080070, + HV_X64_REGISTER_MSR_MTRR_FIX16K80000 = 0x00080071, + HV_X64_REGISTER_MSR_MTRR_FIX16KA0000 = 0x00080072, + HV_X64_REGISTER_MSR_MTRR_FIX4KC0000 = 0x00080073, + HV_X64_REGISTER_MSR_MTRR_FIX4KC8000 = 0x00080074, + HV_X64_REGISTER_MSR_MTRR_FIX4KD0000 = 0x00080075, + HV_X64_REGISTER_MSR_MTRR_FIX4KD8000 = 0x00080076, + HV_X64_REGISTER_MSR_MTRR_FIX4KE0000 = 0x00080077, + HV_X64_REGISTER_MSR_MTRR_FIX4KE8000 = 0x00080078, + HV_X64_REGISTER_MSR_MTRR_FIX4KF0000 = 0x00080079, + HV_X64_REGISTER_MSR_MTRR_FIX4KF8000 = 0x0008007A, + + HV_X64_REGISTER_REG_PAGE = 0x0009001C, +#elif defined(CONFIG_ARM64) + HV_ARM64_REGISTER_SINT_RESERVED_INTERRUPT_ID = 0x00070001, +#endif }; /* @@ -987,7 +1133,7 @@ enum hv_register_name { /* * To support arch-generic code calling hv_set/get_register: - * - On x86, HV_MSR_ indicates an MSR accessed via rdmsrl/wrmsrl + * - On x86, HV_MSR_ indicates an MSR accessed via rdmsrq/wrmsrq * - On ARM, HV_MSR_ indicates a VP register accessed via hypercall */ #define HV_MSR_CRASH_P0 (HV_X64_MSR_CRASH_P0) @@ -1202,7 +1348,7 @@ struct hv_send_ipi { /* HV_INPUT_SEND_SYNTHETIC_CLUSTER_IPI */ u64 cpu_mask; } __packed; -#define HV_X64_VTL_MASK GENMASK(3, 0) +#define HV_VTL_MASK GENMASK(3, 0) /* Hyper-V memory host visibility */ enum hv_mem_host_visibility { @@ -1325,6 +1471,49 @@ struct hv_retarget_device_interrupt { /* HV_INPUT_RETARGET_DEVICE_INTERRUPT */ struct hv_device_interrupt_target int_target; } __packed __aligned(8); +enum hv_intercept_type { +#if defined(CONFIG_X86) + HV_INTERCEPT_TYPE_X64_IO_PORT = 0x00000000, + HV_INTERCEPT_TYPE_X64_MSR = 0x00000001, + HV_INTERCEPT_TYPE_X64_CPUID = 0x00000002, +#endif + HV_INTERCEPT_TYPE_EXCEPTION = 0x00000003, + /* Used to be HV_INTERCEPT_TYPE_REGISTER */ + HV_INTERCEPT_TYPE_RESERVED0 = 0x00000004, + HV_INTERCEPT_TYPE_MMIO = 0x00000005, +#if defined(CONFIG_X86) + HV_INTERCEPT_TYPE_X64_GLOBAL_CPUID = 0x00000006, + HV_INTERCEPT_TYPE_X64_APIC_SMI = 0x00000007, +#endif + HV_INTERCEPT_TYPE_HYPERCALL = 0x00000008, +#if defined(CONFIG_X86) + HV_INTERCEPT_TYPE_X64_APIC_INIT_SIPI = 0x00000009, + HV_INTERCEPT_MC_UPDATE_PATCH_LEVEL_MSR_READ = 0x0000000A, + HV_INTERCEPT_TYPE_X64_APIC_WRITE = 0x0000000B, + HV_INTERCEPT_TYPE_X64_MSR_INDEX = 0x0000000C, +#endif + HV_INTERCEPT_TYPE_MAX, + HV_INTERCEPT_TYPE_INVALID = 0xFFFFFFFF, +}; + +union hv_intercept_parameters { + /* HV_INTERCEPT_PARAMETERS is defined to be an 8-byte field. */ + u64 as_uint64; +#if defined(CONFIG_X86) + /* HV_INTERCEPT_TYPE_X64_IO_PORT */ + u16 io_port; + /* HV_INTERCEPT_TYPE_X64_CPUID */ + u32 cpuid_index; + /* HV_INTERCEPT_TYPE_X64_APIC_WRITE */ + u32 apic_write_mask; + /* HV_INTERCEPT_TYPE_EXCEPTION */ + u16 exception_vector; + /* HV_INTERCEPT_TYPE_X64_MSR_INDEX */ + u32 msr_index; +#endif + /* N.B. Other intercept types do not have any parameters. */ +}; + /* Data structures for HVCALL_MMIO_READ and HVCALL_MMIO_WRITE */ #define HV_HYPERCALL_MMIO_MAX_DATA_LENGTH 64 @@ -1345,4 +1534,10 @@ struct hv_mmio_write_input { u8 data[HV_HYPERCALL_MMIO_MAX_DATA_LENGTH]; } __packed; +enum hv_intercept_access_type { + HV_INTERCEPT_ACCESS_READ = 0, + HV_INTERCEPT_ACCESS_WRITE = 1, + HV_INTERCEPT_ACCESS_EXECUTE = 2 +}; + #endif /* _HV_HVGDK_MINI_H */ diff --git a/include/hyperv/hvhdk.h b/include/hyperv/hvhdk.h index 64407c2a3809..5e83d3714966 100644 --- a/include/hyperv/hvhdk.h +++ b/include/hyperv/hvhdk.h @@ -10,6 +10,13 @@ #include "hvhdk_mini.h" #include "hvgdk.h" +/* + * Hypervisor statistics page format + */ +struct hv_stats_page { + u64 data[HV_HYP_PAGE_SIZE / sizeof(u64)]; +} __packed; + /* Bits for dirty mask of hv_vp_register_page */ #define HV_X64_REGISTER_CLASS_GENERAL 0 #define HV_X64_REGISTER_CLASS_IP 1 @@ -19,11 +26,24 @@ #define HV_VP_REGISTER_PAGE_VERSION_1 1u +#define HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT 7 + +union hv_vp_register_page_interrupt_vectors { + u64 as_uint64; + struct { + u8 vector_count; + u8 vector[HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT]; + } __packed; +}; + struct hv_vp_register_page { u16 version; u8 isvalid; u8 rsvdz; u32 dirty; + +#if IS_ENABLED(CONFIG_X86) + union { struct { /* General purpose registers @@ -95,6 +115,22 @@ struct hv_vp_register_page { union hv_x64_pending_interruption_register pending_interruption; union hv_x64_interrupt_state_register interrupt_state; u64 instruction_emulation_hints; + u64 xfem; + + /* + * Fields from this point are not included in the register page save chunk. + * The reserved field is intended to maintain alignment for unsaved fields. + */ + u8 reserved1[0x100]; + + /* + * Interrupts injected as part of HvCallDispatchVp. + */ + union hv_vp_register_page_interrupt_vectors interrupt_vectors; + +#elif IS_ENABLED(CONFIG_ARM64) + /* Not yet supported in ARM */ +#endif } __packed; #define HV_PARTITION_PROCESSOR_FEATURES_BANKS 2 @@ -299,10 +335,13 @@ union hv_partition_isolation_properties { #define HV_PARTITION_ISOLATION_HOST_TYPE_RESERVED 0x2 /* Note: Exo partition is enabled by default */ -#define HV_PARTITION_CREATION_FLAG_EXO_PARTITION BIT(8) -#define HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED BIT(13) -#define HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED BIT(19) -#define HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE BIT(22) +#define HV_PARTITION_CREATION_FLAG_SMT_ENABLED_GUEST BIT(0) +#define HV_PARTITION_CREATION_FLAG_NESTED_VIRTUALIZATION_CAPABLE BIT(1) +#define HV_PARTITION_CREATION_FLAG_GPA_SUPER_PAGES_ENABLED BIT(4) +#define HV_PARTITION_CREATION_FLAG_EXO_PARTITION BIT(8) +#define HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED BIT(13) +#define HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED BIT(19) +#define HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE BIT(22) struct hv_input_create_partition { u64 flags; @@ -346,16 +385,66 @@ struct hv_input_set_partition_property { u64 property_value; } __packed; +union hv_partition_property_arg { + u64 as_uint64; + struct { + union { + u32 arg; + u32 vp_index; + }; + u16 reserved0; + u8 reserved1; + u8 object_type; + } __packed; +}; + +struct hv_input_get_partition_property_ex { + u64 partition_id; + u32 property_code; /* enum hv_partition_property_code */ + u32 padding; + union { + union hv_partition_property_arg arg_data; + u64 arg; + }; +} __packed; + +/* + * NOTE: Should use hv_input_set_partition_property_ex_header to compute this + * size, but hv_input_get_partition_property_ex is identical so it suffices + */ +#define HV_PARTITION_PROPERTY_EX_MAX_VAR_SIZE \ + (HV_HYP_PAGE_SIZE - sizeof(struct hv_input_get_partition_property_ex)) + +union hv_partition_property_ex { + u8 buffer[HV_PARTITION_PROPERTY_EX_MAX_VAR_SIZE]; + struct hv_partition_property_vmm_capabilities vmm_capabilities; + /* More fields to be filled in when needed */ +}; + +struct hv_output_get_partition_property_ex { + union hv_partition_property_ex property_value; +} __packed; + enum hv_vp_state_page_type { HV_VP_STATE_PAGE_REGISTERS = 0, HV_VP_STATE_PAGE_INTERCEPT_MESSAGE = 1, + HV_VP_STATE_PAGE_GHCB = 2, HV_VP_STATE_PAGE_COUNT }; struct hv_input_map_vp_state_page { u64 partition_id; u32 vp_index; - u32 type; /* enum hv_vp_state_page_type */ + u16 type; /* enum hv_vp_state_page_type */ + union hv_input_vtl input_vtl; + union { + u8 as_uint8; + struct { + u8 map_location_provided : 1; + u8 reserved : 7; + }; + } flags; + u64 requested_map_location; } __packed; struct hv_output_map_vp_state_page { @@ -365,7 +454,14 @@ struct hv_output_map_vp_state_page { struct hv_input_unmap_vp_state_page { u64 partition_id; u32 vp_index; - u32 type; /* enum hv_vp_state_page_type */ + u16 type; /* enum hv_vp_state_page_type */ + union hv_input_vtl input_vtl; + u8 reserved0; +} __packed; + +struct hv_x64_apic_eoi_message { + u32 vp_index; + u32 interrupt_vector; } __packed; struct hv_opaque_intercept_message { @@ -492,9 +588,15 @@ union hv_interrupt_control { u64 as_uint64; struct { u32 interrupt_type; /* enum hv_interrupt_type */ +#if IS_ENABLED(CONFIG_X86) u32 level_triggered : 1; u32 logical_dest_mode : 1; u32 rsvd : 30; +#elif IS_ENABLED(CONFIG_ARM64) + u32 rsvd1 : 2; + u32 asserted : 1; + u32 rsvd2 : 29; +#endif } __packed; }; @@ -515,6 +617,13 @@ struct hv_synthetic_timers_state { u64 reserved[5]; } __packed; +struct hv_async_completion_message_payload { + u64 partition_id; + u32 status; + u32 completion_count; + u64 sub_status; +} __packed; + union hv_input_delete_vp { u64 as_uint64[2]; struct { @@ -649,6 +758,104 @@ struct hv_input_set_vp_state { union hv_input_set_vp_state_data data[]; } __packed; +union hv_x64_vp_execution_state { + u16 as_uint16; + struct { + u16 cpl:2; + u16 cr0_pe:1; + u16 cr0_am:1; + u16 efer_lma:1; + u16 debug_active:1; + u16 interruption_pending:1; + u16 vtl:4; + u16 enclave_mode:1; + u16 interrupt_shadow:1; + u16 virtualization_fault_active:1; + u16 reserved:2; + } __packed; +}; + +struct hv_x64_intercept_message_header { + u32 vp_index; + u8 instruction_length:4; + u8 cr8:4; /* Only set for exo partitions */ + u8 intercept_access_type; /* enum hv_intercept_access_type */ + union hv_x64_vp_execution_state execution_state; + struct hv_x64_segment_register cs_segment; + u64 rip; + u64 rflags; +} __packed; + +union hv_x64_memory_access_info { + u8 as_uint8; + struct { + u8 gva_valid:1; + u8 gva_gpa_valid:1; + u8 hypercall_output_pending:1; + u8 tlb_locked_no_overlay:1; + u8 reserved:4; + } __packed; +}; + +struct hv_x64_memory_intercept_message { + struct hv_x64_intercept_message_header header; + u32 cache_type; /* enum hv_cache_type */ + u8 instruction_byte_count; + union hv_x64_memory_access_info memory_access_info; + u8 tpr_priority; + u8 reserved1; + u64 guest_virtual_address; + u64 guest_physical_address; + u8 instruction_bytes[16]; +} __packed; + +#if IS_ENABLED(CONFIG_ARM64) +union hv_arm64_vp_execution_state { + u16 as_uint16; + struct { + u16 cpl:2; /* Exception Level (EL) */ + u16 debug_active:1; + u16 interruption_pending:1; + u16 vtl:4; + u16 virtualization_fault_active:1; + u16 reserved:7; + } __packed; +}; + +struct hv_arm64_intercept_message_header { + u32 vp_index; + u8 instruction_length; + u8 intercept_access_type; /* enum hv_intercept_access_type */ + union hv_arm64_vp_execution_state execution_state; + u64 pc; + u64 cpsr; +} __packed; + +union hv_arm64_memory_access_info { + u8 as_uint8; + struct { + u8 gva_valid:1; + u8 gva_gpa_valid:1; + u8 hypercall_output_pending:1; + u8 reserved:5; + } __packed; +}; + +struct hv_arm64_memory_intercept_message { + struct hv_arm64_intercept_message_header header; + u32 cache_type; /* enum hv_cache_type */ + u8 instruction_byte_count; + union hv_arm64_memory_access_info memory_access_info; + u16 reserved1; + u8 instruction_bytes[4]; + u32 reserved2; + u64 guest_virtual_address; + u64 guest_physical_address; + u64 syndrome; +} __packed; + +#endif /* CONFIG_ARM64 */ + /* * Dispatch state for the VP communicated by the hypervisor to the * VP-dispatching thread in the root on return from HVCALL_DISPATCH_VP. @@ -716,6 +923,7 @@ static_assert(sizeof(struct hv_vp_signal_pair_scheduler_message) == #define HV_DISPATCH_VP_FLAG_SKIP_VP_SPEC_FLUSH 0x8 #define HV_DISPATCH_VP_FLAG_SKIP_CALLER_SPEC_FLUSH 0x10 #define HV_DISPATCH_VP_FLAG_SKIP_CALLER_USER_SPEC_FLUSH 0x20 +#define HV_DISPATCH_VP_FLAG_SCAN_INTERRUPT_INJECTION 0x40 struct hv_input_dispatch_vp { u64 partition_id; @@ -730,4 +938,18 @@ struct hv_output_dispatch_vp { u32 dispatch_event; /* enum hv_vp_dispatch_event */ } __packed; +struct hv_input_modify_sparse_spa_page_host_access { + u32 host_access : 2; + u32 reserved : 30; + u32 flags; + u64 partition_id; + u64 spa_page_list[]; +} __packed; + +/* hv_input_modify_sparse_spa_page_host_access flags */ +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE 0x1 +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_SHARED 0x2 +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE 0x4 +#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_HUGE_PAGE 0x8 + #endif /* _HV_HVHDK_H */ diff --git a/include/hyperv/hvhdk_mini.h b/include/hyperv/hvhdk_mini.h index f8a39d3e9ce6..b4cb2fa26e9b 100644 --- a/include/hyperv/hvhdk_mini.h +++ b/include/hyperv/hvhdk_mini.h @@ -7,6 +7,8 @@ #include "hvgdk_mini.h" +#define HV_MAX_CONTIGUOUS_ALLOCATION_PAGES 8 + /* * Doorbell connection_info flags. */ @@ -36,30 +38,158 @@ enum hv_scheduler_type { HV_SCHEDULER_TYPE_MAX }; +/* HV_STATS_AREA_TYPE */ +enum hv_stats_area_type { + HV_STATS_AREA_SELF = 0, + HV_STATS_AREA_PARENT = 1, + HV_STATS_AREA_INTERNAL = 2, + HV_STATS_AREA_COUNT +}; + +enum hv_stats_object_type { + HV_STATS_OBJECT_HYPERVISOR = 0x00000001, + HV_STATS_OBJECT_LOGICAL_PROCESSOR = 0x00000002, + HV_STATS_OBJECT_PARTITION = 0x00010001, + HV_STATS_OBJECT_VP = 0x00010002 +}; + +union hv_stats_object_identity { + /* hv_stats_hypervisor */ + struct { + u8 reserved[15]; + u8 stats_area_type; + } __packed hv; + + /* hv_stats_logical_processor */ + struct { + u32 lp_index; + u8 reserved[11]; + u8 stats_area_type; + } __packed lp; + + /* hv_stats_partition */ + struct { + u64 partition_id; + u8 reserved[7]; + u8 stats_area_type; + } __packed partition; + + /* hv_stats_vp */ + struct { + u64 partition_id; + u32 vp_index; + u16 flags; + u8 reserved; + u8 stats_area_type; + } __packed vp; +}; + enum hv_partition_property_code { /* Privilege properties */ HV_PARTITION_PROPERTY_PRIVILEGE_FLAGS = 0x00010000, HV_PARTITION_PROPERTY_SYNTHETIC_PROC_FEATURES = 0x00010001, + /* Integrated scheduling properties */ + HV_PARTITION_PROPERTY_INTEGRATED_SCHEDULER_ENABLED = 0x00020005, + /* Resource properties */ HV_PARTITION_PROPERTY_GPA_PAGE_ACCESS_TRACKING = 0x00050005, HV_PARTITION_PROPERTY_UNIMPLEMENTED_MSR_ACTION = 0x00050017, /* Compatibility properties */ HV_PARTITION_PROPERTY_PROCESSOR_XSAVE_FEATURES = 0x00060002, + HV_PARTITION_PROPERTY_XSAVE_STATES = 0x00060007, HV_PARTITION_PROPERTY_MAX_XSAVE_DATA_SIZE = 0x00060008, HV_PARTITION_PROPERTY_PROCESSOR_CLOCK_FREQUENCY = 0x00060009, + + /* Extended properties with larger property values */ + HV_PARTITION_PROPERTY_VMM_CAPABILITIES = 0x00090007, +}; + +#define HV_PARTITION_VMM_CAPABILITIES_BANK_COUNT 1 +#define HV_PARTITION_VMM_CAPABILITIES_RESERVED_BITFIELD_COUNT 57 + +struct hv_partition_property_vmm_capabilities { + u16 bank_count; + u16 reserved[3]; + union { + u64 as_uint64[HV_PARTITION_VMM_CAPABILITIES_BANK_COUNT]; + struct { + u64 map_gpa_preserve_adjustable: 1; + u64 vmm_can_provide_overlay_gpfn: 1; + u64 vp_affinity_property: 1; +#if IS_ENABLED(CONFIG_ARM64) + u64 vmm_can_provide_gic_overlay_locations: 1; +#else + u64 reservedbit3: 1; +#endif + u64 assignable_synthetic_proc_features: 1; + u64 reservedbit5: 1; + u64 vmm_enable_integrated_scheduler : 1; + u64 reserved0: HV_PARTITION_VMM_CAPABILITIES_RESERVED_BITFIELD_COUNT; + } __packed; + }; +} __packed; + +enum hv_snp_status { + HV_SNP_STATUS_NONE = 0, + HV_SNP_STATUS_AVAILABLE = 1, + HV_SNP_STATUS_INCOMPATIBLE = 2, + HV_SNP_STATUS_PSP_UNAVAILABLE = 3, + HV_SNP_STATUS_PSP_INIT_FAILED = 4, + HV_SNP_STATUS_PSP_BAD_FW_VERSION = 5, + HV_SNP_STATUS_BAD_CONFIGURATION = 6, + HV_SNP_STATUS_PSP_FW_UPDATE_IN_PROGRESS = 7, + HV_SNP_STATUS_PSP_RB_INIT_FAILED = 8, + HV_SNP_STATUS_PSP_PLATFORM_STATUS_FAILED = 9, + HV_SNP_STATUS_PSP_INIT_LATE_FAILED = 10, }; enum hv_system_property { /* Add more values when needed */ + HV_SYSTEM_PROPERTY_SLEEP_STATE = 3, HV_SYSTEM_PROPERTY_SCHEDULER_TYPE = 15, + HV_DYNAMIC_PROCESSOR_FEATURE_PROPERTY = 21, + HV_SYSTEM_PROPERTY_CRASHDUMPAREA = 47, +}; + +#define HV_PFN_RANGE_PGBITS 24 /* HV_SPA_PAGE_RANGE_ADDITIONAL_PAGES_BITS */ +union hv_pfn_range { /* HV_SPA_PAGE_RANGE */ + u64 as_uint64; + struct { + /* 39:0: base pfn. 63:40: additional pages */ + u64 base_pfn : 64 - HV_PFN_RANGE_PGBITS; + u64 add_pfns : HV_PFN_RANGE_PGBITS; + } __packed; +}; + +enum hv_sleep_state { + HV_SLEEP_STATE_S1 = 1, + HV_SLEEP_STATE_S2 = 2, + HV_SLEEP_STATE_S3 = 3, + HV_SLEEP_STATE_S4 = 4, + HV_SLEEP_STATE_S5 = 5, + /* + * After hypervisor has received this, any follow up sleep + * state registration requests will be rejected. + */ + HV_SLEEP_STATE_LOCK = 6 +}; + +enum hv_dynamic_processor_feature_property { + /* Add more values when needed */ + HV_X64_DYNAMIC_PROCESSOR_FEATURE_MAX_ENCRYPTED_PARTITIONS = 13, + HV_X64_DYNAMIC_PROCESSOR_FEATURE_SNP_STATUS = 16, }; struct hv_input_get_system_property { u32 property_id; /* enum hv_system_property */ union { u32 as_uint32; +#if IS_ENABLED(CONFIG_X86) + /* enum hv_dynamic_processor_feature_property */ + u32 hv_processor_feature; +#endif /* More fields to be filled in when needed */ }; } __packed; @@ -67,9 +197,63 @@ struct hv_input_get_system_property { struct hv_output_get_system_property { union { u32 scheduler_type; /* enum hv_scheduler_type */ +#if IS_ENABLED(CONFIG_X86) + u64 hv_processor_feature_value; +#endif + union hv_pfn_range hv_cda_info; /* CrashdumpAreaAddress */ + u64 hv_tramp_pa; /* CrashdumpTrampolineAddress */ + }; +} __packed; + +struct hv_sleep_state_info { + u32 sleep_state; /* enum hv_sleep_state */ + u8 pm1a_slp_typ; + u8 pm1b_slp_typ; +} __packed; + +struct hv_input_set_system_property { + u32 property_id; /* enum hv_system_property */ + u32 reserved; + union { + /* More fields to be filled in when needed */ + struct hv_sleep_state_info set_sleep_state_info; + + /* + * Add a reserved field to ensure the union is 8-byte aligned as + * existing members may not be. This is a temporary measure + * until all remaining members are added. + */ + u64 reserved0[8]; }; } __packed; +struct hv_input_enter_sleep_state { /* HV_INPUT_ENTER_SLEEP_STATE */ + u32 sleep_state; /* enum hv_sleep_state */ +} __packed; + +struct hv_input_map_stats_page { + u32 type; /* enum hv_stats_object_type */ + u32 padding; + union hv_stats_object_identity identity; +} __packed; + +struct hv_input_map_stats_page2 { + u32 type; /* enum hv_stats_object_type */ + u32 padding; + union hv_stats_object_identity identity; + u64 map_location; +} __packed; + +struct hv_output_map_stats_page { + u64 map_location; +} __packed; + +struct hv_input_unmap_stats_page { + u32 type; /* enum hv_stats_object_type */ + u32 padding; + union hv_stats_object_identity identity; +} __packed; + struct hv_proximity_domain_flags { u32 proximity_preferred : 1; u32 reserved : 30; @@ -143,6 +327,60 @@ union hv_gpa_page_access_state { u8 as_uint8; } __packed; +enum hv_crashdump_action { + HV_CRASHDUMP_NONE = 0, + HV_CRASHDUMP_SUSPEND_ALL_VPS, + HV_CRASHDUMP_PREPARE_FOR_STATE_SAVE, + HV_CRASHDUMP_STATE_SAVED, + HV_CRASHDUMP_ENTRY, +}; + +struct hv_partition_event_root_crashdump_input { + u32 crashdump_action; /* enum hv_crashdump_action */ +} __packed; + +struct hv_input_disable_hyp_ex { /* HV_X64_INPUT_DISABLE_HYPERVISOR_EX */ + u64 rip; + u64 arg; +} __packed; + +struct hv_crashdump_area { /* HV_CRASHDUMP_AREA */ + u32 version; + union { + u32 flags_as_uint32; + struct { + u32 cda_valid : 1; + u32 cda_unused : 31; + } __packed; + }; + /* more unused fields */ +} __packed; + +union hv_partition_event_input { + struct hv_partition_event_root_crashdump_input crashdump_input; +}; + +enum hv_partition_event { + HV_PARTITION_EVENT_ROOT_CRASHDUMP = 2, + HV_PARTITION_ALL_LOGICAL_PROCESSORS_STARTED = 4, +}; + +struct hv_input_notify_partition_event { + u32 event; /* enum hv_partition_event */ + union hv_partition_event_input input; +} __packed; + +struct hv_input_get_logical_processor_run_time { + u32 lp_index; +} __packed; + +struct hv_output_get_logical_processor_run_time { + u64 global_time; + u64 local_run_time; + u64 rsvdz0; + u64 hypervisor_time; +} __packed; + struct hv_lp_startup_status { u64 hv_status; u64 substatus1; @@ -210,6 +448,7 @@ struct hv_input_map_device_interrupt { /* HV_OUTPUT_MAP_DEVICE_INTERRUPT */ struct hv_output_map_device_interrupt { struct hv_interrupt_entry interrupt_entry; + u64 ext_status_deprecated[5]; } __packed; /* HV_INPUT_UNMAP_DEVICE_INTERRUPT */ |
