xref: /kvm-unit-tests/x86/hyperv.h (revision 30353da70e2e7977b1b8477960585c29de835266)
1c865f654SCornelia Huck #ifndef X86_HYPERV_H
2c865f654SCornelia Huck #define X86_HYPERV_H
398fb3357SAndrey Smetanin 
498fb3357SAndrey Smetanin #include "libcflat.h"
598fb3357SAndrey Smetanin #include "processor.h"
698fb3357SAndrey Smetanin 
798fb3357SAndrey Smetanin #define HYPERV_CPUID_FEATURES                   0x40000003
898fb3357SAndrey Smetanin 
969d4bf75SAndrey Smetanin #define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE     (1 << 1)
1098fb3357SAndrey Smetanin #define HV_X64_MSR_SYNIC_AVAILABLE              (1 << 2)
1169d4bf75SAndrey Smetanin #define HV_X64_MSR_SYNTIMER_AVAILABLE           (1 << 3)
1269d4bf75SAndrey Smetanin 
13b9f6c977SRoman Kagan #define HV_X64_MSR_GUEST_OS_ID                  0x40000000
14b9f6c977SRoman Kagan #define HV_X64_MSR_HYPERCALL                    0x40000001
15b9f6c977SRoman Kagan 
1669d4bf75SAndrey Smetanin #define HV_X64_MSR_TIME_REF_COUNT               0x40000020
17907ce0f7SPaolo Bonzini #define HV_X64_MSR_REFERENCE_TSC                0x40000021
1898fb3357SAndrey Smetanin 
1998fb3357SAndrey Smetanin /* Define synthetic interrupt controller model specific registers. */
2098fb3357SAndrey Smetanin #define HV_X64_MSR_SCONTROL                     0x40000080
2198fb3357SAndrey Smetanin #define HV_X64_MSR_SVERSION                     0x40000081
2298fb3357SAndrey Smetanin #define HV_X64_MSR_SIEFP                        0x40000082
2398fb3357SAndrey Smetanin #define HV_X64_MSR_SIMP                         0x40000083
2498fb3357SAndrey Smetanin #define HV_X64_MSR_EOM                          0x40000084
2598fb3357SAndrey Smetanin #define HV_X64_MSR_SINT0                        0x40000090
2698fb3357SAndrey Smetanin #define HV_X64_MSR_SINT1                        0x40000091
2798fb3357SAndrey Smetanin #define HV_X64_MSR_SINT2                        0x40000092
2898fb3357SAndrey Smetanin #define HV_X64_MSR_SINT3                        0x40000093
2998fb3357SAndrey Smetanin #define HV_X64_MSR_SINT4                        0x40000094
3098fb3357SAndrey Smetanin #define HV_X64_MSR_SINT5                        0x40000095
3198fb3357SAndrey Smetanin #define HV_X64_MSR_SINT6                        0x40000096
3298fb3357SAndrey Smetanin #define HV_X64_MSR_SINT7                        0x40000097
3398fb3357SAndrey Smetanin #define HV_X64_MSR_SINT8                        0x40000098
3498fb3357SAndrey Smetanin #define HV_X64_MSR_SINT9                        0x40000099
3598fb3357SAndrey Smetanin #define HV_X64_MSR_SINT10                       0x4000009A
3698fb3357SAndrey Smetanin #define HV_X64_MSR_SINT11                       0x4000009B
3798fb3357SAndrey Smetanin #define HV_X64_MSR_SINT12                       0x4000009C
3898fb3357SAndrey Smetanin #define HV_X64_MSR_SINT13                       0x4000009D
3998fb3357SAndrey Smetanin #define HV_X64_MSR_SINT14                       0x4000009E
4098fb3357SAndrey Smetanin #define HV_X64_MSR_SINT15                       0x4000009F
4198fb3357SAndrey Smetanin 
4269d4bf75SAndrey Smetanin /*
4369d4bf75SAndrey Smetanin  * Synthetic Timer MSRs. Four timers per vcpu.
4469d4bf75SAndrey Smetanin  */
4569d4bf75SAndrey Smetanin 
4669d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER0_CONFIG               0x400000B0
4769d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER0_COUNT                0x400000B1
4869d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER1_CONFIG               0x400000B2
4969d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER1_COUNT                0x400000B3
5069d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER2_CONFIG               0x400000B4
5169d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER2_COUNT                0x400000B5
5269d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER3_CONFIG               0x400000B6
5369d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER3_COUNT                0x400000B7
5469d4bf75SAndrey Smetanin 
5598fb3357SAndrey Smetanin #define HV_SYNIC_CONTROL_ENABLE                 (1ULL << 0)
5698fb3357SAndrey Smetanin #define HV_SYNIC_SIMP_ENABLE                    (1ULL << 0)
5798fb3357SAndrey Smetanin #define HV_SYNIC_SIEFP_ENABLE                   (1ULL << 0)
5898fb3357SAndrey Smetanin #define HV_SYNIC_SINT_MASKED                    (1ULL << 16)
5998fb3357SAndrey Smetanin #define HV_SYNIC_SINT_AUTO_EOI                  (1ULL << 17)
6098fb3357SAndrey Smetanin #define HV_SYNIC_SINT_VECTOR_MASK               (0xFF)
6198fb3357SAndrey Smetanin #define HV_SYNIC_SINT_COUNT                     16
6298fb3357SAndrey Smetanin 
63*30353da7SVitaly Kuznetsov /*
64*30353da7SVitaly Kuznetsov  * Synthetic timer configuration.
65*30353da7SVitaly Kuznetsov  */
66*30353da7SVitaly Kuznetsov union hv_stimer_config {
67*30353da7SVitaly Kuznetsov 	u64 as_uint64;
68*30353da7SVitaly Kuznetsov 	struct {
69*30353da7SVitaly Kuznetsov 		u64 enable:1;
70*30353da7SVitaly Kuznetsov 		u64 periodic:1;
71*30353da7SVitaly Kuznetsov 		u64 lazy:1;
72*30353da7SVitaly Kuznetsov 		u64 auto_enable:1;
73*30353da7SVitaly Kuznetsov 		u64 apic_vector:8;
74*30353da7SVitaly Kuznetsov 		u64 direct_mode:1;
75*30353da7SVitaly Kuznetsov 		u64 reserved_z0:3;
76*30353da7SVitaly Kuznetsov 		u64 sintx:4;
77*30353da7SVitaly Kuznetsov 		u64 reserved_z1:44;
78*30353da7SVitaly Kuznetsov 	};
79*30353da7SVitaly Kuznetsov };
8069d4bf75SAndrey Smetanin 
8169d4bf75SAndrey Smetanin #define HV_SYNIC_STIMER_COUNT           (4)
8269d4bf75SAndrey Smetanin 
8369d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message constants. */
8469d4bf75SAndrey Smetanin #define HV_MESSAGE_SIZE                 (256)
8569d4bf75SAndrey Smetanin #define HV_MESSAGE_PAYLOAD_BYTE_COUNT   (240)
8669d4bf75SAndrey Smetanin #define HV_MESSAGE_PAYLOAD_QWORD_COUNT  (30)
8769d4bf75SAndrey Smetanin 
8869d4bf75SAndrey Smetanin /* Define hypervisor message types. */
8969d4bf75SAndrey Smetanin enum hv_message_type {
9069d4bf75SAndrey Smetanin         HVMSG_NONE                      = 0x00000000,
9169d4bf75SAndrey Smetanin 
9269d4bf75SAndrey Smetanin         /* Memory access messages. */
9369d4bf75SAndrey Smetanin         HVMSG_UNMAPPED_GPA              = 0x80000000,
9469d4bf75SAndrey Smetanin         HVMSG_GPA_INTERCEPT             = 0x80000001,
9569d4bf75SAndrey Smetanin 
9669d4bf75SAndrey Smetanin         /* Timer notification messages. */
9769d4bf75SAndrey Smetanin         HVMSG_TIMER_EXPIRED                     = 0x80000010,
9869d4bf75SAndrey Smetanin 
9969d4bf75SAndrey Smetanin         /* Error messages. */
10069d4bf75SAndrey Smetanin         HVMSG_INVALID_VP_REGISTER_VALUE = 0x80000020,
10169d4bf75SAndrey Smetanin         HVMSG_UNRECOVERABLE_EXCEPTION   = 0x80000021,
10269d4bf75SAndrey Smetanin         HVMSG_UNSUPPORTED_FEATURE               = 0x80000022,
10369d4bf75SAndrey Smetanin 
10469d4bf75SAndrey Smetanin         /* Trace buffer complete messages. */
10569d4bf75SAndrey Smetanin         HVMSG_EVENTLOG_BUFFERCOMPLETE   = 0x80000040,
10669d4bf75SAndrey Smetanin 
10769d4bf75SAndrey Smetanin         /* Platform-specific processor intercept messages. */
10869d4bf75SAndrey Smetanin         HVMSG_X64_IOPORT_INTERCEPT              = 0x80010000,
10969d4bf75SAndrey Smetanin         HVMSG_X64_MSR_INTERCEPT         = 0x80010001,
11069d4bf75SAndrey Smetanin         HVMSG_X64_CPUID_INTERCEPT               = 0x80010002,
11169d4bf75SAndrey Smetanin         HVMSG_X64_EXCEPTION_INTERCEPT   = 0x80010003,
11269d4bf75SAndrey Smetanin         HVMSG_X64_APIC_EOI                      = 0x80010004,
11369d4bf75SAndrey Smetanin         HVMSG_X64_LEGACY_FP_ERROR               = 0x80010005
11469d4bf75SAndrey Smetanin };
11569d4bf75SAndrey Smetanin 
11669d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message flags. */
11769d4bf75SAndrey Smetanin union hv_message_flags {
11869d4bf75SAndrey Smetanin         uint8_t asu8;
11969d4bf75SAndrey Smetanin         struct {
12069d4bf75SAndrey Smetanin                 uint8_t msg_pending:1;
12169d4bf75SAndrey Smetanin                 uint8_t reserved:7;
12269d4bf75SAndrey Smetanin         };
12369d4bf75SAndrey Smetanin };
12469d4bf75SAndrey Smetanin 
12569d4bf75SAndrey Smetanin union hv_port_id {
12669d4bf75SAndrey Smetanin         uint32_t asu32;
12769d4bf75SAndrey Smetanin         struct {
12869d4bf75SAndrey Smetanin                 uint32_t id:24;
12969d4bf75SAndrey Smetanin                 uint32_t reserved:8;
13069d4bf75SAndrey Smetanin         } u;
13169d4bf75SAndrey Smetanin };
13269d4bf75SAndrey Smetanin 
13369d4bf75SAndrey Smetanin /* Define port type. */
13469d4bf75SAndrey Smetanin enum hv_port_type {
13569d4bf75SAndrey Smetanin         HVPORT_MSG      = 1,
13669d4bf75SAndrey Smetanin         HVPORT_EVENT            = 2,
13769d4bf75SAndrey Smetanin         HVPORT_MONITOR  = 3
13869d4bf75SAndrey Smetanin };
13969d4bf75SAndrey Smetanin 
14069d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message header. */
14169d4bf75SAndrey Smetanin struct hv_message_header {
14269d4bf75SAndrey Smetanin         uint32_t message_type;
14369d4bf75SAndrey Smetanin         uint8_t payload_size;
14469d4bf75SAndrey Smetanin         union hv_message_flags message_flags;
14569d4bf75SAndrey Smetanin         uint8_t reserved[2];
14669d4bf75SAndrey Smetanin         union {
14769d4bf75SAndrey Smetanin                 uint64_t sender;
14869d4bf75SAndrey Smetanin                 union hv_port_id port;
14969d4bf75SAndrey Smetanin         };
15069d4bf75SAndrey Smetanin };
15169d4bf75SAndrey Smetanin 
15269d4bf75SAndrey Smetanin /* Define timer message payload structure. */
15369d4bf75SAndrey Smetanin struct hv_timer_message_payload {
15469d4bf75SAndrey Smetanin         uint32_t timer_index;
15569d4bf75SAndrey Smetanin         uint32_t reserved;
15669d4bf75SAndrey Smetanin         uint64_t expiration_time;       /* When the timer expired */
15769d4bf75SAndrey Smetanin         uint64_t delivery_time; /* When the message was delivered */
15869d4bf75SAndrey Smetanin };
15969d4bf75SAndrey Smetanin 
16069d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message format. */
16169d4bf75SAndrey Smetanin struct hv_message {
16269d4bf75SAndrey Smetanin         struct hv_message_header header;
16369d4bf75SAndrey Smetanin         union {
16469d4bf75SAndrey Smetanin                 uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
16569d4bf75SAndrey Smetanin         } u;
16669d4bf75SAndrey Smetanin };
16769d4bf75SAndrey Smetanin 
16869d4bf75SAndrey Smetanin /* Define the synthetic interrupt message page layout. */
16969d4bf75SAndrey Smetanin struct hv_message_page {
17069d4bf75SAndrey Smetanin         struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
17169d4bf75SAndrey Smetanin };
17269d4bf75SAndrey Smetanin 
173b9f6c977SRoman Kagan #define HV_EVENT_FLAGS_COUNT	(256 * 8)
174b9f6c977SRoman Kagan 
175b9f6c977SRoman Kagan struct hv_event_flags {
176b9f6c977SRoman Kagan 	ulong flags[HV_EVENT_FLAGS_COUNT / (8 * sizeof(ulong))];
177b9f6c977SRoman Kagan };
178b9f6c977SRoman Kagan 
179b9f6c977SRoman Kagan struct hv_event_flags_page {
180b9f6c977SRoman Kagan 	struct hv_event_flags slot[HV_SYNIC_SINT_COUNT];
181b9f6c977SRoman Kagan };
182b9f6c977SRoman Kagan 
183b9f6c977SRoman Kagan #define HV_X64_MSR_HYPERCALL_ENABLE             0x1
184b9f6c977SRoman Kagan 
185b9f6c977SRoman Kagan #define HV_HYPERCALL_FAST               (1u << 16)
186b9f6c977SRoman Kagan 
187b9f6c977SRoman Kagan #define HVCALL_POST_MESSAGE                     0x5c
188b9f6c977SRoman Kagan #define HVCALL_SIGNAL_EVENT                     0x5d
189b9f6c977SRoman Kagan 
190b9f6c977SRoman Kagan struct hv_input_post_message {
191b9f6c977SRoman Kagan 	u32 connectionid;
192b9f6c977SRoman Kagan 	u32 reserved;
193b9f6c977SRoman Kagan 	u32 message_type;
194b9f6c977SRoman Kagan 	u32 payload_size;
195b9f6c977SRoman Kagan 	u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
196b9f6c977SRoman Kagan };
197b9f6c977SRoman Kagan 
198e53b4aceSMetin Kaya static inline bool hv_synic_supported(void)
19998fb3357SAndrey Smetanin {
20098fb3357SAndrey Smetanin    return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNIC_AVAILABLE;
20198fb3357SAndrey Smetanin }
20298fb3357SAndrey Smetanin 
203e53b4aceSMetin Kaya static inline bool hv_stimer_supported(void)
20469d4bf75SAndrey Smetanin {
205ac3ef494SMetin Kaya     return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNTIMER_AVAILABLE;
20669d4bf75SAndrey Smetanin }
20769d4bf75SAndrey Smetanin 
20869d4bf75SAndrey Smetanin static inline bool hv_time_ref_counter_supported(void)
20969d4bf75SAndrey Smetanin {
21069d4bf75SAndrey Smetanin     return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE;
21169d4bf75SAndrey Smetanin }
21269d4bf75SAndrey Smetanin 
213d2c248afSRoman Kagan void synic_sint_create(u8 sint, u8 vec, bool auto_eoi);
214d2c248afSRoman Kagan void synic_sint_set(u8 vcpu, u8 sint);
215d2c248afSRoman Kagan void synic_sint_destroy(u8 sint);
216faf6f82fSRoman Kagan void msg_conn_create(u8 sint, u8 vec, u8 conn_id);
217faf6f82fSRoman Kagan void msg_conn_destroy(u8 sint, u8 conn_id);
218faf6f82fSRoman Kagan void evt_conn_create(u8 sint, u8 vec, u8 conn_id);
219faf6f82fSRoman Kagan void evt_conn_destroy(u8 sint, u8 conn_id);
22098fb3357SAndrey Smetanin 
221907ce0f7SPaolo Bonzini struct hv_reference_tsc_page {
222907ce0f7SPaolo Bonzini         uint32_t tsc_sequence;
223907ce0f7SPaolo Bonzini         uint32_t res1;
224907ce0f7SPaolo Bonzini         uint64_t tsc_scale;
225907ce0f7SPaolo Bonzini         int64_t tsc_offset;
226907ce0f7SPaolo Bonzini };
227907ce0f7SPaolo Bonzini 
228907ce0f7SPaolo Bonzini 
22998fb3357SAndrey Smetanin #endif
230