Drivers: hv: Add arch independent default functions for some Hyper-V handlers
[linux-2.6-microblaze.git] / drivers / hv / hv_common.c
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>
16 #include <linux/export.h>
17 #include <linux/bitfield.h>
18 #include <linux/cpumask.h>
19 #include <linux/ptrace.h>
20 #include <linux/slab.h>
21 #include <asm/hyperv-tlfs.h>
22 #include <asm/mshyperv.h>
23
24 /*
25  * hv_root_partition and ms_hyperv are defined here with other Hyper-V
26  * specific globals so they are shared across all architectures and are
27  * built only when CONFIG_HYPERV is defined.  But on x86,
28  * ms_hyperv_init_platform() is built even when CONFIG_HYPERV is not
29  * defined, and it uses these two variables.  So mark them as __weak
30  * here, allowing for an overriding definition in the module containing
31  * ms_hyperv_init_platform().
32  */
33 bool __weak hv_root_partition;
34 EXPORT_SYMBOL_GPL(hv_root_partition);
35
36 struct ms_hyperv_info __weak ms_hyperv;
37 EXPORT_SYMBOL_GPL(ms_hyperv);
38
39 u32 *hv_vp_index;
40 EXPORT_SYMBOL_GPL(hv_vp_index);
41
42 u32 hv_max_vp_index;
43 EXPORT_SYMBOL_GPL(hv_max_vp_index);
44
45 void  __percpu **hyperv_pcpu_input_arg;
46 EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg);
47
48 void  __percpu **hyperv_pcpu_output_arg;
49 EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg);
50
51 /*
52  * Hyper-V specific initialization and shutdown code that is
53  * common across all architectures.  Called from architecture
54  * specific initialization functions.
55  */
56
57 void __init hv_common_free(void)
58 {
59         kfree(hv_vp_index);
60         hv_vp_index = NULL;
61
62         free_percpu(hyperv_pcpu_output_arg);
63         hyperv_pcpu_output_arg = NULL;
64
65         free_percpu(hyperv_pcpu_input_arg);
66         hyperv_pcpu_input_arg = NULL;
67 }
68
69 int __init hv_common_init(void)
70 {
71         int i;
72
73         /*
74          * Allocate the per-CPU state for the hypercall input arg.
75          * If this allocation fails, we will not be able to setup
76          * (per-CPU) hypercall input page and thus this failure is
77          * fatal on Hyper-V.
78          */
79         hyperv_pcpu_input_arg = alloc_percpu(void  *);
80         BUG_ON(!hyperv_pcpu_input_arg);
81
82         /* Allocate the per-CPU state for output arg for root */
83         if (hv_root_partition) {
84                 hyperv_pcpu_output_arg = alloc_percpu(void *);
85                 BUG_ON(!hyperv_pcpu_output_arg);
86         }
87
88         hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
89                                     GFP_KERNEL);
90         if (!hv_vp_index) {
91                 hv_common_free();
92                 return -ENOMEM;
93         }
94
95         for (i = 0; i < num_possible_cpus(); i++)
96                 hv_vp_index[i] = VP_INVAL;
97
98         return 0;
99 }
100
101 /*
102  * Hyper-V specific initialization and die code for
103  * individual CPUs that is common across all architectures.
104  * Called by the CPU hotplug mechanism.
105  */
106
107 int hv_common_cpu_init(unsigned int cpu)
108 {
109         void **inputarg, **outputarg;
110         u64 msr_vp_index;
111         gfp_t flags;
112         int pgcount = hv_root_partition ? 2 : 1;
113
114         /* hv_cpu_init() can be called with IRQs disabled from hv_resume() */
115         flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL;
116
117         inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
118         *inputarg = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
119         if (!(*inputarg))
120                 return -ENOMEM;
121
122         if (hv_root_partition) {
123                 outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
124                 *outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE;
125         }
126
127         msr_vp_index = hv_get_register(HV_REGISTER_VP_INDEX);
128
129         hv_vp_index[cpu] = msr_vp_index;
130
131         if (msr_vp_index > hv_max_vp_index)
132                 hv_max_vp_index = msr_vp_index;
133
134         return 0;
135 }
136
137 int hv_common_cpu_die(unsigned int cpu)
138 {
139         unsigned long flags;
140         void **inputarg, **outputarg;
141         void *mem;
142
143         local_irq_save(flags);
144
145         inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
146         mem = *inputarg;
147         *inputarg = NULL;
148
149         if (hv_root_partition) {
150                 outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
151                 *outputarg = NULL;
152         }
153
154         local_irq_restore(flags);
155
156         kfree(mem);
157
158         return 0;
159 }
160
161 /* Bit mask of the extended capability to query: see HV_EXT_CAPABILITY_xxx */
162 bool hv_query_ext_cap(u64 cap_query)
163 {
164         /*
165          * The address of the 'hv_extended_cap' variable will be used as an
166          * output parameter to the hypercall below and so it should be
167          * compatible with 'virt_to_phys'. Which means, it's address should be
168          * directly mapped. Use 'static' to keep it compatible; stack variables
169          * can be virtually mapped, making them incompatible with
170          * 'virt_to_phys'.
171          * Hypercall input/output addresses should also be 8-byte aligned.
172          */
173         static u64 hv_extended_cap __aligned(8);
174         static bool hv_extended_cap_queried;
175         u64 status;
176
177         /*
178          * Querying extended capabilities is an extended hypercall. Check if the
179          * partition supports extended hypercall, first.
180          */
181         if (!(ms_hyperv.priv_high & HV_ENABLE_EXTENDED_HYPERCALLS))
182                 return false;
183
184         /* Extended capabilities do not change at runtime. */
185         if (hv_extended_cap_queried)
186                 return hv_extended_cap & cap_query;
187
188         status = hv_do_hypercall(HV_EXT_CALL_QUERY_CAPABILITIES, NULL,
189                                  &hv_extended_cap);
190
191         /*
192          * The query extended capabilities hypercall should not fail under
193          * any normal circumstances. Avoid repeatedly making the hypercall, on
194          * error.
195          */
196         hv_extended_cap_queried = true;
197         if (!hv_result_success(status)) {
198                 pr_err("Hyper-V: Extended query capabilities hypercall failed 0x%llx\n",
199                        status);
200                 return false;
201         }
202
203         return hv_extended_cap & cap_query;
204 }
205 EXPORT_SYMBOL_GPL(hv_query_ext_cap);
206
207 /* These __weak functions provide default "no-op" behavior and
208  * may be overridden by architecture specific versions. Architectures
209  * for which the default "no-op" behavior is sufficient can leave
210  * them unimplemented and not be cluttered with a bunch of stub
211  * functions in arch-specific code.
212  */
213
214 bool __weak hv_is_isolation_supported(void)
215 {
216         return false;
217 }
218 EXPORT_SYMBOL_GPL(hv_is_isolation_supported);
219
220 void __weak hv_setup_vmbus_handler(void (*handler)(void))
221 {
222 }
223 EXPORT_SYMBOL_GPL(hv_setup_vmbus_handler);
224
225 void __weak hv_remove_vmbus_handler(void)
226 {
227 }
228 EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler);
229
230 void __weak hv_setup_kexec_handler(void (*handler)(void))
231 {
232 }
233 EXPORT_SYMBOL_GPL(hv_setup_kexec_handler);
234
235 void __weak hv_remove_kexec_handler(void)
236 {
237 }
238 EXPORT_SYMBOL_GPL(hv_remove_kexec_handler);
239
240 void __weak hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
241 {
242 }
243 EXPORT_SYMBOL_GPL(hv_setup_crash_handler);
244
245 void __weak hv_remove_crash_handler(void)
246 {
247 }
248 EXPORT_SYMBOL_GPL(hv_remove_crash_handler);
249
250 void __weak hyperv_cleanup(void)
251 {
252 }
253 EXPORT_SYMBOL_GPL(hyperv_cleanup);