0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/types.h>
0016 #include <linux/acpi.h>
0017 #include <linux/export.h>
0018 #include <linux/bitfield.h>
0019 #include <linux/cpumask.h>
0020 #include <linux/panic_notifier.h>
0021 #include <linux/ptrace.h>
0022 #include <linux/slab.h>
0023 #include <linux/dma-map-ops.h>
0024 #include <asm/hyperv-tlfs.h>
0025 #include <asm/mshyperv.h>
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 bool __weak hv_root_partition;
0037 EXPORT_SYMBOL_GPL(hv_root_partition);
0038
0039 struct ms_hyperv_info __weak ms_hyperv;
0040 EXPORT_SYMBOL_GPL(ms_hyperv);
0041
0042 u32 *hv_vp_index;
0043 EXPORT_SYMBOL_GPL(hv_vp_index);
0044
0045 u32 hv_max_vp_index;
0046 EXPORT_SYMBOL_GPL(hv_max_vp_index);
0047
0048 void * __percpu *hyperv_pcpu_input_arg;
0049 EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg);
0050
0051 void * __percpu *hyperv_pcpu_output_arg;
0052 EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg);
0053
0054
0055
0056
0057
0058
0059
0060 void __init hv_common_free(void)
0061 {
0062 kfree(hv_vp_index);
0063 hv_vp_index = NULL;
0064
0065 free_percpu(hyperv_pcpu_output_arg);
0066 hyperv_pcpu_output_arg = NULL;
0067
0068 free_percpu(hyperv_pcpu_input_arg);
0069 hyperv_pcpu_input_arg = NULL;
0070 }
0071
0072 int __init hv_common_init(void)
0073 {
0074 int i;
0075
0076
0077
0078
0079
0080
0081
0082
0083 if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
0084 crash_kexec_post_notifiers = true;
0085 pr_info("Hyper-V: enabling crash_kexec_post_notifiers\n");
0086 }
0087
0088
0089
0090
0091
0092
0093
0094 hyperv_pcpu_input_arg = alloc_percpu(void *);
0095 BUG_ON(!hyperv_pcpu_input_arg);
0096
0097
0098 if (hv_root_partition) {
0099 hyperv_pcpu_output_arg = alloc_percpu(void *);
0100 BUG_ON(!hyperv_pcpu_output_arg);
0101 }
0102
0103 hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
0104 GFP_KERNEL);
0105 if (!hv_vp_index) {
0106 hv_common_free();
0107 return -ENOMEM;
0108 }
0109
0110 for (i = 0; i < num_possible_cpus(); i++)
0111 hv_vp_index[i] = VP_INVAL;
0112
0113 return 0;
0114 }
0115
0116
0117
0118
0119
0120
0121
0122 int hv_common_cpu_init(unsigned int cpu)
0123 {
0124 void **inputarg, **outputarg;
0125 u64 msr_vp_index;
0126 gfp_t flags;
0127 int pgcount = hv_root_partition ? 2 : 1;
0128
0129
0130 flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL;
0131
0132 inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
0133 *inputarg = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
0134 if (!(*inputarg))
0135 return -ENOMEM;
0136
0137 if (hv_root_partition) {
0138 outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
0139 *outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE;
0140 }
0141
0142 msr_vp_index = hv_get_register(HV_REGISTER_VP_INDEX);
0143
0144 hv_vp_index[cpu] = msr_vp_index;
0145
0146 if (msr_vp_index > hv_max_vp_index)
0147 hv_max_vp_index = msr_vp_index;
0148
0149 return 0;
0150 }
0151
0152 int hv_common_cpu_die(unsigned int cpu)
0153 {
0154 unsigned long flags;
0155 void **inputarg, **outputarg;
0156 void *mem;
0157
0158 local_irq_save(flags);
0159
0160 inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
0161 mem = *inputarg;
0162 *inputarg = NULL;
0163
0164 if (hv_root_partition) {
0165 outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
0166 *outputarg = NULL;
0167 }
0168
0169 local_irq_restore(flags);
0170
0171 kfree(mem);
0172
0173 return 0;
0174 }
0175
0176
0177 bool hv_query_ext_cap(u64 cap_query)
0178 {
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188 static u64 hv_extended_cap __aligned(8);
0189 static bool hv_extended_cap_queried;
0190 u64 status;
0191
0192
0193
0194
0195
0196 if (!(ms_hyperv.priv_high & HV_ENABLE_EXTENDED_HYPERCALLS))
0197 return false;
0198
0199
0200 if (hv_extended_cap_queried)
0201 return hv_extended_cap & cap_query;
0202
0203 status = hv_do_hypercall(HV_EXT_CALL_QUERY_CAPABILITIES, NULL,
0204 &hv_extended_cap);
0205
0206
0207
0208
0209
0210
0211 hv_extended_cap_queried = true;
0212 if (!hv_result_success(status)) {
0213 pr_err("Hyper-V: Extended query capabilities hypercall failed 0x%llx\n",
0214 status);
0215 return false;
0216 }
0217
0218 return hv_extended_cap & cap_query;
0219 }
0220 EXPORT_SYMBOL_GPL(hv_query_ext_cap);
0221
0222 void hv_setup_dma_ops(struct device *dev, bool coherent)
0223 {
0224
0225
0226
0227
0228 arch_setup_dma_ops(dev, 0, 0, NULL, coherent);
0229 }
0230 EXPORT_SYMBOL_GPL(hv_setup_dma_ops);
0231
0232 bool hv_is_hibernation_supported(void)
0233 {
0234 return !hv_root_partition && acpi_sleep_state_supported(ACPI_STATE_S4);
0235 }
0236 EXPORT_SYMBOL_GPL(hv_is_hibernation_supported);
0237
0238
0239
0240
0241
0242
0243
0244 static u64 __hv_read_ref_counter(void)
0245 {
0246 return hv_get_register(HV_REGISTER_TIME_REF_COUNT);
0247 }
0248
0249 u64 (*hv_read_reference_counter)(void) = __hv_read_ref_counter;
0250 EXPORT_SYMBOL_GPL(hv_read_reference_counter);
0251
0252
0253
0254
0255
0256
0257
0258
0259 bool __weak hv_is_isolation_supported(void)
0260 {
0261 return false;
0262 }
0263 EXPORT_SYMBOL_GPL(hv_is_isolation_supported);
0264
0265 bool __weak hv_isolation_type_snp(void)
0266 {
0267 return false;
0268 }
0269 EXPORT_SYMBOL_GPL(hv_isolation_type_snp);
0270
0271 void __weak hv_setup_vmbus_handler(void (*handler)(void))
0272 {
0273 }
0274 EXPORT_SYMBOL_GPL(hv_setup_vmbus_handler);
0275
0276 void __weak hv_remove_vmbus_handler(void)
0277 {
0278 }
0279 EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler);
0280
0281 void __weak hv_setup_kexec_handler(void (*handler)(void))
0282 {
0283 }
0284 EXPORT_SYMBOL_GPL(hv_setup_kexec_handler);
0285
0286 void __weak hv_remove_kexec_handler(void)
0287 {
0288 }
0289 EXPORT_SYMBOL_GPL(hv_remove_kexec_handler);
0290
0291 void __weak hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
0292 {
0293 }
0294 EXPORT_SYMBOL_GPL(hv_setup_crash_handler);
0295
0296 void __weak hv_remove_crash_handler(void)
0297 {
0298 }
0299 EXPORT_SYMBOL_GPL(hv_remove_crash_handler);
0300
0301 void __weak hyperv_cleanup(void)
0302 {
0303 }
0304 EXPORT_SYMBOL_GPL(hyperv_cleanup);
0305
0306 u64 __weak hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)
0307 {
0308 return HV_STATUS_INVALID_PARAMETER;
0309 }
0310 EXPORT_SYMBOL_GPL(hv_ghcb_hypercall);
0311
0312 void __weak *hv_map_memory(void *addr, unsigned long size)
0313 {
0314 return NULL;
0315 }
0316 EXPORT_SYMBOL_GPL(hv_map_memory);
0317
0318 void __weak hv_unmap_memory(void *addr)
0319 {
0320 }
0321 EXPORT_SYMBOL_GPL(hv_unmap_memory);