1e08cae41SH. Peter Anvin #ifndef _ASM_X86_MSHYPER_H 2e08cae41SH. Peter Anvin #define _ASM_X86_MSHYPER_H 3a2a47c6cSKy Srinivasan 4e08cae41SH. Peter Anvin #include <linux/types.h> 526fcd952SThomas Gleixner #include <linux/atomic.h> 6e08cae41SH. Peter Anvin #include <asm/hyperv.h> 7e08cae41SH. Peter Anvin 88de8af7eSK. Y. Srinivasan /* 98de8af7eSK. Y. Srinivasan * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent 108de8af7eSK. Y. Srinivasan * is set by CPUID(HVCPUID_VERSION_FEATURES). 118de8af7eSK. Y. Srinivasan */ 128de8af7eSK. Y. Srinivasan enum hv_cpuid_function { 138de8af7eSK. Y. Srinivasan HVCPUID_VERSION_FEATURES = 0x00000001, 148de8af7eSK. Y. Srinivasan HVCPUID_VENDOR_MAXFUNCTION = 0x40000000, 158de8af7eSK. Y. Srinivasan HVCPUID_INTERFACE = 0x40000001, 168de8af7eSK. Y. Srinivasan 178de8af7eSK. Y. Srinivasan /* 188de8af7eSK. Y. Srinivasan * The remaining functions depend on the value of 198de8af7eSK. Y. Srinivasan * HVCPUID_INTERFACE 208de8af7eSK. Y. Srinivasan */ 218de8af7eSK. Y. Srinivasan HVCPUID_VERSION = 0x40000002, 228de8af7eSK. Y. Srinivasan HVCPUID_FEATURES = 0x40000003, 238de8af7eSK. Y. Srinivasan HVCPUID_ENLIGHTENMENT_INFO = 0x40000004, 248de8af7eSK. Y. Srinivasan HVCPUID_IMPLEMENTATION_LIMITS = 0x40000005, 258de8af7eSK. Y. Srinivasan }; 268de8af7eSK. Y. Srinivasan 27e08cae41SH. Peter Anvin struct ms_hyperv_info { 28e08cae41SH. Peter Anvin u32 features; 29cc2dd402SDenis V. Lunev u32 misc_features; 30e08cae41SH. Peter Anvin u32 hints; 31e08cae41SH. Peter Anvin }; 32e08cae41SH. Peter Anvin 33e08cae41SH. Peter Anvin extern struct ms_hyperv_info ms_hyperv; 34a2a47c6cSKy Srinivasan 353f646ed7SK. Y. Srinivasan /* 363f646ed7SK. Y. Srinivasan * Declare the MSR used to setup pages used to communicate with the hypervisor. 373f646ed7SK. Y. Srinivasan */ 383f646ed7SK. Y. Srinivasan union hv_x64_msr_hypercall_contents { 393f646ed7SK. Y. Srinivasan u64 as_uint64; 403f646ed7SK. Y. Srinivasan struct { 413f646ed7SK. Y. Srinivasan u64 enable:1; 423f646ed7SK. Y. Srinivasan u64 reserved:11; 433f646ed7SK. Y. Srinivasan u64 guest_physical_address:52; 443f646ed7SK. Y. Srinivasan }; 453f646ed7SK. Y. Srinivasan }; 463f646ed7SK. Y. Srinivasan 47352c9624SK. Y. Srinivasan /* 4863ed4e0cSK. Y. Srinivasan * TSC page layout. 4963ed4e0cSK. Y. Srinivasan */ 5063ed4e0cSK. Y. Srinivasan 5163ed4e0cSK. Y. Srinivasan struct ms_hyperv_tsc_page { 5263ed4e0cSK. Y. Srinivasan volatile u32 tsc_sequence; 5363ed4e0cSK. Y. Srinivasan u32 reserved1; 5463ed4e0cSK. Y. Srinivasan volatile u64 tsc_scale; 5563ed4e0cSK. Y. Srinivasan volatile s64 tsc_offset; 5663ed4e0cSK. Y. Srinivasan u64 reserved2[509]; 5763ed4e0cSK. Y. Srinivasan }; 5863ed4e0cSK. Y. Srinivasan 5963ed4e0cSK. Y. Srinivasan /* 60352c9624SK. Y. Srinivasan * The guest OS needs to register the guest ID with the hypervisor. 61352c9624SK. Y. Srinivasan * The guest ID is a 64 bit entity and the structure of this ID is 62352c9624SK. Y. Srinivasan * specified in the Hyper-V specification: 63352c9624SK. Y. Srinivasan * 64352c9624SK. Y. Srinivasan * msdn.microsoft.com/en-us/library/windows/hardware/ff542653%28v=vs.85%29.aspx 65352c9624SK. Y. Srinivasan * 66352c9624SK. Y. Srinivasan * While the current guideline does not specify how Linux guest ID(s) 67352c9624SK. Y. Srinivasan * need to be generated, our plan is to publish the guidelines for 68352c9624SK. Y. Srinivasan * Linux and other guest operating systems that currently are hosted 69352c9624SK. Y. Srinivasan * on Hyper-V. The implementation here conforms to this yet 70352c9624SK. Y. Srinivasan * unpublished guidelines. 71352c9624SK. Y. Srinivasan * 72352c9624SK. Y. Srinivasan * 73352c9624SK. Y. Srinivasan * Bit(s) 74352c9624SK. Y. Srinivasan * 63 - Indicates if the OS is Open Source or not; 1 is Open Source 75352c9624SK. Y. Srinivasan * 62:56 - Os Type; Linux is 0x100 76352c9624SK. Y. Srinivasan * 55:48 - Distro specific identification 77352c9624SK. Y. Srinivasan * 47:16 - Linux kernel version number 78352c9624SK. Y. Srinivasan * 15:0 - Distro specific identification 79352c9624SK. Y. Srinivasan * 80352c9624SK. Y. Srinivasan * 81352c9624SK. Y. Srinivasan */ 82352c9624SK. Y. Srinivasan 839b06e101SK. Y. Srinivasan #define HV_LINUX_VENDOR_ID 0x8100 84352c9624SK. Y. Srinivasan 85352c9624SK. Y. Srinivasan /* 86352c9624SK. Y. Srinivasan * Generate the guest ID based on the guideline described above. 87352c9624SK. Y. Srinivasan */ 88352c9624SK. Y. Srinivasan 89352c9624SK. Y. Srinivasan static inline __u64 generate_guest_id(__u64 d_info1, __u64 kernel_version, 90352c9624SK. Y. Srinivasan __u64 d_info2) 91352c9624SK. Y. Srinivasan { 92352c9624SK. Y. Srinivasan __u64 guest_id = 0; 93352c9624SK. Y. Srinivasan 949b06e101SK. Y. Srinivasan guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48); 95352c9624SK. Y. Srinivasan guest_id |= (d_info1 << 48); 96352c9624SK. Y. Srinivasan guest_id |= (kernel_version << 16); 97352c9624SK. Y. Srinivasan guest_id |= d_info2; 98352c9624SK. Y. Srinivasan 99352c9624SK. Y. Srinivasan return guest_id; 100352c9624SK. Y. Srinivasan } 101352c9624SK. Y. Srinivasan 102e810e48cSK. Y. Srinivasan 103e810e48cSK. Y. Srinivasan /* Free the message slot and signal end-of-message if required */ 104e810e48cSK. Y. Srinivasan static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) 105e810e48cSK. Y. Srinivasan { 106e810e48cSK. Y. Srinivasan /* 107e810e48cSK. Y. Srinivasan * On crash we're reading some other CPU's message page and we need 108e810e48cSK. Y. Srinivasan * to be careful: this other CPU may already had cleared the header 109e810e48cSK. Y. Srinivasan * and the host may already had delivered some other message there. 110e810e48cSK. Y. Srinivasan * In case we blindly write msg->header.message_type we're going 111e810e48cSK. Y. Srinivasan * to lose it. We can still lose a message of the same type but 112e810e48cSK. Y. Srinivasan * we count on the fact that there can only be one 113e810e48cSK. Y. Srinivasan * CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages 114e810e48cSK. Y. Srinivasan * on crash. 115e810e48cSK. Y. Srinivasan */ 116e810e48cSK. Y. Srinivasan if (cmpxchg(&msg->header.message_type, old_msg_type, 117e810e48cSK. Y. Srinivasan HVMSG_NONE) != old_msg_type) 118e810e48cSK. Y. Srinivasan return; 119e810e48cSK. Y. Srinivasan 120e810e48cSK. Y. Srinivasan /* 121e810e48cSK. Y. Srinivasan * Make sure the write to MessageType (ie set to 122e810e48cSK. Y. Srinivasan * HVMSG_NONE) happens before we read the 123e810e48cSK. Y. Srinivasan * MessagePending and EOMing. Otherwise, the EOMing 124e810e48cSK. Y. Srinivasan * will not deliver any more messages since there is 125e810e48cSK. Y. Srinivasan * no empty slot 126e810e48cSK. Y. Srinivasan */ 127e810e48cSK. Y. Srinivasan mb(); 128e810e48cSK. Y. Srinivasan 129e810e48cSK. Y. Srinivasan if (msg->header.message_flags.msg_pending) { 130e810e48cSK. Y. Srinivasan /* 131e810e48cSK. Y. Srinivasan * This will cause message queue rescan to 132e810e48cSK. Y. Srinivasan * possibly deliver another msg from the 133e810e48cSK. Y. Srinivasan * hypervisor 134e810e48cSK. Y. Srinivasan */ 135e810e48cSK. Y. Srinivasan wrmsrl(HV_X64_MSR_EOM, 0); 136e810e48cSK. Y. Srinivasan } 137e810e48cSK. Y. Srinivasan } 138e810e48cSK. Y. Srinivasan 139d5116b40SK. Y. Srinivasan #define hv_init_timer(timer, tick) wrmsrl(timer, tick) 140d5116b40SK. Y. Srinivasan #define hv_init_timer_config(config, val) wrmsrl(config, val) 141d5116b40SK. Y. Srinivasan 142155e4a2fSK. Y. Srinivasan #define hv_get_simp(val) rdmsrl(HV_X64_MSR_SIMP, val) 143155e4a2fSK. Y. Srinivasan #define hv_set_simp(val) wrmsrl(HV_X64_MSR_SIMP, val) 144155e4a2fSK. Y. Srinivasan 1458e307bf8SK. Y. Srinivasan #define hv_get_siefp(val) rdmsrl(HV_X64_MSR_SIEFP, val) 1468e307bf8SK. Y. Srinivasan #define hv_set_siefp(val) wrmsrl(HV_X64_MSR_SIEFP, val) 1478e307bf8SK. Y. Srinivasan 14806d1d98aSK. Y. Srinivasan #define hv_get_synic_state(val) rdmsrl(HV_X64_MSR_SCONTROL, val) 14906d1d98aSK. Y. Srinivasan #define hv_set_synic_state(val) wrmsrl(HV_X64_MSR_SCONTROL, val) 15006d1d98aSK. Y. Srinivasan 1517297ff0cSK. Y. Srinivasan #define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index) 1527297ff0cSK. Y. Srinivasan 15337e11d5cSK. Y. Srinivasan #define hv_get_synint_state(int_num, val) rdmsrl(int_num, val) 15437e11d5cSK. Y. Srinivasan #define hv_set_synint_state(int_num, val) wrmsrl(int_num, val) 15537e11d5cSK. Y. Srinivasan 156bc2b0331SK. Y. Srinivasan void hyperv_callback_vector(void); 157cf910e83SSeiji Aguchi #ifdef CONFIG_TRACING 158cf910e83SSeiji Aguchi #define trace_hyperv_callback_vector hyperv_callback_vector 159cf910e83SSeiji Aguchi #endif 160bc2b0331SK. Y. Srinivasan void hyperv_vector_handler(struct pt_regs *regs); 16176d388cdSThomas Gleixner void hv_setup_vmbus_irq(void (*handler)(void)); 16276d388cdSThomas Gleixner void hv_remove_vmbus_irq(void); 163bc2b0331SK. Y. Srinivasan 1642517281dSVitaly Kuznetsov void hv_setup_kexec_handler(void (*handler)(void)); 1652517281dSVitaly Kuznetsov void hv_remove_kexec_handler(void); 166b4370df2SVitaly Kuznetsov void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); 167b4370df2SVitaly Kuznetsov void hv_remove_crash_handler(void); 1688730046cSK. Y. Srinivasan 1698730046cSK. Y. Srinivasan #if IS_ENABLED(CONFIG_HYPERV) 170dee863b5SVitaly Kuznetsov extern struct clocksource *hyperv_cs; 171dee863b5SVitaly Kuznetsov 1728730046cSK. Y. Srinivasan void hyperv_init(void); 173d058fa7eSK. Y. Srinivasan void hyperv_report_panic(struct pt_regs *regs); 17473638cddSK. Y. Srinivasan bool hv_is_hypercall_page_setup(void); 175d6f3609dSVitaly Kuznetsov void hyperv_cleanup(void); 176*79cadff2SVitaly Kuznetsov #else /* CONFIG_HYPERV */ 177*79cadff2SVitaly Kuznetsov static inline void hyperv_init(void) {} 178*79cadff2SVitaly Kuznetsov static inline bool hv_is_hypercall_page_setup(void) { return false; } 179*79cadff2SVitaly Kuznetsov static inline void hyperv_cleanup(void) {} 180*79cadff2SVitaly Kuznetsov #endif /* CONFIG_HYPERV */ 181*79cadff2SVitaly Kuznetsov 182bd2a9adaSVitaly Kuznetsov #ifdef CONFIG_HYPERV_TSCPAGE 183bd2a9adaSVitaly Kuznetsov struct ms_hyperv_tsc_page *hv_get_tsc_page(void); 1840733379bSVitaly Kuznetsov static inline u64 hv_read_tsc_page(const struct ms_hyperv_tsc_page *tsc_pg) 1850733379bSVitaly Kuznetsov { 1860733379bSVitaly Kuznetsov u64 scale, offset, cur_tsc; 1870733379bSVitaly Kuznetsov u32 sequence; 1880733379bSVitaly Kuznetsov 1890733379bSVitaly Kuznetsov /* 1900733379bSVitaly Kuznetsov * The protocol for reading Hyper-V TSC page is specified in Hypervisor 1910733379bSVitaly Kuznetsov * Top-Level Functional Specification ver. 3.0 and above. To get the 1920733379bSVitaly Kuznetsov * reference time we must do the following: 1930733379bSVitaly Kuznetsov * - READ ReferenceTscSequence 1940733379bSVitaly Kuznetsov * A special '0' value indicates the time source is unreliable and we 1950733379bSVitaly Kuznetsov * need to use something else. The currently published specification 1960733379bSVitaly Kuznetsov * versions (up to 4.0b) contain a mistake and wrongly claim '-1' 1970733379bSVitaly Kuznetsov * instead of '0' as the special value, see commit c35b82ef0294. 1980733379bSVitaly Kuznetsov * - ReferenceTime = 1990733379bSVitaly Kuznetsov * ((RDTSC() * ReferenceTscScale) >> 64) + ReferenceTscOffset 2000733379bSVitaly Kuznetsov * - READ ReferenceTscSequence again. In case its value has changed 2010733379bSVitaly Kuznetsov * since our first reading we need to discard ReferenceTime and repeat 2020733379bSVitaly Kuznetsov * the whole sequence as the hypervisor was updating the page in 2030733379bSVitaly Kuznetsov * between. 2040733379bSVitaly Kuznetsov */ 2050733379bSVitaly Kuznetsov do { 2060733379bSVitaly Kuznetsov sequence = READ_ONCE(tsc_pg->tsc_sequence); 2070733379bSVitaly Kuznetsov if (!sequence) 2080733379bSVitaly Kuznetsov return U64_MAX; 2090733379bSVitaly Kuznetsov /* 2100733379bSVitaly Kuznetsov * Make sure we read sequence before we read other values from 2110733379bSVitaly Kuznetsov * TSC page. 2120733379bSVitaly Kuznetsov */ 2130733379bSVitaly Kuznetsov smp_rmb(); 2140733379bSVitaly Kuznetsov 2150733379bSVitaly Kuznetsov scale = READ_ONCE(tsc_pg->tsc_scale); 2160733379bSVitaly Kuznetsov offset = READ_ONCE(tsc_pg->tsc_offset); 2170733379bSVitaly Kuznetsov cur_tsc = rdtsc_ordered(); 2180733379bSVitaly Kuznetsov 2190733379bSVitaly Kuznetsov /* 2200733379bSVitaly Kuznetsov * Make sure we read sequence after we read all other values 2210733379bSVitaly Kuznetsov * from TSC page. 2220733379bSVitaly Kuznetsov */ 2230733379bSVitaly Kuznetsov smp_rmb(); 2240733379bSVitaly Kuznetsov 2250733379bSVitaly Kuznetsov } while (READ_ONCE(tsc_pg->tsc_sequence) != sequence); 2260733379bSVitaly Kuznetsov 2270733379bSVitaly Kuznetsov return mul_u64_u64_shr(cur_tsc, scale, 64) + offset; 2280733379bSVitaly Kuznetsov } 2290733379bSVitaly Kuznetsov 230bd2a9adaSVitaly Kuznetsov #else 231bd2a9adaSVitaly Kuznetsov static inline struct ms_hyperv_tsc_page *hv_get_tsc_page(void) 232bd2a9adaSVitaly Kuznetsov { 233bd2a9adaSVitaly Kuznetsov return NULL; 234bd2a9adaSVitaly Kuznetsov } 235bd2a9adaSVitaly Kuznetsov #endif 236a2a47c6cSKy Srinivasan #endif 237