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> 51aec1696SThomas Gleixner #include <linux/interrupt.h> 6*dee863b5SVitaly Kuznetsov #include <linux/clocksource.h> 7e08cae41SH. Peter Anvin #include <asm/hyperv.h> 8e08cae41SH. Peter Anvin 98de8af7eSK. Y. Srinivasan /* 108de8af7eSK. Y. Srinivasan * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent 118de8af7eSK. Y. Srinivasan * is set by CPUID(HVCPUID_VERSION_FEATURES). 128de8af7eSK. Y. Srinivasan */ 138de8af7eSK. Y. Srinivasan enum hv_cpuid_function { 148de8af7eSK. Y. Srinivasan HVCPUID_VERSION_FEATURES = 0x00000001, 158de8af7eSK. Y. Srinivasan HVCPUID_VENDOR_MAXFUNCTION = 0x40000000, 168de8af7eSK. Y. Srinivasan HVCPUID_INTERFACE = 0x40000001, 178de8af7eSK. Y. Srinivasan 188de8af7eSK. Y. Srinivasan /* 198de8af7eSK. Y. Srinivasan * The remaining functions depend on the value of 208de8af7eSK. Y. Srinivasan * HVCPUID_INTERFACE 218de8af7eSK. Y. Srinivasan */ 228de8af7eSK. Y. Srinivasan HVCPUID_VERSION = 0x40000002, 238de8af7eSK. Y. Srinivasan HVCPUID_FEATURES = 0x40000003, 248de8af7eSK. Y. Srinivasan HVCPUID_ENLIGHTENMENT_INFO = 0x40000004, 258de8af7eSK. Y. Srinivasan HVCPUID_IMPLEMENTATION_LIMITS = 0x40000005, 268de8af7eSK. Y. Srinivasan }; 278de8af7eSK. Y. Srinivasan 28e08cae41SH. Peter Anvin struct ms_hyperv_info { 29e08cae41SH. Peter Anvin u32 features; 30cc2dd402SDenis V. Lunev u32 misc_features; 31e08cae41SH. Peter Anvin u32 hints; 32e08cae41SH. Peter Anvin }; 33e08cae41SH. Peter Anvin 34e08cae41SH. Peter Anvin extern struct ms_hyperv_info ms_hyperv; 35a2a47c6cSKy Srinivasan 363f646ed7SK. Y. Srinivasan /* 373f646ed7SK. Y. Srinivasan * Declare the MSR used to setup pages used to communicate with the hypervisor. 383f646ed7SK. Y. Srinivasan */ 393f646ed7SK. Y. Srinivasan union hv_x64_msr_hypercall_contents { 403f646ed7SK. Y. Srinivasan u64 as_uint64; 413f646ed7SK. Y. Srinivasan struct { 423f646ed7SK. Y. Srinivasan u64 enable:1; 433f646ed7SK. Y. Srinivasan u64 reserved:11; 443f646ed7SK. Y. Srinivasan u64 guest_physical_address:52; 453f646ed7SK. Y. Srinivasan }; 463f646ed7SK. Y. Srinivasan }; 473f646ed7SK. Y. Srinivasan 48352c9624SK. Y. Srinivasan /* 4963ed4e0cSK. Y. Srinivasan * TSC page layout. 5063ed4e0cSK. Y. Srinivasan */ 5163ed4e0cSK. Y. Srinivasan 5263ed4e0cSK. Y. Srinivasan struct ms_hyperv_tsc_page { 5363ed4e0cSK. Y. Srinivasan volatile u32 tsc_sequence; 5463ed4e0cSK. Y. Srinivasan u32 reserved1; 5563ed4e0cSK. Y. Srinivasan volatile u64 tsc_scale; 5663ed4e0cSK. Y. Srinivasan volatile s64 tsc_offset; 5763ed4e0cSK. Y. Srinivasan u64 reserved2[509]; 5863ed4e0cSK. Y. Srinivasan }; 5963ed4e0cSK. Y. Srinivasan 6063ed4e0cSK. Y. Srinivasan /* 61352c9624SK. Y. Srinivasan * The guest OS needs to register the guest ID with the hypervisor. 62352c9624SK. Y. Srinivasan * The guest ID is a 64 bit entity and the structure of this ID is 63352c9624SK. Y. Srinivasan * specified in the Hyper-V specification: 64352c9624SK. Y. Srinivasan * 65352c9624SK. Y. Srinivasan * msdn.microsoft.com/en-us/library/windows/hardware/ff542653%28v=vs.85%29.aspx 66352c9624SK. Y. Srinivasan * 67352c9624SK. Y. Srinivasan * While the current guideline does not specify how Linux guest ID(s) 68352c9624SK. Y. Srinivasan * need to be generated, our plan is to publish the guidelines for 69352c9624SK. Y. Srinivasan * Linux and other guest operating systems that currently are hosted 70352c9624SK. Y. Srinivasan * on Hyper-V. The implementation here conforms to this yet 71352c9624SK. Y. Srinivasan * unpublished guidelines. 72352c9624SK. Y. Srinivasan * 73352c9624SK. Y. Srinivasan * 74352c9624SK. Y. Srinivasan * Bit(s) 75352c9624SK. Y. Srinivasan * 63 - Indicates if the OS is Open Source or not; 1 is Open Source 76352c9624SK. Y. Srinivasan * 62:56 - Os Type; Linux is 0x100 77352c9624SK. Y. Srinivasan * 55:48 - Distro specific identification 78352c9624SK. Y. Srinivasan * 47:16 - Linux kernel version number 79352c9624SK. Y. Srinivasan * 15:0 - Distro specific identification 80352c9624SK. Y. Srinivasan * 81352c9624SK. Y. Srinivasan * 82352c9624SK. Y. Srinivasan */ 83352c9624SK. Y. Srinivasan 849b06e101SK. Y. Srinivasan #define HV_LINUX_VENDOR_ID 0x8100 85352c9624SK. Y. Srinivasan 86352c9624SK. Y. Srinivasan /* 87352c9624SK. Y. Srinivasan * Generate the guest ID based on the guideline described above. 88352c9624SK. Y. Srinivasan */ 89352c9624SK. Y. Srinivasan 90352c9624SK. Y. Srinivasan static inline __u64 generate_guest_id(__u64 d_info1, __u64 kernel_version, 91352c9624SK. Y. Srinivasan __u64 d_info2) 92352c9624SK. Y. Srinivasan { 93352c9624SK. Y. Srinivasan __u64 guest_id = 0; 94352c9624SK. Y. Srinivasan 959b06e101SK. Y. Srinivasan guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48); 96352c9624SK. Y. Srinivasan guest_id |= (d_info1 << 48); 97352c9624SK. Y. Srinivasan guest_id |= (kernel_version << 16); 98352c9624SK. Y. Srinivasan guest_id |= d_info2; 99352c9624SK. Y. Srinivasan 100352c9624SK. Y. Srinivasan return guest_id; 101352c9624SK. Y. Srinivasan } 102352c9624SK. Y. Srinivasan 103e810e48cSK. Y. Srinivasan 104e810e48cSK. Y. Srinivasan /* Free the message slot and signal end-of-message if required */ 105e810e48cSK. Y. Srinivasan static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type) 106e810e48cSK. Y. Srinivasan { 107e810e48cSK. Y. Srinivasan /* 108e810e48cSK. Y. Srinivasan * On crash we're reading some other CPU's message page and we need 109e810e48cSK. Y. Srinivasan * to be careful: this other CPU may already had cleared the header 110e810e48cSK. Y. Srinivasan * and the host may already had delivered some other message there. 111e810e48cSK. Y. Srinivasan * In case we blindly write msg->header.message_type we're going 112e810e48cSK. Y. Srinivasan * to lose it. We can still lose a message of the same type but 113e810e48cSK. Y. Srinivasan * we count on the fact that there can only be one 114e810e48cSK. Y. Srinivasan * CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages 115e810e48cSK. Y. Srinivasan * on crash. 116e810e48cSK. Y. Srinivasan */ 117e810e48cSK. Y. Srinivasan if (cmpxchg(&msg->header.message_type, old_msg_type, 118e810e48cSK. Y. Srinivasan HVMSG_NONE) != old_msg_type) 119e810e48cSK. Y. Srinivasan return; 120e810e48cSK. Y. Srinivasan 121e810e48cSK. Y. Srinivasan /* 122e810e48cSK. Y. Srinivasan * Make sure the write to MessageType (ie set to 123e810e48cSK. Y. Srinivasan * HVMSG_NONE) happens before we read the 124e810e48cSK. Y. Srinivasan * MessagePending and EOMing. Otherwise, the EOMing 125e810e48cSK. Y. Srinivasan * will not deliver any more messages since there is 126e810e48cSK. Y. Srinivasan * no empty slot 127e810e48cSK. Y. Srinivasan */ 128e810e48cSK. Y. Srinivasan mb(); 129e810e48cSK. Y. Srinivasan 130e810e48cSK. Y. Srinivasan if (msg->header.message_flags.msg_pending) { 131e810e48cSK. Y. Srinivasan /* 132e810e48cSK. Y. Srinivasan * This will cause message queue rescan to 133e810e48cSK. Y. Srinivasan * possibly deliver another msg from the 134e810e48cSK. Y. Srinivasan * hypervisor 135e810e48cSK. Y. Srinivasan */ 136e810e48cSK. Y. Srinivasan wrmsrl(HV_X64_MSR_EOM, 0); 137e810e48cSK. Y. Srinivasan } 138e810e48cSK. Y. Srinivasan } 139e810e48cSK. Y. Srinivasan 140d5116b40SK. Y. Srinivasan #define hv_get_current_tick(tick) rdmsrl(HV_X64_MSR_TIME_REF_COUNT, tick) 141d5116b40SK. Y. Srinivasan #define hv_init_timer(timer, tick) wrmsrl(timer, tick) 142d5116b40SK. Y. Srinivasan #define hv_init_timer_config(config, val) wrmsrl(config, val) 143d5116b40SK. Y. Srinivasan 144155e4a2fSK. Y. Srinivasan #define hv_get_simp(val) rdmsrl(HV_X64_MSR_SIMP, val) 145155e4a2fSK. Y. Srinivasan #define hv_set_simp(val) wrmsrl(HV_X64_MSR_SIMP, val) 146155e4a2fSK. Y. Srinivasan 1478e307bf8SK. Y. Srinivasan #define hv_get_siefp(val) rdmsrl(HV_X64_MSR_SIEFP, val) 1488e307bf8SK. Y. Srinivasan #define hv_set_siefp(val) wrmsrl(HV_X64_MSR_SIEFP, val) 1498e307bf8SK. Y. Srinivasan 15006d1d98aSK. Y. Srinivasan #define hv_get_synic_state(val) rdmsrl(HV_X64_MSR_SCONTROL, val) 15106d1d98aSK. Y. Srinivasan #define hv_set_synic_state(val) wrmsrl(HV_X64_MSR_SCONTROL, val) 15206d1d98aSK. Y. Srinivasan 1537297ff0cSK. Y. Srinivasan #define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index) 1547297ff0cSK. Y. Srinivasan 15537e11d5cSK. Y. Srinivasan #define hv_get_synint_state(int_num, val) rdmsrl(int_num, val) 15637e11d5cSK. Y. Srinivasan #define hv_set_synint_state(int_num, val) wrmsrl(int_num, val) 15737e11d5cSK. Y. Srinivasan 158bc2b0331SK. Y. Srinivasan void hyperv_callback_vector(void); 159cf910e83SSeiji Aguchi #ifdef CONFIG_TRACING 160cf910e83SSeiji Aguchi #define trace_hyperv_callback_vector hyperv_callback_vector 161cf910e83SSeiji Aguchi #endif 162bc2b0331SK. Y. Srinivasan void hyperv_vector_handler(struct pt_regs *regs); 16376d388cdSThomas Gleixner void hv_setup_vmbus_irq(void (*handler)(void)); 16476d388cdSThomas Gleixner void hv_remove_vmbus_irq(void); 165bc2b0331SK. Y. Srinivasan 1662517281dSVitaly Kuznetsov void hv_setup_kexec_handler(void (*handler)(void)); 1672517281dSVitaly Kuznetsov void hv_remove_kexec_handler(void); 168b4370df2SVitaly Kuznetsov void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)); 169b4370df2SVitaly Kuznetsov void hv_remove_crash_handler(void); 1708730046cSK. Y. Srinivasan 1718730046cSK. Y. Srinivasan #if IS_ENABLED(CONFIG_HYPERV) 172*dee863b5SVitaly Kuznetsov extern struct clocksource *hyperv_cs; 173*dee863b5SVitaly Kuznetsov 1748730046cSK. Y. Srinivasan void hyperv_init(void); 175d058fa7eSK. Y. Srinivasan void hyperv_report_panic(struct pt_regs *regs); 17673638cddSK. Y. Srinivasan bool hv_is_hypercall_page_setup(void); 177d6f3609dSVitaly Kuznetsov void hyperv_cleanup(void); 1788730046cSK. Y. Srinivasan #endif 179a2a47c6cSKy Srinivasan #endif 180