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