diff options
Diffstat (limited to 'arch/x86/hyperv/hv_init.c')
-rw-r--r-- | arch/x86/hyperv/hv_init.c | 32 |
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); | |||
91 | struct hv_vp_assist_page **hv_vp_assist_page; | 91 | struct hv_vp_assist_page **hv_vp_assist_page; |
92 | EXPORT_SYMBOL_GPL(hv_vp_assist_page); | 92 | EXPORT_SYMBOL_GPL(hv_vp_assist_page); |
93 | 93 | ||
94 | void __percpu **hyperv_pcpu_input_arg; | ||
95 | EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); | ||
96 | |||
94 | u32 hv_max_vp_index; | 97 | u32 hv_max_vp_index; |
95 | 98 | ||
96 | static int hv_cpu_init(unsigned int cpu) | 99 | static 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 | */ |
246 | void hyperv_init(void) | 264 | void __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. |