]>
Commit | Line | Data |
---|---|---|
e08cae41 PA |
1 | #ifndef _ASM_X86_MSHYPER_H |
2 | #define _ASM_X86_MSHYPER_H | |
a2a47c6c | 3 | |
e08cae41 | 4 | #include <linux/types.h> |
1aec1696 | 5 | #include <linux/interrupt.h> |
43fb06ce | 6 | #include <linux/clocksource.h> |
e08cae41 PA |
7 | #include <asm/hyperv.h> |
8 | ||
e51e57fd S |
9 | /* |
10 | * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent | |
11 | * is set by CPUID(HVCPUID_VERSION_FEATURES). | |
12 | */ | |
13 | enum hv_cpuid_function { | |
14 | HVCPUID_VERSION_FEATURES = 0x00000001, | |
15 | HVCPUID_VENDOR_MAXFUNCTION = 0x40000000, | |
16 | HVCPUID_INTERFACE = 0x40000001, | |
17 | ||
18 | /* | |
19 | * The remaining functions depend on the value of | |
20 | * HVCPUID_INTERFACE | |
21 | */ | |
22 | HVCPUID_VERSION = 0x40000002, | |
23 | HVCPUID_FEATURES = 0x40000003, | |
24 | HVCPUID_ENLIGHTENMENT_INFO = 0x40000004, | |
25 | HVCPUID_IMPLEMENTATION_LIMITS = 0x40000005, | |
26 | }; | |
27 | ||
e08cae41 PA |
28 | struct ms_hyperv_info { |
29 | u32 features; | |
cc2dd402 | 30 | u32 misc_features; |
e08cae41 PA |
31 | u32 hints; |
32 | }; | |
33 | ||
34 | extern struct ms_hyperv_info ms_hyperv; | |
a2a47c6c | 35 | |
2b032f0c S |
36 | /* |
37 | * Declare the MSR used to setup pages used to communicate with the hypervisor. | |
38 | */ | |
39 | union hv_x64_msr_hypercall_contents { | |
40 | u64 as_uint64; | |
41 | struct { | |
42 | u64 enable:1; | |
43 | u64 reserved:11; | |
44 | u64 guest_physical_address:52; | |
45 | }; | |
46 | }; | |
47 | ||
abcafcc6 S |
48 | /* |
49 | * TSC page layout. | |
50 | */ | |
51 | ||
52 | struct ms_hyperv_tsc_page { | |
53 | volatile u32 tsc_sequence; | |
54 | u32 reserved1; | |
55 | volatile u64 tsc_scale; | |
56 | volatile s64 tsc_offset; | |
57 | u64 reserved2[509]; | |
58 | }; | |
59 | ||
0bec7965 S |
60 | /* |
61 | * The guest OS needs to register the guest ID with the hypervisor. | |
62 | * The guest ID is a 64 bit entity and the structure of this ID is | |
63 | * specified in the Hyper-V specification: | |
64 | * | |
65 | * msdn.microsoft.com/en-us/library/windows/hardware/ff542653%28v=vs.85%29.aspx | |
66 | * | |
67 | * While the current guideline does not specify how Linux guest ID(s) | |
68 | * need to be generated, our plan is to publish the guidelines for | |
69 | * Linux and other guest operating systems that currently are hosted | |
70 | * on Hyper-V. The implementation here conforms to this yet | |
71 | * unpublished guidelines. | |
72 | * | |
73 | * | |
74 | * Bit(s) | |
75 | * 63 - Indicates if the OS is Open Source or not; 1 is Open Source | |
76 | * 62:56 - Os Type; Linux is 0x100 | |
77 | * 55:48 - Distro specific identification | |
78 | * 47:16 - Linux kernel version number | |
79 | * 15:0 - Distro specific identification | |
80 | * | |
81 | * | |
82 | */ | |
83 | ||
21717645 | 84 | #define HV_LINUX_VENDOR_ID 0x8100 |
0bec7965 S |
85 | |
86 | /* | |
87 | * Generate the guest ID based on the guideline described above. | |
88 | */ | |
89 | ||
90 | static inline __u64 generate_guest_id(__u64 d_info1, __u64 kernel_version, | |
91 | __u64 d_info2) | |
92 | { | |
93 | __u64 guest_id = 0; | |
94 | ||
21717645 | 95 | guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48); |
0bec7965 S |
96 | guest_id |= (d_info1 << 48); |
97 | guest_id |= (kernel_version << 16); | |
98 | guest_id |= d_info2; | |
99 | ||
100 | return guest_id; | |
101 | } | |
102 | ||
1121f302 S |
103 | |
104 | /* Free the message slot and signal end-of-message if required */ | |
105 | static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) | |
106 | { | |
107 | /* | |
108 | * On crash we're reading some other CPU's message page and we need | |
109 | * to be careful: this other CPU may already had cleared the header | |
110 | * and the host may already had delivered some other message there. | |
111 | * In case we blindly write msg->header.message_type we're going | |
112 | * to lose it. We can still lose a message of the same type but | |
113 | * we count on the fact that there can only be one | |
114 | * CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages | |
115 | * on crash. | |
116 | */ | |
117 | if (cmpxchg(&msg->header.message_type, old_msg_type, | |
118 | HVMSG_NONE) != old_msg_type) | |
119 | return; | |
120 | ||
121 | /* | |
122 | * Make sure the write to MessageType (ie set to | |
123 | * HVMSG_NONE) happens before we read the | |
124 | * MessagePending and EOMing. Otherwise, the EOMing | |
125 | * will not deliver any more messages since there is | |
126 | * no empty slot | |
127 | */ | |
128 | mb(); | |
129 | ||
130 | if (msg->header.message_flags.msg_pending) { | |
131 | /* | |
132 | * This will cause message queue rescan to | |
133 | * possibly deliver another msg from the | |
134 | * hypervisor | |
135 | */ | |
136 | wrmsrl(HV_X64_MSR_EOM, 0); | |
137 | } | |
138 | } | |
139 | ||
72329152 S |
140 | #define hv_get_current_tick(tick) rdmsrl(HV_X64_MSR_TIME_REF_COUNT, tick) |
141 | #define hv_init_timer(timer, tick) wrmsrl(timer, tick) | |
142 | #define hv_init_timer_config(config, val) wrmsrl(config, val) | |
143 | ||
a62c7499 S |
144 | #define hv_get_simp(val) rdmsrl(HV_X64_MSR_SIMP, val) |
145 | #define hv_set_simp(val) wrmsrl(HV_X64_MSR_SIMP, val) | |
146 | ||
4a14dadd S |
147 | #define hv_get_siefp(val) rdmsrl(HV_X64_MSR_SIEFP, val) |
148 | #define hv_set_siefp(val) wrmsrl(HV_X64_MSR_SIEFP, val) | |
149 | ||
cd0142ec S |
150 | #define hv_get_synic_state(val) rdmsrl(HV_X64_MSR_SCONTROL, val) |
151 | #define hv_set_synic_state(val) wrmsrl(HV_X64_MSR_SCONTROL, val) | |
152 | ||
041fcba2 S |
153 | #define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index) |
154 | ||
117f8ab2 S |
155 | #define hv_get_synint_state(int_num, val) rdmsrl(int_num, val) |
156 | #define hv_set_synint_state(int_num, val) wrmsrl(int_num, val) | |
157 | ||
bc2b0331 | 158 | void hyperv_callback_vector(void); |
cf910e83 SA |
159 | #ifdef CONFIG_TRACING |
160 | #define trace_hyperv_callback_vector hyperv_callback_vector | |
161 | #endif | |
bc2b0331 | 162 | void hyperv_vector_handler(struct pt_regs *regs); |
76d388cd TG |
163 | void hv_setup_vmbus_irq(void (*handler)(void)); |
164 | void hv_remove_vmbus_irq(void); | |
bc2b0331 | 165 | |
2517281d VK |
166 | void hv_setup_kexec_handler(void (*handler)(void)); |
167 | void hv_remove_kexec_handler(void); | |
b4370df2 VK |
168 | void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); |
169 | void hv_remove_crash_handler(void); | |
b1d6b256 S |
170 | |
171 | #if IS_ENABLED(CONFIG_HYPERV) | |
43fb06ce VK |
172 | extern struct clocksource *hyperv_cs; |
173 | ||
b1d6b256 | 174 | void hyperv_init(void); |
2c1f68a9 | 175 | void hyperv_report_panic(struct pt_regs *regs); |
c4398016 | 176 | bool hv_is_hypercall_page_setup(void); |
27a01f1e | 177 | void hyperv_cleanup(void); |
b1d6b256 | 178 | #endif |
a2a47c6c | 179 | #endif |