.. | .. |
---|
3 | 3 | #define _ASM_X86_MSHYPER_H |
---|
4 | 4 | |
---|
5 | 5 | #include <linux/types.h> |
---|
6 | | -#include <linux/atomic.h> |
---|
7 | 6 | #include <linux/nmi.h> |
---|
| 7 | +#include <linux/msi.h> |
---|
8 | 8 | #include <asm/io.h> |
---|
9 | 9 | #include <asm/hyperv-tlfs.h> |
---|
10 | 10 | #include <asm/nospec-branch.h> |
---|
| 11 | +#include <asm/paravirt.h> |
---|
11 | 12 | |
---|
12 | | -#define VP_INVAL U32_MAX |
---|
13 | | - |
---|
14 | | -struct ms_hyperv_info { |
---|
15 | | - u32 features; |
---|
16 | | - u32 misc_features; |
---|
17 | | - u32 hints; |
---|
18 | | - u32 nested_features; |
---|
19 | | - u32 max_vp_index; |
---|
20 | | - u32 max_lp_index; |
---|
21 | | -}; |
---|
22 | | - |
---|
23 | | -extern struct ms_hyperv_info ms_hyperv; |
---|
24 | | - |
---|
25 | | -/* |
---|
26 | | - * Generate the guest ID. |
---|
27 | | - */ |
---|
28 | | - |
---|
29 | | -static inline __u64 generate_guest_id(__u64 d_info1, __u64 kernel_version, |
---|
30 | | - __u64 d_info2) |
---|
31 | | -{ |
---|
32 | | - __u64 guest_id = 0; |
---|
33 | | - |
---|
34 | | - guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48); |
---|
35 | | - guest_id |= (d_info1 << 48); |
---|
36 | | - guest_id |= (kernel_version << 16); |
---|
37 | | - guest_id |= d_info2; |
---|
38 | | - |
---|
39 | | - return guest_id; |
---|
40 | | -} |
---|
41 | | - |
---|
42 | | - |
---|
43 | | -/* Free the message slot and signal end-of-message if required */ |
---|
44 | | -static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) |
---|
45 | | -{ |
---|
46 | | - /* |
---|
47 | | - * On crash we're reading some other CPU's message page and we need |
---|
48 | | - * to be careful: this other CPU may already had cleared the header |
---|
49 | | - * and the host may already had delivered some other message there. |
---|
50 | | - * In case we blindly write msg->header.message_type we're going |
---|
51 | | - * to lose it. We can still lose a message of the same type but |
---|
52 | | - * we count on the fact that there can only be one |
---|
53 | | - * CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages |
---|
54 | | - * on crash. |
---|
55 | | - */ |
---|
56 | | - if (cmpxchg(&msg->header.message_type, old_msg_type, |
---|
57 | | - HVMSG_NONE) != old_msg_type) |
---|
58 | | - return; |
---|
59 | | - |
---|
60 | | - /* |
---|
61 | | - * Make sure the write to MessageType (ie set to |
---|
62 | | - * HVMSG_NONE) happens before we read the |
---|
63 | | - * MessagePending and EOMing. Otherwise, the EOMing |
---|
64 | | - * will not deliver any more messages since there is |
---|
65 | | - * no empty slot |
---|
66 | | - */ |
---|
67 | | - mb(); |
---|
68 | | - |
---|
69 | | - if (msg->header.message_flags.msg_pending) { |
---|
70 | | - /* |
---|
71 | | - * This will cause message queue rescan to |
---|
72 | | - * possibly deliver another msg from the |
---|
73 | | - * hypervisor |
---|
74 | | - */ |
---|
75 | | - wrmsrl(HV_X64_MSR_EOM, 0); |
---|
76 | | - } |
---|
77 | | -} |
---|
| 13 | +typedef int (*hyperv_fill_flush_list_func)( |
---|
| 14 | + struct hv_guest_mapping_flush_list *flush, |
---|
| 15 | + void *data); |
---|
78 | 16 | |
---|
79 | 17 | #define hv_init_timer(timer, tick) \ |
---|
80 | 18 | wrmsrl(HV_X64_MSR_STIMER0_COUNT + (2*timer), tick) |
---|
.. | .. |
---|
92 | 30 | |
---|
93 | 31 | #define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index) |
---|
94 | 32 | |
---|
| 33 | +#define hv_signal_eom() wrmsrl(HV_X64_MSR_EOM, 0) |
---|
| 34 | + |
---|
95 | 35 | #define hv_get_synint_state(int_num, val) \ |
---|
96 | 36 | rdmsrl(HV_X64_MSR_SINT0 + int_num, val) |
---|
97 | 37 | #define hv_set_synint_state(int_num, val) \ |
---|
98 | 38 | wrmsrl(HV_X64_MSR_SINT0 + int_num, val) |
---|
| 39 | +#define hv_recommend_using_aeoi() \ |
---|
| 40 | + (!(ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED)) |
---|
99 | 41 | |
---|
100 | 42 | #define hv_get_crash_ctl(val) \ |
---|
101 | 43 | rdmsrl(HV_X64_MSR_CRASH_CTL, val) |
---|
102 | 44 | |
---|
103 | | -void hyperv_callback_vector(void); |
---|
104 | | -void hyperv_reenlightenment_vector(void); |
---|
105 | | -#ifdef CONFIG_TRACING |
---|
106 | | -#define trace_hyperv_callback_vector hyperv_callback_vector |
---|
107 | | -#endif |
---|
108 | | -void hyperv_vector_handler(struct pt_regs *regs); |
---|
109 | | -void hv_setup_vmbus_irq(void (*handler)(void)); |
---|
110 | | -void hv_remove_vmbus_irq(void); |
---|
| 45 | +#define hv_get_time_ref_count(val) \ |
---|
| 46 | + rdmsrl(HV_X64_MSR_TIME_REF_COUNT, val) |
---|
111 | 47 | |
---|
112 | | -void hv_setup_kexec_handler(void (*handler)(void)); |
---|
113 | | -void hv_remove_kexec_handler(void); |
---|
114 | | -void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); |
---|
115 | | -void hv_remove_crash_handler(void); |
---|
| 48 | +#define hv_get_reference_tsc(val) \ |
---|
| 49 | + rdmsrl(HV_X64_MSR_REFERENCE_TSC, val) |
---|
| 50 | +#define hv_set_reference_tsc(val) \ |
---|
| 51 | + wrmsrl(HV_X64_MSR_REFERENCE_TSC, val) |
---|
| 52 | +#define hv_set_clocksource_vdso(val) \ |
---|
| 53 | + ((val).vdso_clock_mode = VDSO_CLOCKMODE_HVCLOCK) |
---|
| 54 | +#define hv_enable_vdso_clocksource() \ |
---|
| 55 | + vclocks_set_used(VDSO_CLOCKMODE_HVCLOCK); |
---|
| 56 | +#define hv_get_raw_timer() rdtsc_ordered() |
---|
| 57 | +#define hv_get_vector() HYPERVISOR_CALLBACK_VECTOR |
---|
116 | 58 | |
---|
117 | 59 | /* |
---|
118 | | - * Routines for stimer0 Direct Mode handling. |
---|
119 | | - * On x86/x64, there are no percpu actions to take. |
---|
| 60 | + * Reference to pv_ops must be inline so objtool |
---|
| 61 | + * detection of noinstr violations can work correctly. |
---|
120 | 62 | */ |
---|
121 | | -void hv_stimer0_vector_handler(struct pt_regs *regs); |
---|
122 | | -void hv_stimer0_callback_vector(void); |
---|
123 | | -int hv_setup_stimer0_irq(int *irq, int *vector, void (*handler)(void)); |
---|
124 | | -void hv_remove_stimer0_irq(int irq); |
---|
| 63 | +static __always_inline void hv_setup_sched_clock(void *sched_clock) |
---|
| 64 | +{ |
---|
| 65 | +#ifdef CONFIG_PARAVIRT |
---|
| 66 | + pv_ops.time.sched_clock = sched_clock; |
---|
| 67 | +#endif |
---|
| 68 | +} |
---|
| 69 | + |
---|
| 70 | +void hyperv_vector_handler(struct pt_regs *regs); |
---|
125 | 71 | |
---|
126 | 72 | static inline void hv_enable_stimer0_percpu_irq(int irq) {} |
---|
127 | 73 | static inline void hv_disable_stimer0_percpu_irq(int irq) {} |
---|
128 | 74 | |
---|
129 | 75 | |
---|
130 | 76 | #if IS_ENABLED(CONFIG_HYPERV) |
---|
131 | | -extern struct clocksource *hyperv_cs; |
---|
| 77 | +extern int hyperv_init_cpuhp; |
---|
| 78 | + |
---|
132 | 79 | extern void *hv_hypercall_pg; |
---|
133 | 80 | extern void __percpu **hyperv_pcpu_input_arg; |
---|
134 | 81 | |
---|
.. | .. |
---|
232 | 179 | : "cc"); |
---|
233 | 180 | } |
---|
234 | 181 | #endif |
---|
235 | | - return hv_status; |
---|
| 182 | + return hv_status; |
---|
236 | 183 | } |
---|
237 | 184 | |
---|
238 | 185 | /* |
---|
.. | .. |
---|
267 | 214 | return status; |
---|
268 | 215 | } |
---|
269 | 216 | |
---|
270 | | -/* |
---|
271 | | - * Hypervisor's notion of virtual processor ID is different from |
---|
272 | | - * Linux' notion of CPU ID. This information can only be retrieved |
---|
273 | | - * in the context of the calling CPU. Setup a map for easy access |
---|
274 | | - * to this information. |
---|
275 | | - */ |
---|
276 | | -extern u32 *hv_vp_index; |
---|
277 | | -extern u32 hv_max_vp_index; |
---|
278 | 217 | extern struct hv_vp_assist_page **hv_vp_assist_page; |
---|
279 | 218 | |
---|
280 | 219 | static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu) |
---|
.. | .. |
---|
285 | 224 | return hv_vp_assist_page[cpu]; |
---|
286 | 225 | } |
---|
287 | 226 | |
---|
288 | | -/** |
---|
289 | | - * hv_cpu_number_to_vp_number() - Map CPU to VP. |
---|
290 | | - * @cpu_number: CPU number in Linux terms |
---|
291 | | - * |
---|
292 | | - * This function returns the mapping between the Linux processor |
---|
293 | | - * number and the hypervisor's virtual processor number, useful |
---|
294 | | - * in making hypercalls and such that talk about specific |
---|
295 | | - * processors. |
---|
296 | | - * |
---|
297 | | - * Return: Virtual processor number in Hyper-V terms |
---|
298 | | - */ |
---|
299 | | -static inline int hv_cpu_number_to_vp_number(int cpu_number) |
---|
300 | | -{ |
---|
301 | | - return hv_vp_index[cpu_number]; |
---|
302 | | -} |
---|
303 | | - |
---|
304 | | -static inline int cpumask_to_vpset(struct hv_vpset *vpset, |
---|
305 | | - const struct cpumask *cpus) |
---|
306 | | -{ |
---|
307 | | - int cpu, vcpu, vcpu_bank, vcpu_offset, nr_bank = 1; |
---|
308 | | - |
---|
309 | | - /* valid_bank_mask can represent up to 64 banks */ |
---|
310 | | - if (hv_max_vp_index / 64 >= 64) |
---|
311 | | - return 0; |
---|
312 | | - |
---|
313 | | - /* |
---|
314 | | - * Clear all banks up to the maximum possible bank as hv_tlb_flush_ex |
---|
315 | | - * structs are not cleared between calls, we risk flushing unneeded |
---|
316 | | - * vCPUs otherwise. |
---|
317 | | - */ |
---|
318 | | - for (vcpu_bank = 0; vcpu_bank <= hv_max_vp_index / 64; vcpu_bank++) |
---|
319 | | - vpset->bank_contents[vcpu_bank] = 0; |
---|
320 | | - |
---|
321 | | - /* |
---|
322 | | - * Some banks may end up being empty but this is acceptable. |
---|
323 | | - */ |
---|
324 | | - for_each_cpu(cpu, cpus) { |
---|
325 | | - vcpu = hv_cpu_number_to_vp_number(cpu); |
---|
326 | | - if (vcpu == VP_INVAL) |
---|
327 | | - return -1; |
---|
328 | | - vcpu_bank = vcpu / 64; |
---|
329 | | - vcpu_offset = vcpu % 64; |
---|
330 | | - __set_bit(vcpu_offset, (unsigned long *) |
---|
331 | | - &vpset->bank_contents[vcpu_bank]); |
---|
332 | | - if (vcpu_bank >= nr_bank) |
---|
333 | | - nr_bank = vcpu_bank + 1; |
---|
334 | | - } |
---|
335 | | - vpset->valid_bank_mask = GENMASK_ULL(nr_bank - 1, 0); |
---|
336 | | - return nr_bank; |
---|
337 | | -} |
---|
338 | | - |
---|
339 | 227 | void __init hyperv_init(void); |
---|
340 | 228 | void hyperv_setup_mmu_ops(void); |
---|
341 | | -void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die); |
---|
342 | | -void hyperv_report_panic_msg(phys_addr_t pa, size_t size); |
---|
343 | | -bool hv_is_hyperv_initialized(void); |
---|
344 | | -void hyperv_cleanup(void); |
---|
345 | | - |
---|
346 | | -void hyperv_reenlightenment_intr(struct pt_regs *regs); |
---|
| 229 | +void *hv_alloc_hyperv_page(void); |
---|
| 230 | +void *hv_alloc_hyperv_zeroed_page(void); |
---|
| 231 | +void hv_free_hyperv_page(unsigned long addr); |
---|
347 | 232 | void set_hv_tscchange_cb(void (*cb)(void)); |
---|
348 | 233 | void clear_hv_tscchange_cb(void); |
---|
349 | 234 | void hyperv_stop_tsc_emulation(void); |
---|
350 | 235 | int hyperv_flush_guest_mapping(u64 as); |
---|
| 236 | +int hyperv_flush_guest_mapping_range(u64 as, |
---|
| 237 | + hyperv_fill_flush_list_func fill_func, void *data); |
---|
| 238 | +int hyperv_fill_flush_guest_mapping_list( |
---|
| 239 | + struct hv_guest_mapping_flush_list *flush, |
---|
| 240 | + u64 start_gfn, u64 end_gfn); |
---|
351 | 241 | |
---|
352 | 242 | #ifdef CONFIG_X86_64 |
---|
353 | 243 | void hv_apic_init(void); |
---|
| 244 | +void __init hv_init_spinlocks(void); |
---|
| 245 | +bool hv_vcpu_is_preempted(int vcpu); |
---|
354 | 246 | #else |
---|
355 | 247 | static inline void hv_apic_init(void) {} |
---|
356 | 248 | #endif |
---|
357 | 249 | |
---|
358 | 250 | #else /* CONFIG_HYPERV */ |
---|
359 | 251 | static inline void hyperv_init(void) {} |
---|
360 | | -static inline bool hv_is_hyperv_initialized(void) { return false; } |
---|
361 | | -static inline void hyperv_cleanup(void) {} |
---|
362 | 252 | static inline void hyperv_setup_mmu_ops(void) {} |
---|
| 253 | +static inline void *hv_alloc_hyperv_page(void) { return NULL; } |
---|
| 254 | +static inline void hv_free_hyperv_page(unsigned long addr) {} |
---|
363 | 255 | static inline void set_hv_tscchange_cb(void (*cb)(void)) {} |
---|
364 | 256 | static inline void clear_hv_tscchange_cb(void) {} |
---|
365 | 257 | static inline void hyperv_stop_tsc_emulation(void) {}; |
---|
.. | .. |
---|
368 | 260 | return NULL; |
---|
369 | 261 | } |
---|
370 | 262 | static inline int hyperv_flush_guest_mapping(u64 as) { return -1; } |
---|
| 263 | +static inline int hyperv_flush_guest_mapping_range(u64 as, |
---|
| 264 | + hyperv_fill_flush_list_func fill_func, void *data) |
---|
| 265 | +{ |
---|
| 266 | + return -1; |
---|
| 267 | +} |
---|
371 | 268 | #endif /* CONFIG_HYPERV */ |
---|
372 | 269 | |
---|
373 | | -#ifdef CONFIG_HYPERV_TSCPAGE |
---|
374 | | -struct ms_hyperv_tsc_page *hv_get_tsc_page(void); |
---|
375 | | -static inline u64 hv_read_tsc_page_tsc(const struct ms_hyperv_tsc_page *tsc_pg, |
---|
376 | | - u64 *cur_tsc) |
---|
377 | | -{ |
---|
378 | | - u64 scale, offset; |
---|
379 | | - u32 sequence; |
---|
380 | 270 | |
---|
381 | | - /* |
---|
382 | | - * The protocol for reading Hyper-V TSC page is specified in Hypervisor |
---|
383 | | - * Top-Level Functional Specification ver. 3.0 and above. To get the |
---|
384 | | - * reference time we must do the following: |
---|
385 | | - * - READ ReferenceTscSequence |
---|
386 | | - * A special '0' value indicates the time source is unreliable and we |
---|
387 | | - * need to use something else. The currently published specification |
---|
388 | | - * versions (up to 4.0b) contain a mistake and wrongly claim '-1' |
---|
389 | | - * instead of '0' as the special value, see commit c35b82ef0294. |
---|
390 | | - * - ReferenceTime = |
---|
391 | | - * ((RDTSC() * ReferenceTscScale) >> 64) + ReferenceTscOffset |
---|
392 | | - * - READ ReferenceTscSequence again. In case its value has changed |
---|
393 | | - * since our first reading we need to discard ReferenceTime and repeat |
---|
394 | | - * the whole sequence as the hypervisor was updating the page in |
---|
395 | | - * between. |
---|
396 | | - */ |
---|
397 | | - do { |
---|
398 | | - sequence = READ_ONCE(tsc_pg->tsc_sequence); |
---|
399 | | - if (!sequence) |
---|
400 | | - return U64_MAX; |
---|
401 | | - /* |
---|
402 | | - * Make sure we read sequence before we read other values from |
---|
403 | | - * TSC page. |
---|
404 | | - */ |
---|
405 | | - smp_rmb(); |
---|
| 271 | +#include <asm-generic/mshyperv.h> |
---|
406 | 272 | |
---|
407 | | - scale = READ_ONCE(tsc_pg->tsc_scale); |
---|
408 | | - offset = READ_ONCE(tsc_pg->tsc_offset); |
---|
409 | | - *cur_tsc = rdtsc_ordered(); |
---|
410 | | - |
---|
411 | | - /* |
---|
412 | | - * Make sure we read sequence after we read all other values |
---|
413 | | - * from TSC page. |
---|
414 | | - */ |
---|
415 | | - smp_rmb(); |
---|
416 | | - |
---|
417 | | - } while (READ_ONCE(tsc_pg->tsc_sequence) != sequence); |
---|
418 | | - |
---|
419 | | - return mul_u64_u64_shr(*cur_tsc, scale, 64) + offset; |
---|
420 | | -} |
---|
421 | | - |
---|
422 | | -static inline u64 hv_read_tsc_page(const struct ms_hyperv_tsc_page *tsc_pg) |
---|
423 | | -{ |
---|
424 | | - u64 cur_tsc; |
---|
425 | | - |
---|
426 | | - return hv_read_tsc_page_tsc(tsc_pg, &cur_tsc); |
---|
427 | | -} |
---|
428 | | - |
---|
429 | | -#else |
---|
430 | | -static inline struct ms_hyperv_tsc_page *hv_get_tsc_page(void) |
---|
431 | | -{ |
---|
432 | | - return NULL; |
---|
433 | | -} |
---|
434 | | - |
---|
435 | | -static inline u64 hv_read_tsc_page_tsc(const struct ms_hyperv_tsc_page *tsc_pg, |
---|
436 | | - u64 *cur_tsc) |
---|
437 | | -{ |
---|
438 | | - BUG(); |
---|
439 | | - return U64_MAX; |
---|
440 | | -} |
---|
441 | | -#endif |
---|
442 | 273 | #endif |
---|