xref: /kvm-unit-tests/x86/hyperv.h (revision 69d4bf751641520f5b2d8e3f160c63c8966fcd8b)
198fb3357SAndrey Smetanin #ifndef __HYPERV_H
298fb3357SAndrey Smetanin #define __HYPERV_H
398fb3357SAndrey Smetanin 
498fb3357SAndrey Smetanin #include "libcflat.h"
598fb3357SAndrey Smetanin #include "processor.h"
698fb3357SAndrey Smetanin #include "io.h"
798fb3357SAndrey Smetanin 
898fb3357SAndrey Smetanin #define HYPERV_CPUID_FEATURES                   0x40000003
998fb3357SAndrey Smetanin 
10*69d4bf75SAndrey Smetanin #define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE     (1 << 1)
1198fb3357SAndrey Smetanin #define HV_X64_MSR_SYNIC_AVAILABLE              (1 << 2)
12*69d4bf75SAndrey Smetanin #define HV_X64_MSR_SYNTIMER_AVAILABLE           (1 << 3)
13*69d4bf75SAndrey Smetanin 
14*69d4bf75SAndrey Smetanin #define HV_X64_MSR_TIME_REF_COUNT               0x40000020
1598fb3357SAndrey Smetanin 
1698fb3357SAndrey Smetanin /* Define synthetic interrupt controller model specific registers. */
1798fb3357SAndrey Smetanin #define HV_X64_MSR_SCONTROL                     0x40000080
1898fb3357SAndrey Smetanin #define HV_X64_MSR_SVERSION                     0x40000081
1998fb3357SAndrey Smetanin #define HV_X64_MSR_SIEFP                        0x40000082
2098fb3357SAndrey Smetanin #define HV_X64_MSR_SIMP                         0x40000083
2198fb3357SAndrey Smetanin #define HV_X64_MSR_EOM                          0x40000084
2298fb3357SAndrey Smetanin #define HV_X64_MSR_SINT0                        0x40000090
2398fb3357SAndrey Smetanin #define HV_X64_MSR_SINT1                        0x40000091
2498fb3357SAndrey Smetanin #define HV_X64_MSR_SINT2                        0x40000092
2598fb3357SAndrey Smetanin #define HV_X64_MSR_SINT3                        0x40000093
2698fb3357SAndrey Smetanin #define HV_X64_MSR_SINT4                        0x40000094
2798fb3357SAndrey Smetanin #define HV_X64_MSR_SINT5                        0x40000095
2898fb3357SAndrey Smetanin #define HV_X64_MSR_SINT6                        0x40000096
2998fb3357SAndrey Smetanin #define HV_X64_MSR_SINT7                        0x40000097
3098fb3357SAndrey Smetanin #define HV_X64_MSR_SINT8                        0x40000098
3198fb3357SAndrey Smetanin #define HV_X64_MSR_SINT9                        0x40000099
3298fb3357SAndrey Smetanin #define HV_X64_MSR_SINT10                       0x4000009A
3398fb3357SAndrey Smetanin #define HV_X64_MSR_SINT11                       0x4000009B
3498fb3357SAndrey Smetanin #define HV_X64_MSR_SINT12                       0x4000009C
3598fb3357SAndrey Smetanin #define HV_X64_MSR_SINT13                       0x4000009D
3698fb3357SAndrey Smetanin #define HV_X64_MSR_SINT14                       0x4000009E
3798fb3357SAndrey Smetanin #define HV_X64_MSR_SINT15                       0x4000009F
3898fb3357SAndrey Smetanin 
39*69d4bf75SAndrey Smetanin /*
40*69d4bf75SAndrey Smetanin  * Synthetic Timer MSRs. Four timers per vcpu.
41*69d4bf75SAndrey Smetanin  */
42*69d4bf75SAndrey Smetanin 
43*69d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER0_CONFIG               0x400000B0
44*69d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER0_COUNT                0x400000B1
45*69d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER1_CONFIG               0x400000B2
46*69d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER1_COUNT                0x400000B3
47*69d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER2_CONFIG               0x400000B4
48*69d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER2_COUNT                0x400000B5
49*69d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER3_CONFIG               0x400000B6
50*69d4bf75SAndrey Smetanin #define HV_X64_MSR_STIMER3_COUNT                0x400000B7
51*69d4bf75SAndrey Smetanin 
5298fb3357SAndrey Smetanin #define HV_SYNIC_CONTROL_ENABLE                 (1ULL << 0)
5398fb3357SAndrey Smetanin #define HV_SYNIC_SIMP_ENABLE                    (1ULL << 0)
5498fb3357SAndrey Smetanin #define HV_SYNIC_SIEFP_ENABLE                   (1ULL << 0)
5598fb3357SAndrey Smetanin #define HV_SYNIC_SINT_MASKED                    (1ULL << 16)
5698fb3357SAndrey Smetanin #define HV_SYNIC_SINT_AUTO_EOI                  (1ULL << 17)
5798fb3357SAndrey Smetanin #define HV_SYNIC_SINT_VECTOR_MASK               (0xFF)
5898fb3357SAndrey Smetanin #define HV_SYNIC_SINT_COUNT                     16
5998fb3357SAndrey Smetanin 
60*69d4bf75SAndrey Smetanin #define HV_STIMER_ENABLE                (1ULL << 0)
61*69d4bf75SAndrey Smetanin #define HV_STIMER_PERIODIC              (1ULL << 1)
62*69d4bf75SAndrey Smetanin #define HV_STIMER_LAZY                  (1ULL << 2)
63*69d4bf75SAndrey Smetanin #define HV_STIMER_AUTOENABLE            (1ULL << 3)
64*69d4bf75SAndrey Smetanin #define HV_STIMER_SINT(config)          (__u8)(((config) >> 16) & 0x0F)
65*69d4bf75SAndrey Smetanin 
66*69d4bf75SAndrey Smetanin #define HV_SYNIC_STIMER_COUNT           (4)
67*69d4bf75SAndrey Smetanin 
68*69d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message constants. */
69*69d4bf75SAndrey Smetanin #define HV_MESSAGE_SIZE                 (256)
70*69d4bf75SAndrey Smetanin #define HV_MESSAGE_PAYLOAD_BYTE_COUNT   (240)
71*69d4bf75SAndrey Smetanin #define HV_MESSAGE_PAYLOAD_QWORD_COUNT  (30)
72*69d4bf75SAndrey Smetanin 
73*69d4bf75SAndrey Smetanin /* Define hypervisor message types. */
74*69d4bf75SAndrey Smetanin enum hv_message_type {
75*69d4bf75SAndrey Smetanin         HVMSG_NONE                      = 0x00000000,
76*69d4bf75SAndrey Smetanin 
77*69d4bf75SAndrey Smetanin         /* Memory access messages. */
78*69d4bf75SAndrey Smetanin         HVMSG_UNMAPPED_GPA              = 0x80000000,
79*69d4bf75SAndrey Smetanin         HVMSG_GPA_INTERCEPT             = 0x80000001,
80*69d4bf75SAndrey Smetanin 
81*69d4bf75SAndrey Smetanin         /* Timer notification messages. */
82*69d4bf75SAndrey Smetanin         HVMSG_TIMER_EXPIRED                     = 0x80000010,
83*69d4bf75SAndrey Smetanin 
84*69d4bf75SAndrey Smetanin         /* Error messages. */
85*69d4bf75SAndrey Smetanin         HVMSG_INVALID_VP_REGISTER_VALUE = 0x80000020,
86*69d4bf75SAndrey Smetanin         HVMSG_UNRECOVERABLE_EXCEPTION   = 0x80000021,
87*69d4bf75SAndrey Smetanin         HVMSG_UNSUPPORTED_FEATURE               = 0x80000022,
88*69d4bf75SAndrey Smetanin 
89*69d4bf75SAndrey Smetanin         /* Trace buffer complete messages. */
90*69d4bf75SAndrey Smetanin         HVMSG_EVENTLOG_BUFFERCOMPLETE   = 0x80000040,
91*69d4bf75SAndrey Smetanin 
92*69d4bf75SAndrey Smetanin         /* Platform-specific processor intercept messages. */
93*69d4bf75SAndrey Smetanin         HVMSG_X64_IOPORT_INTERCEPT              = 0x80010000,
94*69d4bf75SAndrey Smetanin         HVMSG_X64_MSR_INTERCEPT         = 0x80010001,
95*69d4bf75SAndrey Smetanin         HVMSG_X64_CPUID_INTERCEPT               = 0x80010002,
96*69d4bf75SAndrey Smetanin         HVMSG_X64_EXCEPTION_INTERCEPT   = 0x80010003,
97*69d4bf75SAndrey Smetanin         HVMSG_X64_APIC_EOI                      = 0x80010004,
98*69d4bf75SAndrey Smetanin         HVMSG_X64_LEGACY_FP_ERROR               = 0x80010005
99*69d4bf75SAndrey Smetanin };
100*69d4bf75SAndrey Smetanin 
101*69d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message flags. */
102*69d4bf75SAndrey Smetanin union hv_message_flags {
103*69d4bf75SAndrey Smetanin         uint8_t asu8;
104*69d4bf75SAndrey Smetanin         struct {
105*69d4bf75SAndrey Smetanin                 uint8_t msg_pending:1;
106*69d4bf75SAndrey Smetanin                 uint8_t reserved:7;
107*69d4bf75SAndrey Smetanin         };
108*69d4bf75SAndrey Smetanin };
109*69d4bf75SAndrey Smetanin 
110*69d4bf75SAndrey Smetanin union hv_port_id {
111*69d4bf75SAndrey Smetanin         uint32_t asu32;
112*69d4bf75SAndrey Smetanin         struct {
113*69d4bf75SAndrey Smetanin                 uint32_t id:24;
114*69d4bf75SAndrey Smetanin                 uint32_t reserved:8;
115*69d4bf75SAndrey Smetanin         } u;
116*69d4bf75SAndrey Smetanin };
117*69d4bf75SAndrey Smetanin 
118*69d4bf75SAndrey Smetanin /* Define port type. */
119*69d4bf75SAndrey Smetanin enum hv_port_type {
120*69d4bf75SAndrey Smetanin         HVPORT_MSG      = 1,
121*69d4bf75SAndrey Smetanin         HVPORT_EVENT            = 2,
122*69d4bf75SAndrey Smetanin         HVPORT_MONITOR  = 3
123*69d4bf75SAndrey Smetanin };
124*69d4bf75SAndrey Smetanin 
125*69d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message header. */
126*69d4bf75SAndrey Smetanin struct hv_message_header {
127*69d4bf75SAndrey Smetanin         uint32_t message_type;
128*69d4bf75SAndrey Smetanin         uint8_t payload_size;
129*69d4bf75SAndrey Smetanin         union hv_message_flags message_flags;
130*69d4bf75SAndrey Smetanin         uint8_t reserved[2];
131*69d4bf75SAndrey Smetanin         union {
132*69d4bf75SAndrey Smetanin                 uint64_t sender;
133*69d4bf75SAndrey Smetanin                 union hv_port_id port;
134*69d4bf75SAndrey Smetanin         };
135*69d4bf75SAndrey Smetanin };
136*69d4bf75SAndrey Smetanin 
137*69d4bf75SAndrey Smetanin /* Define timer message payload structure. */
138*69d4bf75SAndrey Smetanin struct hv_timer_message_payload {
139*69d4bf75SAndrey Smetanin         uint32_t timer_index;
140*69d4bf75SAndrey Smetanin         uint32_t reserved;
141*69d4bf75SAndrey Smetanin         uint64_t expiration_time;       /* When the timer expired */
142*69d4bf75SAndrey Smetanin         uint64_t delivery_time; /* When the message was delivered */
143*69d4bf75SAndrey Smetanin };
144*69d4bf75SAndrey Smetanin 
145*69d4bf75SAndrey Smetanin /* Define synthetic interrupt controller message format. */
146*69d4bf75SAndrey Smetanin struct hv_message {
147*69d4bf75SAndrey Smetanin         struct hv_message_header header;
148*69d4bf75SAndrey Smetanin         union {
149*69d4bf75SAndrey Smetanin                 uint64_t payload[HV_MESSAGE_PAYLOAD_QWORD_COUNT];
150*69d4bf75SAndrey Smetanin         } u;
151*69d4bf75SAndrey Smetanin };
152*69d4bf75SAndrey Smetanin 
153*69d4bf75SAndrey Smetanin /* Define the synthetic interrupt message page layout. */
154*69d4bf75SAndrey Smetanin struct hv_message_page {
155*69d4bf75SAndrey Smetanin         struct hv_message sint_message[HV_SYNIC_SINT_COUNT];
156*69d4bf75SAndrey Smetanin };
157*69d4bf75SAndrey Smetanin 
15898fb3357SAndrey Smetanin enum {
15998fb3357SAndrey Smetanin     HV_TEST_DEV_SINT_ROUTE_CREATE = 1,
16098fb3357SAndrey Smetanin     HV_TEST_DEV_SINT_ROUTE_DESTROY,
16198fb3357SAndrey Smetanin     HV_TEST_DEV_SINT_ROUTE_SET_SINT
16298fb3357SAndrey Smetanin };
16398fb3357SAndrey Smetanin 
16498fb3357SAndrey Smetanin static inline bool synic_supported(void)
16598fb3357SAndrey Smetanin {
16698fb3357SAndrey Smetanin    return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNIC_AVAILABLE;
16798fb3357SAndrey Smetanin }
16898fb3357SAndrey Smetanin 
169*69d4bf75SAndrey Smetanin static inline bool stimer_supported(void)
170*69d4bf75SAndrey Smetanin {
171*69d4bf75SAndrey Smetanin     return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_SYNIC_AVAILABLE;
172*69d4bf75SAndrey Smetanin }
173*69d4bf75SAndrey Smetanin 
174*69d4bf75SAndrey Smetanin static inline bool hv_time_ref_counter_supported(void)
175*69d4bf75SAndrey Smetanin {
176*69d4bf75SAndrey Smetanin     return cpuid(HYPERV_CPUID_FEATURES).a & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE;
177*69d4bf75SAndrey Smetanin }
178*69d4bf75SAndrey Smetanin 
17998fb3357SAndrey Smetanin void synic_sint_create(int vcpu, int sint, int vec, bool auto_eoi);
18098fb3357SAndrey Smetanin void synic_sint_set(int vcpu, int sint);
18198fb3357SAndrey Smetanin void synic_sint_destroy(int vcpu, int sint);
18298fb3357SAndrey Smetanin 
18398fb3357SAndrey Smetanin #endif
184