xref: /kvm-unit-tests/x86/hyperv.h (revision ddbcb8f4ca8aedc9835851bd9acf2cd5221d7476)
1 #ifndef X86_HYPERV_H
2 #define X86_HYPERV_H
3 
4 #include "libcflat.h"
5 #include "processor.h"
6 
7 #define HYPERV_CPUID_FEATURES                   0x40000003
8 
9 #define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE     (1 << 1)
10 #define HV_X64_MSR_SYNIC_AVAILABLE              (1 << 2)
11 #define HV_X64_MSR_SYNTIMER_AVAILABLE           (1 << 3)
12 
13 #define HV_STIMER_DIRECT_MODE_AVAILABLE		(1 << 19)
14 
15 #define HV_X64_MSR_GUEST_OS_ID                  0x40000000
16 #define HV_X64_MSR_HYPERCALL                    0x40000001
17 
18 #define HV_X64_MSR_TIME_REF_COUNT               0x40000020
19 #define HV_X64_MSR_REFERENCE_TSC                0x40000021
20 
21 /* Define synthetic interrupt controller model specific registers. */
22 #define HV_X64_MSR_SCONTROL                     0x40000080
23 #define HV_X64_MSR_SVERSION                     0x40000081
24 #define HV_X64_MSR_SIEFP                        0x40000082
25 #define HV_X64_MSR_SIMP                         0x40000083
26 #define HV_X64_MSR_EOM                          0x40000084
27 #define HV_X64_MSR_SINT0                        0x40000090
28 #define HV_X64_MSR_SINT1                        0x40000091
29 #define HV_X64_MSR_SINT2                        0x40000092
30 #define HV_X64_MSR_SINT3                        0x40000093
31 #define HV_X64_MSR_SINT4                        0x40000094
32 #define HV_X64_MSR_SINT5                        0x40000095
33 #define HV_X64_MSR_SINT6                        0x40000096
34 #define HV_X64_MSR_SINT7                        0x40000097
35 #define HV_X64_MSR_SINT8                        0x40000098
36 #define HV_X64_MSR_SINT9                        0x40000099
37 #define HV_X64_MSR_SINT10                       0x4000009A
38 #define HV_X64_MSR_SINT11                       0x4000009B
39 #define HV_X64_MSR_SINT12                       0x4000009C
40 #define HV_X64_MSR_SINT13                       0x4000009D
41 #define HV_X64_MSR_SINT14                       0x4000009E
42 #define HV_X64_MSR_SINT15                       0x4000009F
43 
44 /*
45  * Synthetic Timer MSRs. Four timers per vcpu.
46  */
47 
48 #define HV_X64_MSR_STIMER0_CONFIG               0x400000B0
49 #define HV_X64_MSR_STIMER0_COUNT                0x400000B1
50 #define HV_X64_MSR_STIMER1_CONFIG               0x400000B2
51 #define HV_X64_MSR_STIMER1_COUNT                0x400000B3
52 #define HV_X64_MSR_STIMER2_CONFIG               0x400000B4
53 #define HV_X64_MSR_STIMER2_COUNT                0x400000B5
54 #define HV_X64_MSR_STIMER3_CONFIG               0x400000B6
55 #define HV_X64_MSR_STIMER3_COUNT                0x400000B7
56 
57 #define HV_SYNIC_CONTROL_ENABLE                 (1ULL << 0)
58 #define HV_SYNIC_SIMP_ENABLE                    (1ULL << 0)
59 #define HV_SYNIC_SIEFP_ENABLE                   (1ULL << 0)
60 #define HV_SYNIC_SINT_MASKED                    (1ULL << 16)
61 #define HV_SYNIC_SINT_AUTO_EOI                  (1ULL << 17)
62 #define HV_SYNIC_SINT_VECTOR_MASK               (0xFF)
63 #define HV_SYNIC_SINT_COUNT                     16
64 
65 /*
66  * Synthetic timer configuration.
67  */
68 union hv_stimer_config {
69 	u64 as_uint64;
70 	struct {
71 		u64 enable:1;
72 		u64 periodic:1;
73 		u64 lazy:1;
74 		u64 auto_enable:1;
75 		u64 apic_vector:8;
76 		u64 direct_mode:1;
77 		u64 reserved_z0:3;
78 		u64 sintx:4;
79 		u64 reserved_z1:44;
80 	};
81 };
82 
83 #define HV_SYNIC_STIMER_COUNT           (4)
84 
85 /* Define synthetic interrupt controller message constants. */
86 #define HV_MESSAGE_SIZE                 (256)
87 #define HV_MESSAGE_PAYLOAD_BYTE_COUNT   (240)
88 #define HV_MESSAGE_PAYLOAD_QWORD_COUNT  (30)
89 
90 /* Define hypervisor message types. */
91 enum hv_message_type {
92         HVMSG_NONE                      = 0x00000000,
93 
94         /* Memory access messages. */
95         HVMSG_UNMAPPED_GPA              = 0x80000000,
96         HVMSG_GPA_INTERCEPT             = 0x80000001,
97 
98         /* Timer notification messages. */
99         HVMSG_TIMER_EXPIRED                     = 0x80000010,
100 
101         /* Error messages. */
102         HVMSG_INVALID_VP_REGISTER_VALUE = 0x80000020,
103         HVMSG_UNRECOVERABLE_EXCEPTION   = 0x80000021,
104         HVMSG_UNSUPPORTED_FEATURE               = 0x80000022,
105 
106         /* Trace buffer complete messages. */
107         HVMSG_EVENTLOG_BUFFERCOMPLETE   = 0x80000040,
108 
109         /* Platform-specific processor intercept messages. */
110         HVMSG_X64_IOPORT_INTERCEPT              = 0x80010000,
111         HVMSG_X64_MSR_INTERCEPT         = 0x80010001,
112         HVMSG_X64_CPUID_INTERCEPT               = 0x80010002,
113         HVMSG_X64_EXCEPTION_INTERCEPT   = 0x80010003,
114         HVMSG_X64_APIC_EOI                      = 0x80010004,
115         HVMSG_X64_LEGACY_FP_ERROR               = 0x80010005
116 };
117 
118 /* Define synthetic interrupt controller message flags. */
119 union hv_message_flags {
120         uint8_t asu8;
121         struct {
122                 uint8_t msg_pending:1;
123                 uint8_t reserved:7;
124         };
125 };
126 
127 union hv_port_id {
128         uint32_t asu32;
129         struct {
130                 uint32_t id:24;
131                 uint32_t reserved:8;
132         } u;
133 };
134 
135 /* Define port type. */
136 enum hv_port_type {
137         HVPORT_MSG      = 1,
138         HVPORT_EVENT            = 2,
139         HVPORT_MONITOR  = 3
140 };
141 
142 /* Define synthetic interrupt controller message header. */
143 struct hv_message_header {
144         uint32_t message_type;
145         uint8_t payload_size;
146         union hv_message_flags message_flags;
147         uint8_t reserved[2];
148         union {
149                 uint64_t sender;
150                 union hv_port_id port;
151         };
152 };
153 
154 /* Define timer message payload structure. */
155 struct hv_timer_message_payload {
156         uint32_t timer_index;
157         uint32_t reserved;
158         uint64_t expiration_time;       /* When the timer expired */
159         uint64_t delivery_time; /* When the message was delivered */
160 };
161 
162 /* Define synthetic interrupt controller message format. */
163 struct hv_message {
164         struct hv_message_header header;
165         union {
166                 uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
167         } u;
168 };
169 
170 /* Define the synthetic interrupt message page layout. */
171 struct hv_message_page {
172         struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
173 };
174 
175 #define HV_EVENT_FLAGS_COUNT	(256 * 8)
176 
177 struct hv_event_flags {
178 	ulong flags[HV_EVENT_FLAGS_COUNT / (8 * sizeof(ulong))];
179 };
180 
181 struct hv_event_flags_page {
182 	struct hv_event_flags slot[HV_SYNIC_SINT_COUNT];
183 };
184 
185 #define HV_X64_MSR_HYPERCALL_ENABLE             0x1
186 
187 #define HV_HYPERCALL_FAST               (1u << 16)
188 
189 #define HVCALL_POST_MESSAGE                     0x5c
190 #define HVCALL_SIGNAL_EVENT                     0x5d
191 
192 struct hv_input_post_message {
193 	u32 connectionid;
194 	u32 reserved;
195 	u32 message_type;
196 	u32 payload_size;
197 	u64 payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
198 };
199 
hv_synic_supported(void)200 static inline bool hv_synic_supported(void)
201 {
202    return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNIC_AVAILABLE;
203 }
204 
hv_stimer_supported(void)205 static inline bool hv_stimer_supported(void)
206 {
207     return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNTIMER_AVAILABLE;
208 }
209 
stimer_direct_supported(void)210 static inline bool stimer_direct_supported(void)
211 {
212     return cpuid(HYPERV_CPUID_FEATURES).d & HV_STIMER_DIRECT_MODE_AVAILABLE;
213 }
214 
hv_time_ref_counter_supported(void)215 static inline bool hv_time_ref_counter_supported(void)
216 {
217     return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE;
218 }
219 
220 void synic_sint_create(u8 sint, u8 vec, bool auto_eoi);
221 void synic_sint_set(u8 vcpu, u8 sint);
222 void synic_sint_destroy(u8 sint);
223 void msg_conn_create(u8 sint, u8 vec, u8 conn_id);
224 void msg_conn_destroy(u8 sint, u8 conn_id);
225 void evt_conn_create(u8 sint, u8 vec, u8 conn_id);
226 void evt_conn_destroy(u8 sint, u8 conn_id);
227 
228 struct hv_reference_tsc_page {
229         uint32_t tsc_sequence;
230         uint32_t res1;
231         uint64_t tsc_scale;
232         int64_t tsc_offset;
233 };
234 
235 
236 #endif
237