root/arch/x86/include/asm/mshyperv.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. hv_enable_stimer0_percpu_irq
  2. hv_disable_stimer0_percpu_irq
  3. hv_do_hypercall
  4. hv_do_fast_hypercall8
  5. hv_do_fast_hypercall16
  6. hv_do_rep_hypercall
  7. hv_get_vp_assist_page
  8. hv_apic_init
  9. hyperv_init
  10. hyperv_setup_mmu_ops
  11. hv_alloc_hyperv_page
  12. hv_free_hyperv_page
  13. set_hv_tscchange_cb
  14. clear_hv_tscchange_cb
  15. hyperv_stop_tsc_emulation
  16. hv_get_vp_assist_page
  17. hyperv_flush_guest_mapping
  18. hyperv_flush_guest_mapping_range

   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 #ifndef _ASM_X86_MSHYPER_H
   3 #define _ASM_X86_MSHYPER_H
   4 
   5 #include <linux/types.h>
   6 #include <linux/nmi.h>
   7 #include <asm/io.h>
   8 #include <asm/hyperv-tlfs.h>
   9 #include <asm/nospec-branch.h>
  10 
  11 typedef int (*hyperv_fill_flush_list_func)(
  12                 struct hv_guest_mapping_flush_list *flush,
  13                 void *data);
  14 
  15 #define hv_init_timer(timer, tick) \
  16         wrmsrl(HV_X64_MSR_STIMER0_COUNT + (2*timer), tick)
  17 #define hv_init_timer_config(timer, val) \
  18         wrmsrl(HV_X64_MSR_STIMER0_CONFIG + (2*timer), val)
  19 
  20 #define hv_get_simp(val) rdmsrl(HV_X64_MSR_SIMP, val)
  21 #define hv_set_simp(val) wrmsrl(HV_X64_MSR_SIMP, val)
  22 
  23 #define hv_get_siefp(val) rdmsrl(HV_X64_MSR_SIEFP, val)
  24 #define hv_set_siefp(val) wrmsrl(HV_X64_MSR_SIEFP, val)
  25 
  26 #define hv_get_synic_state(val) rdmsrl(HV_X64_MSR_SCONTROL, val)
  27 #define hv_set_synic_state(val) wrmsrl(HV_X64_MSR_SCONTROL, val)
  28 
  29 #define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index)
  30 
  31 #define hv_signal_eom() wrmsrl(HV_X64_MSR_EOM, 0)
  32 
  33 #define hv_get_synint_state(int_num, val) \
  34         rdmsrl(HV_X64_MSR_SINT0 + int_num, val)
  35 #define hv_set_synint_state(int_num, val) \
  36         wrmsrl(HV_X64_MSR_SINT0 + int_num, val)
  37 
  38 #define hv_get_crash_ctl(val) \
  39         rdmsrl(HV_X64_MSR_CRASH_CTL, val)
  40 
  41 #define hv_get_time_ref_count(val) \
  42         rdmsrl(HV_X64_MSR_TIME_REF_COUNT, val)
  43 
  44 #define hv_get_reference_tsc(val) \
  45         rdmsrl(HV_X64_MSR_REFERENCE_TSC, val)
  46 #define hv_set_reference_tsc(val) \
  47         wrmsrl(HV_X64_MSR_REFERENCE_TSC, val)
  48 #define hv_set_clocksource_vdso(val) \
  49         ((val).archdata.vclock_mode = VCLOCK_HVCLOCK)
  50 #define hv_get_raw_timer() rdtsc_ordered()
  51 
  52 void hyperv_callback_vector(void);
  53 void hyperv_reenlightenment_vector(void);
  54 #ifdef CONFIG_TRACING
  55 #define trace_hyperv_callback_vector hyperv_callback_vector
  56 #endif
  57 void hyperv_vector_handler(struct pt_regs *regs);
  58 
  59 /*
  60  * Routines for stimer0 Direct Mode handling.
  61  * On x86/x64, there are no percpu actions to take.
  62  */
  63 void hv_stimer0_vector_handler(struct pt_regs *regs);
  64 void hv_stimer0_callback_vector(void);
  65 
  66 static inline void hv_enable_stimer0_percpu_irq(int irq) {}
  67 static inline void hv_disable_stimer0_percpu_irq(int irq) {}
  68 
  69 
  70 #if IS_ENABLED(CONFIG_HYPERV)
  71 extern void *hv_hypercall_pg;
  72 extern void  __percpu  **hyperv_pcpu_input_arg;
  73 
  74 static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
  75 {
  76         u64 input_address = input ? virt_to_phys(input) : 0;
  77         u64 output_address = output ? virt_to_phys(output) : 0;
  78         u64 hv_status;
  79 
  80 #ifdef CONFIG_X86_64
  81         if (!hv_hypercall_pg)
  82                 return U64_MAX;
  83 
  84         __asm__ __volatile__("mov %4, %%r8\n"
  85                              CALL_NOSPEC
  86                              : "=a" (hv_status), ASM_CALL_CONSTRAINT,
  87                                "+c" (control), "+d" (input_address)
  88                              :  "r" (output_address),
  89                                 THUNK_TARGET(hv_hypercall_pg)
  90                              : "cc", "memory", "r8", "r9", "r10", "r11");
  91 #else
  92         u32 input_address_hi = upper_32_bits(input_address);
  93         u32 input_address_lo = lower_32_bits(input_address);
  94         u32 output_address_hi = upper_32_bits(output_address);
  95         u32 output_address_lo = lower_32_bits(output_address);
  96 
  97         if (!hv_hypercall_pg)
  98                 return U64_MAX;
  99 
 100         __asm__ __volatile__(CALL_NOSPEC
 101                              : "=A" (hv_status),
 102                                "+c" (input_address_lo), ASM_CALL_CONSTRAINT
 103                              : "A" (control),
 104                                "b" (input_address_hi),
 105                                "D"(output_address_hi), "S"(output_address_lo),
 106                                THUNK_TARGET(hv_hypercall_pg)
 107                              : "cc", "memory");
 108 #endif /* !x86_64 */
 109         return hv_status;
 110 }
 111 
 112 /* Fast hypercall with 8 bytes of input and no output */
 113 static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
 114 {
 115         u64 hv_status, control = (u64)code | HV_HYPERCALL_FAST_BIT;
 116 
 117 #ifdef CONFIG_X86_64
 118         {
 119                 __asm__ __volatile__(CALL_NOSPEC
 120                                      : "=a" (hv_status), ASM_CALL_CONSTRAINT,
 121                                        "+c" (control), "+d" (input1)
 122                                      : THUNK_TARGET(hv_hypercall_pg)
 123                                      : "cc", "r8", "r9", "r10", "r11");
 124         }
 125 #else
 126         {
 127                 u32 input1_hi = upper_32_bits(input1);
 128                 u32 input1_lo = lower_32_bits(input1);
 129 
 130                 __asm__ __volatile__ (CALL_NOSPEC
 131                                       : "=A"(hv_status),
 132                                         "+c"(input1_lo),
 133                                         ASM_CALL_CONSTRAINT
 134                                       : "A" (control),
 135                                         "b" (input1_hi),
 136                                         THUNK_TARGET(hv_hypercall_pg)
 137                                       : "cc", "edi", "esi");
 138         }
 139 #endif
 140                 return hv_status;
 141 }
 142 
 143 /* Fast hypercall with 16 bytes of input */
 144 static inline u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
 145 {
 146         u64 hv_status, control = (u64)code | HV_HYPERCALL_FAST_BIT;
 147 
 148 #ifdef CONFIG_X86_64
 149         {
 150                 __asm__ __volatile__("mov %4, %%r8\n"
 151                                      CALL_NOSPEC
 152                                      : "=a" (hv_status), ASM_CALL_CONSTRAINT,
 153                                        "+c" (control), "+d" (input1)
 154                                      : "r" (input2),
 155                                        THUNK_TARGET(hv_hypercall_pg)
 156                                      : "cc", "r8", "r9", "r10", "r11");
 157         }
 158 #else
 159         {
 160                 u32 input1_hi = upper_32_bits(input1);
 161                 u32 input1_lo = lower_32_bits(input1);
 162                 u32 input2_hi = upper_32_bits(input2);
 163                 u32 input2_lo = lower_32_bits(input2);
 164 
 165                 __asm__ __volatile__ (CALL_NOSPEC
 166                                       : "=A"(hv_status),
 167                                         "+c"(input1_lo), ASM_CALL_CONSTRAINT
 168                                       : "A" (control), "b" (input1_hi),
 169                                         "D"(input2_hi), "S"(input2_lo),
 170                                         THUNK_TARGET(hv_hypercall_pg)
 171                                       : "cc");
 172         }
 173 #endif
 174         return hv_status;
 175 }
 176 
 177 /*
 178  * Rep hypercalls. Callers of this functions are supposed to ensure that
 179  * rep_count and varhead_size comply with Hyper-V hypercall definition.
 180  */
 181 static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size,
 182                                       void *input, void *output)
 183 {
 184         u64 control = code;
 185         u64 status;
 186         u16 rep_comp;
 187 
 188         control |= (u64)varhead_size << HV_HYPERCALL_VARHEAD_OFFSET;
 189         control |= (u64)rep_count << HV_HYPERCALL_REP_COMP_OFFSET;
 190 
 191         do {
 192                 status = hv_do_hypercall(control, input, output);
 193                 if ((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS)
 194                         return status;
 195 
 196                 /* Bits 32-43 of status have 'Reps completed' data. */
 197                 rep_comp = (status & HV_HYPERCALL_REP_COMP_MASK) >>
 198                         HV_HYPERCALL_REP_COMP_OFFSET;
 199 
 200                 control &= ~HV_HYPERCALL_REP_START_MASK;
 201                 control |= (u64)rep_comp << HV_HYPERCALL_REP_START_OFFSET;
 202 
 203                 touch_nmi_watchdog();
 204         } while (rep_comp < rep_count);
 205 
 206         return status;
 207 }
 208 
 209 extern struct hv_vp_assist_page **hv_vp_assist_page;
 210 
 211 static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
 212 {
 213         if (!hv_vp_assist_page)
 214                 return NULL;
 215 
 216         return hv_vp_assist_page[cpu];
 217 }
 218 
 219 void __init hyperv_init(void);
 220 void hyperv_setup_mmu_ops(void);
 221 void *hv_alloc_hyperv_page(void);
 222 void hv_free_hyperv_page(unsigned long addr);
 223 void hyperv_reenlightenment_intr(struct pt_regs *regs);
 224 void set_hv_tscchange_cb(void (*cb)(void));
 225 void clear_hv_tscchange_cb(void);
 226 void hyperv_stop_tsc_emulation(void);
 227 int hyperv_flush_guest_mapping(u64 as);
 228 int hyperv_flush_guest_mapping_range(u64 as,
 229                 hyperv_fill_flush_list_func fill_func, void *data);
 230 int hyperv_fill_flush_guest_mapping_list(
 231                 struct hv_guest_mapping_flush_list *flush,
 232                 u64 start_gfn, u64 end_gfn);
 233 
 234 #ifdef CONFIG_X86_64
 235 void hv_apic_init(void);
 236 void __init hv_init_spinlocks(void);
 237 bool hv_vcpu_is_preempted(int vcpu);
 238 #else
 239 static inline void hv_apic_init(void) {}
 240 #endif
 241 
 242 #else /* CONFIG_HYPERV */
 243 static inline void hyperv_init(void) {}
 244 static inline void hyperv_setup_mmu_ops(void) {}
 245 static inline void *hv_alloc_hyperv_page(void) { return NULL; }
 246 static inline void hv_free_hyperv_page(unsigned long addr) {}
 247 static inline void set_hv_tscchange_cb(void (*cb)(void)) {}
 248 static inline void clear_hv_tscchange_cb(void) {}
 249 static inline void hyperv_stop_tsc_emulation(void) {};
 250 static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
 251 {
 252         return NULL;
 253 }
 254 static inline int hyperv_flush_guest_mapping(u64 as) { return -1; }
 255 static inline int hyperv_flush_guest_mapping_range(u64 as,
 256                 hyperv_fill_flush_list_func fill_func, void *data)
 257 {
 258         return -1;
 259 }
 260 #endif /* CONFIG_HYPERV */
 261 
 262 
 263 #include <asm-generic/mshyperv.h>
 264 
 265 #endif

/* [<][>][^][v][top][bottom][index][help] */