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