Commit | Line | Data |
---|---|---|
a4d7e8ae MK |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | ||
3 | /* | |
4 | * Architecture neutral utility routines for interacting with | |
5 | * Hyper-V. This file is specifically for code that must be | |
6 | * built-in to the kernel image when CONFIG_HYPERV is set | |
7 | * (vs. being in a module) because it is called from architecture | |
8 | * specific code under arch/. | |
9 | * | |
10 | * Copyright (C) 2021, Microsoft, Inc. | |
11 | * | |
12 | * Author : Michael Kelley <mikelley@microsoft.com> | |
13 | */ | |
14 | ||
15 | #include <linux/types.h> | |
6dc77fa5 | 16 | #include <linux/acpi.h> |
a4d7e8ae MK |
17 | #include <linux/export.h> |
18 | #include <linux/bitfield.h> | |
afca4d95 | 19 | #include <linux/cpumask.h> |
6dc77fa5 | 20 | #include <linux/panic_notifier.h> |
9d7cf2c9 | 21 | #include <linux/ptrace.h> |
afca4d95 | 22 | #include <linux/slab.h> |
a4d7e8ae MK |
23 | #include <asm/hyperv-tlfs.h> |
24 | #include <asm/mshyperv.h> | |
25 | ||
afca4d95 MK |
26 | /* |
27 | * hv_root_partition and ms_hyperv are defined here with other Hyper-V | |
28 | * specific globals so they are shared across all architectures and are | |
29 | * built only when CONFIG_HYPERV is defined. But on x86, | |
30 | * ms_hyperv_init_platform() is built even when CONFIG_HYPERV is not | |
31 | * defined, and it uses these two variables. So mark them as __weak | |
32 | * here, allowing for an overriding definition in the module containing | |
33 | * ms_hyperv_init_platform(). | |
34 | */ | |
35 | bool __weak hv_root_partition; | |
36 | EXPORT_SYMBOL_GPL(hv_root_partition); | |
37 | ||
38 | struct ms_hyperv_info __weak ms_hyperv; | |
39 | EXPORT_SYMBOL_GPL(ms_hyperv); | |
40 | ||
41 | u32 *hv_vp_index; | |
42 | EXPORT_SYMBOL_GPL(hv_vp_index); | |
43 | ||
44 | u32 hv_max_vp_index; | |
45 | EXPORT_SYMBOL_GPL(hv_max_vp_index); | |
46 | ||
db3c65bc | 47 | void * __percpu *hyperv_pcpu_input_arg; |
afca4d95 MK |
48 | EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); |
49 | ||
db3c65bc | 50 | void * __percpu *hyperv_pcpu_output_arg; |
afca4d95 MK |
51 | EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg); |
52 | ||
53 | /* | |
54 | * Hyper-V specific initialization and shutdown code that is | |
55 | * common across all architectures. Called from architecture | |
56 | * specific initialization functions. | |
57 | */ | |
58 | ||
59 | void __init hv_common_free(void) | |
60 | { | |
61 | kfree(hv_vp_index); | |
62 | hv_vp_index = NULL; | |
63 | ||
64 | free_percpu(hyperv_pcpu_output_arg); | |
65 | hyperv_pcpu_output_arg = NULL; | |
66 | ||
67 | free_percpu(hyperv_pcpu_input_arg); | |
68 | hyperv_pcpu_input_arg = NULL; | |
69 | } | |
70 | ||
71 | int __init hv_common_init(void) | |
72 | { | |
73 | int i; | |
74 | ||
6dc77fa5 MK |
75 | /* |
76 | * Hyper-V expects to get crash register data or kmsg when | |
77 | * crash enlightment is available and system crashes. Set | |
78 | * crash_kexec_post_notifiers to be true to make sure that | |
79 | * calling crash enlightment interface before running kdump | |
80 | * kernel. | |
81 | */ | |
82 | if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) | |
83 | crash_kexec_post_notifiers = true; | |
84 | ||
afca4d95 MK |
85 | /* |
86 | * Allocate the per-CPU state for the hypercall input arg. | |
87 | * If this allocation fails, we will not be able to setup | |
88 | * (per-CPU) hypercall input page and thus this failure is | |
89 | * fatal on Hyper-V. | |
90 | */ | |
91 | hyperv_pcpu_input_arg = alloc_percpu(void *); | |
92 | BUG_ON(!hyperv_pcpu_input_arg); | |
93 | ||
94 | /* Allocate the per-CPU state for output arg for root */ | |
95 | if (hv_root_partition) { | |
96 | hyperv_pcpu_output_arg = alloc_percpu(void *); | |
97 | BUG_ON(!hyperv_pcpu_output_arg); | |
98 | } | |
99 | ||
100 | hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index), | |
101 | GFP_KERNEL); | |
102 | if (!hv_vp_index) { | |
103 | hv_common_free(); | |
104 | return -ENOMEM; | |
105 | } | |
106 | ||
107 | for (i = 0; i < num_possible_cpus(); i++) | |
108 | hv_vp_index[i] = VP_INVAL; | |
109 | ||
110 | return 0; | |
111 | } | |
112 | ||
113 | /* | |
114 | * Hyper-V specific initialization and die code for | |
115 | * individual CPUs that is common across all architectures. | |
116 | * Called by the CPU hotplug mechanism. | |
117 | */ | |
118 | ||
119 | int hv_common_cpu_init(unsigned int cpu) | |
120 | { | |
121 | void **inputarg, **outputarg; | |
122 | u64 msr_vp_index; | |
123 | gfp_t flags; | |
124 | int pgcount = hv_root_partition ? 2 : 1; | |
125 | ||
126 | /* hv_cpu_init() can be called with IRQs disabled from hv_resume() */ | |
127 | flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL; | |
128 | ||
129 | inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg); | |
130 | *inputarg = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags); | |
131 | if (!(*inputarg)) | |
132 | return -ENOMEM; | |
133 | ||
134 | if (hv_root_partition) { | |
135 | outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); | |
136 | *outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE; | |
137 | } | |
138 | ||
139 | msr_vp_index = hv_get_register(HV_REGISTER_VP_INDEX); | |
140 | ||
141 | hv_vp_index[cpu] = msr_vp_index; | |
142 | ||
143 | if (msr_vp_index > hv_max_vp_index) | |
144 | hv_max_vp_index = msr_vp_index; | |
145 | ||
146 | return 0; | |
147 | } | |
148 | ||
149 | int hv_common_cpu_die(unsigned int cpu) | |
150 | { | |
151 | unsigned long flags; | |
152 | void **inputarg, **outputarg; | |
153 | void *mem; | |
154 | ||
155 | local_irq_save(flags); | |
156 | ||
157 | inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg); | |
158 | mem = *inputarg; | |
159 | *inputarg = NULL; | |
160 | ||
161 | if (hv_root_partition) { | |
162 | outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); | |
163 | *outputarg = NULL; | |
164 | } | |
165 | ||
166 | local_irq_restore(flags); | |
167 | ||
168 | kfree(mem); | |
169 | ||
170 | return 0; | |
171 | } | |
a4d7e8ae MK |
172 | |
173 | /* Bit mask of the extended capability to query: see HV_EXT_CAPABILITY_xxx */ | |
174 | bool hv_query_ext_cap(u64 cap_query) | |
175 | { | |
176 | /* | |
177 | * The address of the 'hv_extended_cap' variable will be used as an | |
178 | * output parameter to the hypercall below and so it should be | |
179 | * compatible with 'virt_to_phys'. Which means, it's address should be | |
180 | * directly mapped. Use 'static' to keep it compatible; stack variables | |
b694011a | 181 | * can be virtually mapped, making them incompatible with |
a4d7e8ae MK |
182 | * 'virt_to_phys'. |
183 | * Hypercall input/output addresses should also be 8-byte aligned. | |
184 | */ | |
185 | static u64 hv_extended_cap __aligned(8); | |
186 | static bool hv_extended_cap_queried; | |
187 | u64 status; | |
188 | ||
189 | /* | |
190 | * Querying extended capabilities is an extended hypercall. Check if the | |
191 | * partition supports extended hypercall, first. | |
192 | */ | |
193 | if (!(ms_hyperv.priv_high & HV_ENABLE_EXTENDED_HYPERCALLS)) | |
194 | return false; | |
195 | ||
196 | /* Extended capabilities do not change at runtime. */ | |
197 | if (hv_extended_cap_queried) | |
198 | return hv_extended_cap & cap_query; | |
199 | ||
200 | status = hv_do_hypercall(HV_EXT_CALL_QUERY_CAPABILITIES, NULL, | |
201 | &hv_extended_cap); | |
202 | ||
203 | /* | |
204 | * The query extended capabilities hypercall should not fail under | |
205 | * any normal circumstances. Avoid repeatedly making the hypercall, on | |
206 | * error. | |
207 | */ | |
208 | hv_extended_cap_queried = true; | |
209 | if (!hv_result_success(status)) { | |
210 | pr_err("Hyper-V: Extended query capabilities hypercall failed 0x%llx\n", | |
211 | status); | |
212 | return false; | |
213 | } | |
214 | ||
215 | return hv_extended_cap & cap_query; | |
216 | } | |
217 | EXPORT_SYMBOL_GPL(hv_query_ext_cap); | |
9d7cf2c9 | 218 | |
6dc77fa5 MK |
219 | bool hv_is_hibernation_supported(void) |
220 | { | |
221 | return !hv_root_partition && acpi_sleep_state_supported(ACPI_STATE_S4); | |
222 | } | |
223 | EXPORT_SYMBOL_GPL(hv_is_hibernation_supported); | |
224 | ||
31e5e646 MK |
225 | /* |
226 | * Default function to read the Hyper-V reference counter, independent | |
227 | * of whether Hyper-V enlightened clocks/timers are being used. But on | |
228 | * architectures where it is used, Hyper-V enlightenment code in | |
229 | * hyperv_timer.c may override this function. | |
230 | */ | |
231 | static u64 __hv_read_ref_counter(void) | |
232 | { | |
233 | return hv_get_register(HV_REGISTER_TIME_REF_COUNT); | |
234 | } | |
235 | ||
236 | u64 (*hv_read_reference_counter)(void) = __hv_read_ref_counter; | |
237 | EXPORT_SYMBOL_GPL(hv_read_reference_counter); | |
238 | ||
9d7cf2c9 MK |
239 | /* These __weak functions provide default "no-op" behavior and |
240 | * may be overridden by architecture specific versions. Architectures | |
241 | * for which the default "no-op" behavior is sufficient can leave | |
242 | * them unimplemented and not be cluttered with a bunch of stub | |
243 | * functions in arch-specific code. | |
244 | */ | |
245 | ||
246 | bool __weak hv_is_isolation_supported(void) | |
247 | { | |
248 | return false; | |
249 | } | |
250 | EXPORT_SYMBOL_GPL(hv_is_isolation_supported); | |
251 | ||
faff4406 TL |
252 | bool __weak hv_isolation_type_snp(void) |
253 | { | |
254 | return false; | |
255 | } | |
256 | EXPORT_SYMBOL_GPL(hv_isolation_type_snp); | |
257 | ||
9d7cf2c9 MK |
258 | void __weak hv_setup_vmbus_handler(void (*handler)(void)) |
259 | { | |
260 | } | |
261 | EXPORT_SYMBOL_GPL(hv_setup_vmbus_handler); | |
262 | ||
263 | void __weak hv_remove_vmbus_handler(void) | |
264 | { | |
265 | } | |
266 | EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler); | |
267 | ||
268 | void __weak hv_setup_kexec_handler(void (*handler)(void)) | |
269 | { | |
270 | } | |
271 | EXPORT_SYMBOL_GPL(hv_setup_kexec_handler); | |
272 | ||
273 | void __weak hv_remove_kexec_handler(void) | |
274 | { | |
275 | } | |
276 | EXPORT_SYMBOL_GPL(hv_remove_kexec_handler); | |
277 | ||
278 | void __weak hv_setup_crash_handler(void (*handler)(struct pt_regs *regs)) | |
279 | { | |
280 | } | |
281 | EXPORT_SYMBOL_GPL(hv_setup_crash_handler); | |
282 | ||
283 | void __weak hv_remove_crash_handler(void) | |
284 | { | |
285 | } | |
286 | EXPORT_SYMBOL_GPL(hv_remove_crash_handler); | |
287 | ||
288 | void __weak hyperv_cleanup(void) | |
289 | { | |
290 | } | |
291 | EXPORT_SYMBOL_GPL(hyperv_cleanup); | |
20c89a55 TL |
292 | |
293 | u64 __weak hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size) | |
294 | { | |
295 | return HV_STATUS_INVALID_PARAMETER; | |
296 | } | |
297 | EXPORT_SYMBOL_GPL(hv_ghcb_hypercall); | |
846da38d TL |
298 | |
299 | void __weak *hv_map_memory(void *addr, unsigned long size) | |
300 | { | |
301 | return NULL; | |
302 | } | |
303 | EXPORT_SYMBOL_GPL(hv_map_memory); | |
304 | ||
305 | void __weak hv_unmap_memory(void *addr) | |
306 | { | |
307 | } | |
308 | EXPORT_SYMBOL_GPL(hv_unmap_memory); |