aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/hyperv/hv_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/hyperv/hv_init.c')
-rw-r--r--arch/x86/hyperv/hv_init.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index cfecc2272f2d..4c431e1c1eff 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -91,12 +91,19 @@ EXPORT_SYMBOL_GPL(hv_vp_index);
91struct hv_vp_assist_page **hv_vp_assist_page; 91struct hv_vp_assist_page **hv_vp_assist_page;
92EXPORT_SYMBOL_GPL(hv_vp_assist_page); 92EXPORT_SYMBOL_GPL(hv_vp_assist_page);
93 93
94void __percpu **hyperv_pcpu_input_arg;
95EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg);
96
94u32 hv_max_vp_index; 97u32 hv_max_vp_index;
95 98
96static int hv_cpu_init(unsigned int cpu) 99static int hv_cpu_init(unsigned int cpu)
97{ 100{
98 u64 msr_vp_index; 101 u64 msr_vp_index;
99 struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()]; 102 struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()];
103 void **input_arg;
104
105 input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
106 *input_arg = page_address(alloc_page(GFP_KERNEL));
100 107
101 hv_get_vp_index(msr_vp_index); 108 hv_get_vp_index(msr_vp_index);
102 109
@@ -217,6 +224,16 @@ static int hv_cpu_die(unsigned int cpu)
217{ 224{
218 struct hv_reenlightenment_control re_ctrl; 225 struct hv_reenlightenment_control re_ctrl;
219 unsigned int new_cpu; 226 unsigned int new_cpu;
227 unsigned long flags;
228 void **input_arg;
229 void *input_pg = NULL;
230
231 local_irq_save(flags);
232 input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
233 input_pg = *input_arg;
234 *input_arg = NULL;
235 local_irq_restore(flags);
236 free_page((unsigned long)input_pg);
220 237
221 if (hv_vp_assist_page && hv_vp_assist_page[cpu]) 238 if (hv_vp_assist_page && hv_vp_assist_page[cpu])
222 wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, 0); 239 wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, 0);
@@ -242,8 +259,9 @@ static int hv_cpu_die(unsigned int cpu)
242 * 259 *
243 * 1. Setup the hypercall page. 260 * 1. Setup the hypercall page.
244 * 2. Register Hyper-V specific clocksource. 261 * 2. Register Hyper-V specific clocksource.
262 * 3. Setup Hyper-V specific APIC entry points.
245 */ 263 */
246void hyperv_init(void) 264void __init hyperv_init(void)
247{ 265{
248 u64 guest_id, required_msrs; 266 u64 guest_id, required_msrs;
249 union hv_x64_msr_hypercall_contents hypercall_msr; 267 union hv_x64_msr_hypercall_contents hypercall_msr;
@@ -259,6 +277,16 @@ void hyperv_init(void)
259 if ((ms_hyperv.features & required_msrs) != required_msrs) 277 if ((ms_hyperv.features & required_msrs) != required_msrs)
260 return; 278 return;
261 279
280 /*
281 * Allocate the per-CPU state for the hypercall input arg.
282 * If this allocation fails, we will not be able to setup
283 * (per-CPU) hypercall input page and thus this failure is
284 * fatal on Hyper-V.
285 */
286 hyperv_pcpu_input_arg = alloc_percpu(void *);
287
288 BUG_ON(hyperv_pcpu_input_arg == NULL);
289
262 /* Allocate percpu VP index */ 290 /* Allocate percpu VP index */
263 hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index), 291 hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
264 GFP_KERNEL); 292 GFP_KERNEL);
@@ -296,7 +324,7 @@ void hyperv_init(void)
296 hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg); 324 hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg);
297 wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); 325 wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
298 326
299 hyper_alloc_mmu(); 327 hv_apic_init();
300 328
301 /* 329 /*
302 * Register Hyper-V specific clocksource. 330 * Register Hyper-V specific clocksource.