Commit 692b7dc8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'hyperv-fixes-signed-20230619' of...

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
parents dbad9ce9 067d6ec7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ static int __init hyperv_init(void)
	if (ret)
		return ret;

	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm64/hyperv_init:online",
	ret = cpuhp_setup_state(CPUHP_AP_HYPERV_ONLINE, "arm64/hyperv_init:online",
				hv_common_cpu_init, hv_common_cpu_die);
	if (ret < 0) {
		hv_common_free();
+1 −1
Original line number Diff line number Diff line
@@ -416,7 +416,7 @@ void __init hyperv_init(void)
			goto free_vp_assist_page;
	}

	cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",
	cpuhp = cpuhp_setup_state(CPUHP_AP_HYPERV_ONLINE, "x86/hyperv_init:online",
				  hv_cpu_init, hv_cpu_die);
	if (cpuhp < 0)
		goto free_ghcb_page;
+2 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ void __init hv_vtl_init_platform(void)
{
	pr_info("Linux runs in Hyper-V Virtual Trust Level\n");

	x86_platform.realmode_reserve = x86_init_noop;
	x86_platform.realmode_init = x86_init_noop;
	x86_init.irqs.pre_vector_init = x86_init_noop;
	x86_init.timers.timer_init = x86_init_noop;

+16 −2
Original line number Diff line number Diff line
@@ -829,11 +829,22 @@ static void vmbus_wait_for_unload(void)
		if (completion_done(&vmbus_connection.unload_event))
			goto completed;

		for_each_online_cpu(cpu) {
		for_each_present_cpu(cpu) {
			struct hv_per_cpu_context *hv_cpu
				= per_cpu_ptr(hv_context.cpu_context, cpu);

			/*
			 * In a CoCo VM the synic_message_page is not allocated
			 * in hv_synic_alloc(). Instead it is set/cleared in
			 * hv_synic_enable_regs() and hv_synic_disable_regs()
			 * such that it is set only when the CPU is online. If
			 * not all present CPUs are online, the message page
			 * might be NULL, so skip such CPUs.
			 */
			page_addr = hv_cpu->synic_message_page;
			if (!page_addr)
				continue;

			msg = (struct hv_message *)page_addr
				+ VMBUS_MESSAGE_SINT;

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

		page_addr = hv_cpu->synic_message_page;
		if (!page_addr)
			continue;

		msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
		msg->header.message_type = HVMSG_NONE;
	}
+24 −24
Original line number Diff line number Diff line
@@ -364,6 +364,12 @@ int hv_common_cpu_init(unsigned int cpu)
	flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL;

	inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);

	/*
	 * hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already
	 * allocated if this CPU was previously online and then taken offline
	 */
	if (!*inputarg) {
		*inputarg = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
		if (!(*inputarg))
			return -ENOMEM;
@@ -372,6 +378,7 @@ int hv_common_cpu_init(unsigned int cpu)
			outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
			*outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE;
		}
	}

	msr_vp_index = hv_get_register(HV_REGISTER_VP_INDEX);

@@ -385,24 +392,17 @@ int hv_common_cpu_init(unsigned int cpu)

int hv_common_cpu_die(unsigned int cpu)
{
	unsigned long flags;
	void **inputarg, **outputarg;
	void *mem;

	local_irq_save(flags);

	inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
	mem = *inputarg;
	*inputarg = NULL;

	if (hv_root_partition) {
		outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
		*outputarg = NULL;
	}

	local_irq_restore(flags);

	kfree(mem);
	/*
	 * The hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory
	 * is not freed when the CPU goes offline as the hyperv_pcpu_input_arg
	 * may be used by the Hyper-V vPCI driver in reassigning interrupts
	 * as part of the offlining process.  The interrupt reassignment
	 * happens *after* the CPUHP_AP_HYPERV_ONLINE state has run and
	 * called this function.
	 *
	 * If a previously offlined CPU is brought back online again, the
	 * originally allocated memory is reused in hv_common_cpu_init().
	 */

	return 0;
}
Loading