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