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 <linux/msi.h> 8 #include <linux/io.h> 9 #include <linux/static_call.h> 10 #include <asm/nospec-branch.h> 11 #include <asm/paravirt.h> 12 #include <asm/msr.h> 13 #include <hyperv/hvhdk.h> 14 15 /* 16 * Hyper-V always provides a single IO-APIC at this MMIO address. 17 * Ideally, the value should be looked up in ACPI tables, but it 18 * is needed for mapping the IO-APIC early in boot on Confidential 19 * VMs, before ACPI functions can be used. 20 */ 21 #define HV_IOAPIC_BASE_ADDRESS 0xfec00000 22 23 #define HV_VTL_NORMAL 0x0 24 #define HV_VTL_SECURE 0x1 25 #define HV_VTL_MGMT 0x2 26 27 union hv_ghcb; 28 29 DECLARE_STATIC_KEY_FALSE(isolation_type_snp); 30 DECLARE_STATIC_KEY_FALSE(isolation_type_tdx); 31 32 typedef int (*hyperv_fill_flush_list_func)( 33 struct hv_guest_mapping_flush_list *flush, 34 void *data); 35 36 void hyperv_vector_handler(struct pt_regs *regs); 37 38 static inline unsigned char hv_get_nmi_reason(void) 39 { 40 return 0; 41 } 42 43 extern u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2); 44 extern u64 hv_snp_hypercall(u64 control, u64 param1, u64 param2); 45 extern u64 hv_std_hypercall(u64 control, u64 param1, u64 param2); 46 47 #if IS_ENABLED(CONFIG_HYPERV) 48 extern void *hv_hypercall_pg; 49 50 extern union hv_ghcb * __percpu *hv_ghcb_pg; 51 52 bool hv_isolation_type_snp(void); 53 bool hv_isolation_type_tdx(void); 54 55 #ifdef CONFIG_X86_64 56 DECLARE_STATIC_CALL(hv_hypercall, hv_std_hypercall); 57 #endif 58 59 /* 60 * DEFAULT INIT GPAT and SEGMENT LIMIT value in struct VMSA 61 * to start AP in enlightened SEV guest. 62 */ 63 #define HV_AP_INIT_GPAT_DEFAULT 0x0007040600070406ULL 64 #define HV_AP_SEGMENT_LIMIT 0xffffffff 65 66 /* 67 * If the hypercall involves no input or output parameters, the hypervisor 68 * ignores the corresponding GPA pointer. 69 */ 70 static inline u64 hv_do_hypercall(u64 control, void *input, void *output) 71 { 72 u64 input_address = input ? virt_to_phys(input) : 0; 73 u64 output_address = output ? virt_to_phys(output) : 0; 74 75 #ifdef CONFIG_X86_64 76 return static_call_mod(hv_hypercall)(control, input_address, output_address); 77 #else 78 u32 input_address_hi = upper_32_bits(input_address); 79 u32 input_address_lo = lower_32_bits(input_address); 80 u32 output_address_hi = upper_32_bits(output_address); 81 u32 output_address_lo = lower_32_bits(output_address); 82 u64 hv_status; 83 84 if (!hv_hypercall_pg) 85 return U64_MAX; 86 87 __asm__ __volatile__(CALL_NOSPEC 88 : "=A" (hv_status), 89 "+c" (input_address_lo), ASM_CALL_CONSTRAINT 90 : "A" (control), 91 "b" (input_address_hi), 92 "D"(output_address_hi), "S"(output_address_lo), 93 THUNK_TARGET(hv_hypercall_pg) 94 : "cc", "memory"); 95 return hv_status; 96 #endif /* !x86_64 */ 97 } 98 99 /* Fast hypercall with 8 bytes of input and no output */ 100 static inline u64 _hv_do_fast_hypercall8(u64 control, u64 input1) 101 { 102 #ifdef CONFIG_X86_64 103 return static_call_mod(hv_hypercall)(control, input1, 0); 104 #else 105 u32 input1_hi = upper_32_bits(input1); 106 u32 input1_lo = lower_32_bits(input1); 107 u64 hv_status; 108 109 __asm__ __volatile__ (CALL_NOSPEC 110 : "=A"(hv_status), 111 "+c"(input1_lo), 112 ASM_CALL_CONSTRAINT 113 : "A" (control), 114 "b" (input1_hi), 115 THUNK_TARGET(hv_hypercall_pg) 116 : "cc", "edi", "esi"); 117 return hv_status; 118 #endif 119 } 120 121 static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1) 122 { 123 u64 control = (u64)code | HV_HYPERCALL_FAST_BIT; 124 125 return _hv_do_fast_hypercall8(control, input1); 126 } 127 128 /* Fast hypercall with 16 bytes of input */ 129 static inline u64 _hv_do_fast_hypercall16(u64 control, u64 input1, u64 input2) 130 { 131 #ifdef CONFIG_X86_64 132 return static_call_mod(hv_hypercall)(control, input1, input2); 133 #else 134 u32 input1_hi = upper_32_bits(input1); 135 u32 input1_lo = lower_32_bits(input1); 136 u32 input2_hi = upper_32_bits(input2); 137 u32 input2_lo = lower_32_bits(input2); 138 u64 hv_status; 139 140 __asm__ __volatile__ (CALL_NOSPEC 141 : "=A"(hv_status), 142 "+c"(input1_lo), ASM_CALL_CONSTRAINT 143 : "A" (control), "b" (input1_hi), 144 "D"(input2_hi), "S"(input2_lo), 145 THUNK_TARGET(hv_hypercall_pg) 146 : "cc"); 147 return hv_status; 148 #endif 149 } 150 151 static inline u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2) 152 { 153 u64 control = (u64)code | HV_HYPERCALL_FAST_BIT; 154 155 return _hv_do_fast_hypercall16(control, input1, input2); 156 } 157 158 extern struct hv_vp_assist_page **hv_vp_assist_page; 159 160 static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu) 161 { 162 if (!hv_vp_assist_page) 163 return NULL; 164 165 return hv_vp_assist_page[cpu]; 166 } 167 168 void __init hyperv_init(void); 169 void hyperv_setup_mmu_ops(void); 170 void set_hv_tscchange_cb(void (*cb)(void)); 171 void clear_hv_tscchange_cb(void); 172 void hyperv_stop_tsc_emulation(void); 173 int hyperv_flush_guest_mapping(u64 as); 174 int hyperv_flush_guest_mapping_range(u64 as, 175 hyperv_fill_flush_list_func fill_func, void *data); 176 int hyperv_fill_flush_guest_mapping_list( 177 struct hv_guest_mapping_flush_list *flush, 178 u64 start_gfn, u64 end_gfn); 179 180 #ifdef CONFIG_X86_64 181 void hv_apic_init(void); 182 void __init hv_init_spinlocks(void); 183 bool hv_vcpu_is_preempted(int vcpu); 184 #else 185 static inline void hv_apic_init(void) {} 186 #endif 187 188 struct irq_domain *hv_create_pci_msi_domain(void); 189 190 int hv_map_msi_interrupt(struct irq_data *data, 191 struct hv_interrupt_entry *out_entry); 192 int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector, 193 struct hv_interrupt_entry *entry); 194 int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry); 195 196 #ifdef CONFIG_AMD_MEM_ENCRYPT 197 bool hv_ghcb_negotiate_protocol(void); 198 void __noreturn hv_ghcb_terminate(unsigned int set, unsigned int reason); 199 int hv_snp_boot_ap(u32 apic_id, unsigned long start_ip, unsigned int cpu); 200 #else 201 static inline bool hv_ghcb_negotiate_protocol(void) { return false; } 202 static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {} 203 static inline int hv_snp_boot_ap(u32 apic_id, unsigned long start_ip, 204 unsigned int cpu) { return 0; } 205 #endif 206 207 #if defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST) 208 void hv_vtom_init(void); 209 void hv_ivm_msr_write(u64 msr, u64 value); 210 void hv_ivm_msr_read(u64 msr, u64 *value); 211 #else 212 static inline void hv_vtom_init(void) {} 213 static inline void hv_ivm_msr_write(u64 msr, u64 value) {} 214 static inline void hv_ivm_msr_read(u64 msr, u64 *value) {} 215 #endif 216 217 static inline bool hv_is_synic_msr(unsigned int reg) 218 { 219 return (reg >= HV_X64_MSR_SCONTROL) && 220 (reg <= HV_X64_MSR_SINT15); 221 } 222 223 static inline bool hv_is_sint_msr(unsigned int reg) 224 { 225 return (reg >= HV_X64_MSR_SINT0) && 226 (reg <= HV_X64_MSR_SINT15); 227 } 228 229 u64 hv_get_msr(unsigned int reg); 230 void hv_set_msr(unsigned int reg, u64 value); 231 u64 hv_get_non_nested_msr(unsigned int reg); 232 void hv_set_non_nested_msr(unsigned int reg, u64 value); 233 234 static __always_inline u64 hv_raw_get_msr(unsigned int reg) 235 { 236 return native_rdmsrq(reg); 237 } 238 int hv_apicid_to_vp_index(u32 apic_id); 239 240 #else /* CONFIG_HYPERV */ 241 static inline void hyperv_init(void) {} 242 static inline void hyperv_setup_mmu_ops(void) {} 243 static inline void set_hv_tscchange_cb(void (*cb)(void)) {} 244 static inline void clear_hv_tscchange_cb(void) {} 245 static inline void hyperv_stop_tsc_emulation(void) {}; 246 static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu) 247 { 248 return NULL; 249 } 250 static inline int hyperv_flush_guest_mapping(u64 as) { return -1; } 251 static inline int hyperv_flush_guest_mapping_range(u64 as, 252 hyperv_fill_flush_list_func fill_func, void *data) 253 { 254 return -1; 255 } 256 static inline void hv_set_msr(unsigned int reg, u64 value) { } 257 static inline u64 hv_get_msr(unsigned int reg) { return 0; } 258 static inline void hv_set_non_nested_msr(unsigned int reg, u64 value) { } 259 static inline u64 hv_get_non_nested_msr(unsigned int reg) { return 0; } 260 static inline int hv_apicid_to_vp_index(u32 apic_id) { return -EINVAL; } 261 #endif /* CONFIG_HYPERV */ 262 263 264 #ifdef CONFIG_HYPERV_VTL_MODE 265 void __init hv_vtl_init_platform(void); 266 int __init hv_vtl_early_init(void); 267 #else 268 static inline void __init hv_vtl_init_platform(void) {} 269 static inline int __init hv_vtl_early_init(void) { return 0; } 270 #endif 271 272 #include <asm-generic/mshyperv.h> 273 274 #endif 275