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
13*367d44e2SVitaly Kuznetsov #define HV_STIMER_DIRECT_MODE_AVAILABLE (1 << 19)
14*367d44e2SVitaly Kuznetsov
15b9f6c977SRoman Kagan #define HV_X64_MSR_GUEST_OS_ID 0x40000000
16b9f6c977SRoman Kagan #define HV_X64_MSR_HYPERCALL 0x40000001
17b9f6c977SRoman Kagan
1869d4bf75SAndrey Smetanin #define HV_X64_MSR_TIME_REF_COUNT 0x40000020
19907ce0f7SPaolo Bonzini #define HV_X64_MSR_REFERENCE_TSC 0x40000021
2098fb3357SAndrey Smetanin
2198fb3357SAndrey Smetanin /* Define synthetic interrupt controller model specific registers. */
2298fb3357SAndrey Smetanin #define HV_X64_MSR_SCONTROL 0x40000080
2398fb3357SAndrey Smetanin #define HV_X64_MSR_SVERSION 0x40000081
2498fb3357SAndrey Smetanin #define HV_X64_MSR_SIEFP 0x40000082
2598fb3357SAndrey Smetanin #define HV_X64_MSR_SIMP 0x40000083
2698fb3357SAndrey Smetanin #define HV_X64_MSR_EOM 0x40000084
2798fb3357SAndrey Smetanin #define HV_X64_MSR_SINT0 0x40000090
2898fb3357SAndrey Smetanin #define HV_X64_MSR_SINT1 0x40000091
2998fb3357SAndrey Smetanin #define HV_X64_MSR_SINT2 0x40000092
3098fb3357SAndrey Smetanin #define HV_X64_MSR_SINT3 0x40000093
3198fb3357SAndrey Smetanin #define HV_X64_MSR_SINT4 0x40000094
3298fb3357SAndrey Smetanin #define HV_X64_MSR_SINT5 0x40000095
3398fb3357SAndrey Smetanin #define HV_X64_MSR_SINT6 0x40000096
3498fb3357SAndrey Smetanin #define HV_X64_MSR_SINT7 0x40000097
3598fb3357SAndrey Smetanin #define HV_X64_MSR_SINT8 0x40000098
3698fb3357SAndrey Smetanin #define HV_X64_MSR_SINT9 0x40000099
3798fb3357SAndrey Smetanin #define HV_X64_MSR_SINT10 0x4000009A
3898fb3357SAndrey Smetanin #define HV_X64_MSR_SINT11 0x4000009B
3998fb3357SAndrey Smetanin #define HV_X64_MSR_SINT12 0x4000009C
4098fb3357SAndrey Smetanin #define HV_X64_MSR_SINT13 0x4000009D
4198fb3357SAndrey Smetanin #define HV_X64_MSR_SINT14 0x4000009E
4298fb3357SAndrey Smetanin #define HV_X64_MSR_SINT15 0x4000009F
4398fb3357SAndrey Smetanin
4469d4bf75SAndrey Smetanin /*
4569d4bf75SAndrey Smetanin * Synthetic Timer MSRs. Four timers per vcpu.
4669d4bf75SAndrey Smetanin */
4769d4bf75SAndrey Smetanin
4869d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER0_CONFIG 0x400000B0
4969d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER0_COUNT 0x400000B1
5069d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER1_CONFIG 0x400000B2
5169d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER1_COUNT 0x400000B3
5269d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER2_CONFIG 0x400000B4
5369d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER2_COUNT 0x400000B5
5469d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER3_CONFIG 0x400000B6
5569d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER3_COUNT 0x400000B7
5669d4bf75SAndrey Smetanin
5798fb3357SAndrey Smetanin #define HV_SYNIC_CONTROL_ENABLE (1ULL << 0)
5898fb3357SAndrey Smetanin #define HV_SYNIC_SIMP_ENABLE (1ULL << 0)
5998fb3357SAndrey Smetanin #define HV_SYNIC_SIEFP_ENABLE (1ULL << 0)
6098fb3357SAndrey Smetanin #define HV_SYNIC_SINT_MASKED (1ULL << 16)
6198fb3357SAndrey Smetanin #define HV_SYNIC_SINT_AUTO_EOI (1ULL << 17)
6298fb3357SAndrey Smetanin #define HV_SYNIC_SINT_VECTOR_MASK (0xFF)
6398fb3357SAndrey Smetanin #define HV_SYNIC_SINT_COUNT 16
6498fb3357SAndrey Smetanin
6530353da7SVitaly Kuznetsov /*
6630353da7SVitaly Kuznetsov * Synthetic timer configuration.
6730353da7SVitaly Kuznetsov */
6830353da7SVitaly Kuznetsov union hv_stimer_config {
6930353da7SVitaly Kuznetsov u64 as_uint64;
7030353da7SVitaly Kuznetsov struct {
7130353da7SVitaly Kuznetsov u64 enable:1;
7230353da7SVitaly Kuznetsov u64 periodic:1;
7330353da7SVitaly Kuznetsov u64 lazy:1;
7430353da7SVitaly Kuznetsov u64 auto_enable:1;
7530353da7SVitaly Kuznetsov u64 apic_vector:8;
7630353da7SVitaly Kuznetsov u64 direct_mode:1;
7730353da7SVitaly Kuznetsov u64 reserved_z0:3;
7830353da7SVitaly Kuznetsov u64 sintx:4;
7930353da7SVitaly Kuznetsov u64 reserved_z1:44;
8030353da7SVitaly Kuznetsov };
8130353da7SVitaly Kuznetsov };
8269d4bf75SAndrey Smetanin
8369d4bf75SAndrey Smetanin #define HV_SYNIC_STIMER_COUNT (4)
8469d4bf75SAndrey Smetanin
8569d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message constants. */
8669d4bf75SAndrey Smetanin #define HV_MESSAGE_SIZE (256)
8769d4bf75SAndrey Smetanin #define HV_MESSAGE_PAYLOAD_BYTE_COUNT (240)
8869d4bf75SAndrey Smetanin #define HV_MESSAGE_PAYLOAD_QWORD_COUNT (30)
8969d4bf75SAndrey Smetanin
9069d4bf75SAndrey Smetanin /* Define hypervisor message types. */
9169d4bf75SAndrey Smetanin enum hv_message_type {
9269d4bf75SAndrey Smetanin HVMSG_NONE = 0x00000000,
9369d4bf75SAndrey Smetanin
9469d4bf75SAndrey Smetanin /* Memory access messages. */
9569d4bf75SAndrey Smetanin HVMSG_UNMAPPED_GPA = 0x80000000,
9669d4bf75SAndrey Smetanin HVMSG_GPA_INTERCEPT = 0x80000001,
9769d4bf75SAndrey Smetanin
9869d4bf75SAndrey Smetanin /* Timer notification messages. */
9969d4bf75SAndrey Smetanin HVMSG_TIMER_EXPIRED = 0x80000010,
10069d4bf75SAndrey Smetanin
10169d4bf75SAndrey Smetanin /* Error messages. */
10269d4bf75SAndrey Smetanin HVMSG_INVALID_VP_REGISTER_VALUE = 0x80000020,
10369d4bf75SAndrey Smetanin HVMSG_UNRECOVERABLE_EXCEPTION = 0x80000021,
10469d4bf75SAndrey Smetanin HVMSG_UNSUPPORTED_FEATURE = 0x80000022,
10569d4bf75SAndrey Smetanin
10669d4bf75SAndrey Smetanin /* Trace buffer complete messages. */
10769d4bf75SAndrey Smetanin HVMSG_EVENTLOG_BUFFERCOMPLETE = 0x80000040,
10869d4bf75SAndrey Smetanin
10969d4bf75SAndrey Smetanin /* Platform-specific processor intercept messages. */
11069d4bf75SAndrey Smetanin HVMSG_X64_IOPORT_INTERCEPT = 0x80010000,
11169d4bf75SAndrey Smetanin HVMSG_X64_MSR_INTERCEPT = 0x80010001,
11269d4bf75SAndrey Smetanin HVMSG_X64_CPUID_INTERCEPT = 0x80010002,
11369d4bf75SAndrey Smetanin HVMSG_X64_EXCEPTION_INTERCEPT = 0x80010003,
11469d4bf75SAndrey Smetanin HVMSG_X64_APIC_EOI = 0x80010004,
11569d4bf75SAndrey Smetanin HVMSG_X64_LEGACY_FP_ERROR = 0x80010005
11669d4bf75SAndrey Smetanin };
11769d4bf75SAndrey Smetanin
11869d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message flags. */
11969d4bf75SAndrey Smetanin union hv_message_flags {
12069d4bf75SAndrey Smetanin uint8_t asu8;
12169d4bf75SAndrey Smetanin struct {
12269d4bf75SAndrey Smetanin uint8_t msg_pending:1;
12369d4bf75SAndrey Smetanin uint8_t reserved:7;
12469d4bf75SAndrey Smetanin };
12569d4bf75SAndrey Smetanin };
12669d4bf75SAndrey Smetanin
12769d4bf75SAndrey Smetanin union hv_port_id {
12869d4bf75SAndrey Smetanin uint32_t asu32;
12969d4bf75SAndrey Smetanin struct {
13069d4bf75SAndrey Smetanin uint32_t id:24;
13169d4bf75SAndrey Smetanin uint32_t reserved:8;
13269d4bf75SAndrey Smetanin } u;
13369d4bf75SAndrey Smetanin };
13469d4bf75SAndrey Smetanin
13569d4bf75SAndrey Smetanin /* Define port type. */
13669d4bf75SAndrey Smetanin enum hv_port_type {
13769d4bf75SAndrey Smetanin HVPORT_MSG = 1,
13869d4bf75SAndrey Smetanin HVPORT_EVENT = 2,
13969d4bf75SAndrey Smetanin HVPORT_MONITOR = 3
14069d4bf75SAndrey Smetanin };
14169d4bf75SAndrey Smetanin
14269d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message header. */
14369d4bf75SAndrey Smetanin struct hv_message_header {
14469d4bf75SAndrey Smetanin uint32_t message_type;
14569d4bf75SAndrey Smetanin uint8_t payload_size;
14669d4bf75SAndrey Smetanin union hv_message_flags message_flags;
14769d4bf75SAndrey Smetanin uint8_t reserved[2];
14869d4bf75SAndrey Smetanin union {
14969d4bf75SAndrey Smetanin uint64_t sender;
15069d4bf75SAndrey Smetanin union hv_port_id port;
15169d4bf75SAndrey Smetanin };
15269d4bf75SAndrey Smetanin };
15369d4bf75SAndrey Smetanin
15469d4bf75SAndrey Smetanin /* Define timer message payload structure. */
15569d4bf75SAndrey Smetanin struct hv_timer_message_payload {
15669d4bf75SAndrey Smetanin uint32_t timer_index;
15769d4bf75SAndrey Smetanin uint32_t reserved;
15869d4bf75SAndrey Smetanin uint64_t expiration_time; /* When the timer expired */
15969d4bf75SAndrey Smetanin uint64_t delivery_time; /* When the message was delivered */
16069d4bf75SAndrey Smetanin };
16169d4bf75SAndrey Smetanin
16269d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message format. */
16369d4bf75SAndrey Smetanin struct hv_message {
16469d4bf75SAndrey Smetanin struct hv_message_header header;
16569d4bf75SAndrey Smetanin union {
16669d4bf75SAndrey Smetanin uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
16769d4bf75SAndrey Smetanin } u;
16869d4bf75SAndrey Smetanin };
16969d4bf75SAndrey Smetanin
17069d4bf75SAndrey Smetanin /* Define the synthetic interrupt message page layout. */
17169d4bf75SAndrey Smetanin struct hv_message_page {
17269d4bf75SAndrey Smetanin struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
17369d4bf75SAndrey Smetanin };
17469d4bf75SAndrey Smetanin
175b9f6c977SRoman Kagan #define HV_EVENT_FLAGS_COUNT (256 * 8)
176b9f6c977SRoman Kagan
177b9f6c977SRoman Kagan struct hv_event_flags {
178b9f6c977SRoman Kagan ulong flags[HV_EVENT_FLAGS_COUNT / (8 * sizeof(ulong))];
179b9f6c977SRoman Kagan };
180b9f6c977SRoman Kagan
181b9f6c977SRoman Kagan struct hv_event_flags_page {
182b9f6c977SRoman Kagan struct hv_event_flags slot[HV_SYNIC_SINT_COUNT];
183b9f6c977SRoman Kagan };
184b9f6c977SRoman Kagan
185b9f6c977SRoman Kagan #define HV_X64_MSR_HYPERCALL_ENABLE 0x1
186b9f6c977SRoman Kagan
187b9f6c977SRoman Kagan #define HV_HYPERCALL_FAST (1u << 16)
188b9f6c977SRoman Kagan
189b9f6c977SRoman Kagan #define HVCALL_POST_MESSAGE 0x5c
190b9f6c977SRoman Kagan #define HVCALL_SIGNAL_EVENT 0x5d
191b9f6c977SRoman Kagan
192b9f6c977SRoman Kagan struct hv_input_post_message {
193b9f6c977SRoman Kagan u32 connectionid;
194b9f6c977SRoman Kagan u32 reserved;
195b9f6c977SRoman Kagan u32 message_type;
196b9f6c977SRoman Kagan u32 payload_size;
197b9f6c977SRoman Kagan u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
198b9f6c977SRoman Kagan };
199b9f6c977SRoman Kagan
hv_synic_supported(void)200e53b4aceSMetin Kaya static inline bool hv_synic_supported(void)
20198fb3357SAndrey Smetanin {
20298fb3357SAndrey Smetanin return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNIC_AVAILABLE;
20398fb3357SAndrey Smetanin }
20498fb3357SAndrey Smetanin
hv_stimer_supported(void)205e53b4aceSMetin Kaya static inline bool hv_stimer_supported(void)
20669d4bf75SAndrey Smetanin {
207ac3ef494SMetin Kaya return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNTIMER_AVAILABLE;
20869d4bf75SAndrey Smetanin }
20969d4bf75SAndrey Smetanin
stimer_direct_supported(void)210*367d44e2SVitaly Kuznetsov static inline bool stimer_direct_supported(void)
211*367d44e2SVitaly Kuznetsov {
212*367d44e2SVitaly Kuznetsov return cpuid(HYPERV_CPUID_FEATURES).d & HV_STIMER_DIRECT_MODE_AVAILABLE;
213*367d44e2SVitaly Kuznetsov }
214*367d44e2SVitaly Kuznetsov
hv_time_ref_counter_supported(void)21569d4bf75SAndrey Smetanin static inline bool hv_time_ref_counter_supported(void)
21669d4bf75SAndrey Smetanin {
21769d4bf75SAndrey Smetanin return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE;
21869d4bf75SAndrey Smetanin }
21969d4bf75SAndrey Smetanin
220d2c248afSRoman Kagan void synic_sint_create(u8 sint, u8 vec, bool auto_eoi);
221d2c248afSRoman Kagan void synic_sint_set(u8 vcpu, u8 sint);
222d2c248afSRoman Kagan void synic_sint_destroy(u8 sint);
223faf6f82fSRoman Kagan void msg_conn_create(u8 sint, u8 vec, u8 conn_id);
224faf6f82fSRoman Kagan void msg_conn_destroy(u8 sint, u8 conn_id);
225faf6f82fSRoman Kagan void evt_conn_create(u8 sint, u8 vec, u8 conn_id);
226faf6f82fSRoman Kagan void evt_conn_destroy(u8 sint, u8 conn_id);
22798fb3357SAndrey Smetanin
228907ce0f7SPaolo Bonzini struct hv_reference_tsc_page {
229907ce0f7SPaolo Bonzini uint32_t tsc_sequence;
230907ce0f7SPaolo Bonzini uint32_t res1;
231907ce0f7SPaolo Bonzini uint64_t tsc_scale;
232907ce0f7SPaolo Bonzini int64_t tsc_offset;
233907ce0f7SPaolo Bonzini };
234907ce0f7SPaolo Bonzini
235907ce0f7SPaolo Bonzini
23698fb3357SAndrey Smetanin #endif
237