Commit 5f054ef2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Merge tag 'hyperv-fixes-signed-20250718' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux

Pull hyperv fixes from Wei Liu:

 - Select use CONFIG_SYSFB only if EFI is enabled (Michael Kelley)

 - An assorted set of fixes to remove warnings for missing export.h
   header inclusion (Naman Jain)

 - An assorted set of fixes for when Linux run as the root partition
   for Microsoft Hypervisor (Mukesh Rathor, Nuno Das Neves, Stanislav
   Kinsburskii)

 - Fix the check for HYPERVISOR_CALLBACK_VECTOR (Naman Jain)

 - Fix fcopy tool to handle irregularities with size of ring buffer
   (Naman Jain)

 - Fix incorrect file path conversion in fcopy tool (Yasumasa Suenaga)

* tag 'hyperv-fixes-signed-20250718' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux:
  tools/hv: fcopy: Fix irregularities with size of ring buffer
  PCI: hv: Use the correct hypercall for unmasking interrupts on nested
  x86/hyperv: Expose hv_map_msi_interrupt()
  Drivers: hv: Use nested hypercall for post message and signal event
  x86/hyperv: Clean up hv_map/unmap_interrupt() return values
  x86/hyperv: Fix usage of cpu_online_mask to get valid cpu
  PCI: hv: Don't load the driver for baremetal root partition
  net: mana: Fix warnings for missing export.h header inclusion
  PCI: hv: Fix warnings for missing export.h header inclusion
  clocksource: hyper-v: Fix warnings for missing export.h header inclusion
  x86/hyperv: Fix warnings for missing export.h header inclusion
  Drivers: hv: Fix warnings for missing export.h header inclusion
  Drivers: hv: Fix the check for HYPERVISOR_CALLBACK_VECTOR
  tools/hv: fcopy: Fix incorrect file path conversion
  Drivers: hv: Select CONFIG_SYSFB only if EFI is enabled
parents 4f066b18 a4131a50
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include <linux/syscore_ops.h>
#include <clocksource/hyperv_timer.h>
#include <linux/highmem.h>
#include <linux/export.h>

void *hv_hypercall_pg;
EXPORT_SYMBOL_GPL(hv_hypercall_pg);
+41 −28
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@

#include <linux/pci.h>
#include <linux/irq.h>
#include <linux/export.h>
#include <asm/mshyperv.h>

static int hv_map_interrupt(union hv_device_id device_id, bool level,
@@ -46,7 +47,7 @@ static int hv_map_interrupt(union hv_device_id device_id, bool level,
	if (nr_bank < 0) {
		local_irq_restore(flags);
		pr_err("%s: unable to generate VP set\n", __func__);
		return EINVAL;
		return -EINVAL;
	}
	intr_desc->target.flags = HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET;

@@ -66,7 +67,7 @@ static int hv_map_interrupt(union hv_device_id device_id, bool level,
	if (!hv_result_success(status))
		hv_status_err(status, "\n");

	return hv_result(status);
	return hv_result_to_errno(status);
}

static int hv_unmap_interrupt(u64 id, struct hv_interrupt_entry *old_entry)
@@ -88,7 +89,10 @@ static int hv_unmap_interrupt(u64 id, struct hv_interrupt_entry *old_entry)
	status = hv_do_hypercall(HVCALL_UNMAP_DEVICE_INTERRUPT, input, NULL);
	local_irq_restore(flags);

	return hv_result(status);
	if (!hv_result_success(status))
		hv_status_err(status, "\n");

	return hv_result_to_errno(status);
}

#ifdef CONFIG_PCI_MSI
@@ -169,13 +173,34 @@ static union hv_device_id hv_build_pci_dev_id(struct pci_dev *dev)
	return dev_id;
}

static int hv_map_msi_interrupt(struct pci_dev *dev, int cpu, int vector,
				struct hv_interrupt_entry *entry)
/**
 * hv_map_msi_interrupt() - "Map" the MSI IRQ in the hypervisor.
 * @data:      Describes the IRQ
 * @out_entry: Hypervisor (MSI) interrupt entry (can be NULL)
 *
 * Map the IRQ in the hypervisor by issuing a MAP_DEVICE_INTERRUPT hypercall.
 *
 * Return: 0 on success, -errno on failure
 */
int hv_map_msi_interrupt(struct irq_data *data,
			 struct hv_interrupt_entry *out_entry)
{
	union hv_device_id device_id = hv_build_pci_dev_id(dev);
	struct irq_cfg *cfg = irqd_cfg(data);
	struct hv_interrupt_entry dummy;
	union hv_device_id device_id;
	struct msi_desc *msidesc;
	struct pci_dev *dev;
	int cpu;

	return hv_map_interrupt(device_id, false, cpu, vector, entry);
	msidesc = irq_data_get_msi_desc(data);
	dev = msi_desc_to_pci_dev(msidesc);
	device_id = hv_build_pci_dev_id(dev);
	cpu = cpumask_first(irq_data_get_effective_affinity_mask(data));

	return hv_map_interrupt(device_id, false, cpu, cfg->vector,
				out_entry ? out_entry : &dummy);
}
EXPORT_SYMBOL_GPL(hv_map_msi_interrupt);

static inline void entry_to_msi_msg(struct hv_interrupt_entry *entry, struct msi_msg *msg)
{
@@ -188,13 +213,11 @@ static inline void entry_to_msi_msg(struct hv_interrupt_entry *entry, struct msi
static int hv_unmap_msi_interrupt(struct pci_dev *dev, struct hv_interrupt_entry *old_entry);
static void hv_irq_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
{
	struct hv_interrupt_entry *stored_entry;
	struct irq_cfg *cfg = irqd_cfg(data);
	struct msi_desc *msidesc;
	struct pci_dev *dev;
	struct hv_interrupt_entry out_entry, *stored_entry;
	struct irq_cfg *cfg = irqd_cfg(data);
	const cpumask_t *affinity;
	int cpu;
	u64 status;
	int ret;

	msidesc = irq_data_get_msi_desc(data);
	dev = msi_desc_to_pci_dev(msidesc);
@@ -204,9 +227,6 @@ static void hv_irq_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
		return;
	}

	affinity = irq_data_get_effective_affinity_mask(data);
	cpu = cpumask_first_and(affinity, cpu_online_mask);

	if (data->chip_data) {
		/*
		 * This interrupt is already mapped. Let's unmap first.
@@ -219,15 +239,13 @@ static void hv_irq_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
		stored_entry = data->chip_data;
		data->chip_data = NULL;

		status = hv_unmap_msi_interrupt(dev, stored_entry);
		ret = hv_unmap_msi_interrupt(dev, stored_entry);

		kfree(stored_entry);

		if (status != HV_STATUS_SUCCESS) {
			hv_status_debug(status, "failed to unmap\n");
		if (ret)
			return;
	}
	}

	stored_entry = kzalloc(sizeof(*stored_entry), GFP_ATOMIC);
	if (!stored_entry) {
@@ -235,15 +253,14 @@ static void hv_irq_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
		return;
	}

	status = hv_map_msi_interrupt(dev, cpu, cfg->vector, &out_entry);
	if (status != HV_STATUS_SUCCESS) {
	ret = hv_map_msi_interrupt(data, stored_entry);
	if (ret) {
		kfree(stored_entry);
		return;
	}

	*stored_entry = out_entry;
	data->chip_data = stored_entry;
	entry_to_msi_msg(&out_entry, msg);
	entry_to_msi_msg(data->chip_data, msg);

	return;
}
@@ -257,7 +274,6 @@ static void hv_teardown_msi_irq(struct pci_dev *dev, struct irq_data *irqd)
{
	struct hv_interrupt_entry old_entry;
	struct msi_msg msg;
	u64 status;

	if (!irqd->chip_data) {
		pr_debug("%s: no chip data\n!", __func__);
@@ -270,10 +286,7 @@ static void hv_teardown_msi_irq(struct pci_dev *dev, struct irq_data *irqd)
	kfree(irqd->chip_data);
	irqd->chip_data = NULL;

	status = hv_unmap_msi_interrupt(dev, &old_entry);

	if (status != HV_STATUS_SUCCESS)
		hv_status_err(status, "\n");
	(void)hv_unmap_msi_interrupt(dev, &old_entry);
}

static void hv_msi_free_irq(struct irq_domain *domain,
+1 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/export.h>
#include <asm/svm.h>
#include <asm/sev.h>
#include <asm/io.h>
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@


#include <linux/types.h>
#include <linux/export.h>
#include <hyperv/hvhdk.h>
#include <asm/mshyperv.h>
#include <asm/tlbflush.h>
+2 −20
Original line number Diff line number Diff line
@@ -112,12 +112,6 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
	return hv_status;
}

/* Hypercall to the L0 hypervisor */
static inline u64 hv_do_nested_hypercall(u64 control, void *input, void *output)
{
	return hv_do_hypercall(control | HV_HYPERCALL_NESTED, input, output);
}

/* Fast hypercall with 8 bytes of input and no output */
static inline u64 _hv_do_fast_hypercall8(u64 control, u64 input1)
{
@@ -165,13 +159,6 @@ static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
	return _hv_do_fast_hypercall8(control, input1);
}

static inline u64 hv_do_fast_nested_hypercall8(u16 code, u64 input1)
{
	u64 control = (u64)code | HV_HYPERCALL_FAST_BIT | HV_HYPERCALL_NESTED;

	return _hv_do_fast_hypercall8(control, input1);
}

/* Fast hypercall with 16 bytes of input */
static inline u64 _hv_do_fast_hypercall16(u64 control, u64 input1, u64 input2)
{
@@ -223,13 +210,6 @@ static inline u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
	return _hv_do_fast_hypercall16(control, input1, input2);
}

static inline u64 hv_do_fast_nested_hypercall16(u16 code, u64 input1, u64 input2)
{
	u64 control = (u64)code | HV_HYPERCALL_FAST_BIT | HV_HYPERCALL_NESTED;

	return _hv_do_fast_hypercall16(control, input1, input2);
}

extern struct hv_vp_assist_page **hv_vp_assist_page;

static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
@@ -262,6 +242,8 @@ static inline void hv_apic_init(void) {}

struct irq_domain *hv_create_pci_msi_domain(void);

int hv_map_msi_interrupt(struct irq_data *data,
			 struct hv_interrupt_entry *out_entry);
int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector,
		struct hv_interrupt_entry *entry);
int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);
Loading