Skip to content

Commit 692b7dc

Browse files
committed
Merge tag 'hyperv-fixes-signed-20230619' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv fixes from Wei Liu: - Fix races in Hyper-V PCI controller (Dexuan Cui) - Fix handling of hyperv_pcpu_input_arg (Michael Kelley) - Fix vmbus_wait_for_unload to scan present CPUs (Michael Kelley) - Call hv_synic_free in the failure path of hv_synic_alloc (Dexuan Cui) - Add noop for real mode handlers for virtual trust level code (Saurabh Sengar) * tag 'hyperv-fixes-signed-20230619' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: PCI: hv: Add a per-bus mutex state_lock Revert "PCI: hv: Fix a timing issue which causes kdump to fail occasionally" PCI: hv: Remove the useless hv_pcichild_state from struct hv_pci_dev PCI: hv: Fix a race condition in hv_irq_unmask() that can cause panic PCI: hv: Fix a race condition bug in hv_pci_query_relations() arm64/hyperv: Use CPUHP_AP_HYPERV_ONLINE state to fix CPU online sequencing x86/hyperv: Fix hyperv_pcpu_input_arg handling when CPUs go online/offline Drivers: hv: vmbus: Fix vmbus_wait_for_unload() to scan present CPUs Drivers: hv: vmbus: Call hv_synic_free() if hv_synic_alloc() fails x86/hyperv/vtl: Add noop for realmode pointers
2 parents dbad9ce + 067d6ec commit 692b7dc

File tree

8 files changed

+129
-88
lines changed

8 files changed

+129
-88
lines changed

arch/arm64/hyperv/mshyperv.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static int __init hyperv_init(void)
6767
if (ret)
6868
return ret;
6969

70-
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm64/hyperv_init:online",
70+
ret = cpuhp_setup_state(CPUHP_AP_HYPERV_ONLINE, "arm64/hyperv_init:online",
7171
hv_common_cpu_init, hv_common_cpu_die);
7272
if (ret < 0) {
7373
hv_common_free();

arch/x86/hyperv/hv_init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ void __init hyperv_init(void)
416416
goto free_vp_assist_page;
417417
}
418418

419-
cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",
419+
cpuhp = cpuhp_setup_state(CPUHP_AP_HYPERV_ONLINE, "x86/hyperv_init:online",
420420
hv_cpu_init, hv_cpu_die);
421421
if (cpuhp < 0)
422422
goto free_ghcb_page;

arch/x86/hyperv/hv_vtl.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ void __init hv_vtl_init_platform(void)
2020
{
2121
pr_info("Linux runs in Hyper-V Virtual Trust Level\n");
2222

23+
x86_platform.realmode_reserve = x86_init_noop;
24+
x86_platform.realmode_init = x86_init_noop;
2325
x86_init.irqs.pre_vector_init = x86_init_noop;
2426
x86_init.timers.timer_init = x86_init_noop;
2527

drivers/hv/channel_mgmt.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -829,11 +829,22 @@ static void vmbus_wait_for_unload(void)
829829
if (completion_done(&vmbus_connection.unload_event))
830830
goto completed;
831831

832-
for_each_online_cpu(cpu) {
832+
for_each_present_cpu(cpu) {
833833
struct hv_per_cpu_context *hv_cpu
834834
= per_cpu_ptr(hv_context.cpu_context, cpu);
835835

836+
/*
837+
* In a CoCo VM the synic_message_page is not allocated
838+
* in hv_synic_alloc(). Instead it is set/cleared in
839+
* hv_synic_enable_regs() and hv_synic_disable_regs()
840+
* such that it is set only when the CPU is online. If
841+
* not all present CPUs are online, the message page
842+
* might be NULL, so skip such CPUs.
843+
*/
836844
page_addr = hv_cpu->synic_message_page;
845+
if (!page_addr)
846+
continue;
847+
837848
msg = (struct hv_message *)page_addr
838849
+ VMBUS_MESSAGE_SINT;
839850

@@ -867,11 +878,14 @@ static void vmbus_wait_for_unload(void)
867878
* maybe-pending messages on all CPUs to be able to receive new
868879
* messages after we reconnect.
869880
*/
870-
for_each_online_cpu(cpu) {
881+
for_each_present_cpu(cpu) {
871882
struct hv_per_cpu_context *hv_cpu
872883
= per_cpu_ptr(hv_context.cpu_context, cpu);
873884

874885
page_addr = hv_cpu->synic_message_page;
886+
if (!page_addr)
887+
continue;
888+
875889
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
876890
msg->header.message_type = HVMSG_NONE;
877891
}

drivers/hv/hv_common.c

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -364,13 +364,20 @@ int hv_common_cpu_init(unsigned int cpu)
364364
flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL;
365365

366366
inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
367-
*inputarg = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
368-
if (!(*inputarg))
369-
return -ENOMEM;
370367

371-
if (hv_root_partition) {
372-
outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
373-
*outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE;
368+
/*
369+
* hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already
370+
* allocated if this CPU was previously online and then taken offline
371+
*/
372+
if (!*inputarg) {
373+
*inputarg = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
374+
if (!(*inputarg))
375+
return -ENOMEM;
376+
377+
if (hv_root_partition) {
378+
outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
379+
*outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE;
380+
}
374381
}
375382

376383
msr_vp_index = hv_get_register(HV_REGISTER_VP_INDEX);
@@ -385,24 +392,17 @@ int hv_common_cpu_init(unsigned int cpu)
385392

386393
int hv_common_cpu_die(unsigned int cpu)
387394
{
388-
unsigned long flags;
389-
void **inputarg, **outputarg;
390-
void *mem;
391-
392-
local_irq_save(flags);
393-
394-
inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
395-
mem = *inputarg;
396-
*inputarg = NULL;
397-
398-
if (hv_root_partition) {
399-
outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
400-
*outputarg = NULL;
401-
}
402-
403-
local_irq_restore(flags);
404-
405-
kfree(mem);
395+
/*
396+
* The hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory
397+
* is not freed when the CPU goes offline as the hyperv_pcpu_input_arg
398+
* may be used by the Hyper-V vPCI driver in reassigning interrupts
399+
* as part of the offlining process. The interrupt reassignment
400+
* happens *after* the CPUHP_AP_HYPERV_ONLINE state has run and
401+
* called this function.
402+
*
403+
* If a previously offlined CPU is brought back online again, the
404+
* originally allocated memory is reused in hv_common_cpu_init().
405+
*/
406406

407407
return 0;
408408
}

drivers/hv/vmbus_drv.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,7 +1372,7 @@ static int vmbus_bus_init(void)
13721372
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hyperv/vmbus:online",
13731373
hv_synic_init, hv_synic_cleanup);
13741374
if (ret < 0)
1375-
goto err_cpuhp;
1375+
goto err_alloc;
13761376
hyperv_cpuhp_online = ret;
13771377

13781378
ret = vmbus_connect();
@@ -1392,9 +1392,8 @@ static int vmbus_bus_init(void)
13921392

13931393
err_connect:
13941394
cpuhp_remove_state(hyperv_cpuhp_online);
1395-
err_cpuhp:
1396-
hv_synic_free();
13971395
err_alloc:
1396+
hv_synic_free();
13981397
if (vmbus_irq == -1) {
13991398
hv_remove_vmbus_handler();
14001399
} else {

0 commit comments

Comments
 (0)