Commit c00b2850 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'hyperv-next-signed-20250602' of...

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

Pull hyperv updates from Wei Liu:

 - Support for Virtual Trust Level (VTL) on arm64 (Roman Kisel)

 - Fixes for Hyper-V UIO driver (Long Li)

 - Fixes for Hyper-V PCI driver (Michael Kelley)

 - Select CONFIG_SYSFB for Hyper-V guests (Michael Kelley)

 - Documentation updates for Hyper-V VMBus (Michael Kelley)

 - Enhance logging for hv_kvp_daemon (Shradha Gupta)

* tag 'hyperv-next-signed-20250602' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: (23 commits)
  Drivers: hv: Always select CONFIG_SYSFB for Hyper-V guests
  Drivers: hv: vmbus: Add comments about races with "channels" sysfs dir
  Documentation: hyperv: Update VMBus doc with new features and info
  PCI: hv: Remove unnecessary flex array in struct pci_packet
  Drivers: hv: Remove hv_alloc/free_* helpers
  Drivers: hv: Use kzalloc for panic page allocation
  uio_hv_generic: Align ring size to system page
  uio_hv_generic: Use correct size for interrupt and monitor pages
  Drivers: hv: Allocate interrupt and monitor pages aligned to system page boundary
  arch/x86: Provide the CPU number in the wakeup AP callback
  x86/hyperv: Fix APIC ID and VP index confusion in hv_snp_boot_ap()
  PCI: hv: Get vPCI MSI IRQ domain from DeviceTree
  ACPI: irq: Introduce acpi_get_gsi_dispatcher()
  Drivers: hv: vmbus: Introduce hv_get_vmbus_root_device()
  Drivers: hv: vmbus: Get the IRQ number from DeviceTree
  dt-bindings: microsoft,vmbus: Add interrupt and DMA coherence properties
  arm64, x86: hyperv: Report the VTL the system boots in
  arm64: hyperv: Initialize the Virtual Trust Level field
  Drivers: hv: Provide arch-neutral implementation of get_vtl()
  Drivers: hv: Enable VTL mode for arm64
  ...
parents 04446eee 96959283
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -10,8 +10,8 @@ maintainers:
  - Saurabh Sengar <ssengar@linux.microsoft.com>

description:
  VMBus is a software bus that implement the protocols for communication
  between the root or host OS and guest OSs (virtual machines).
  VMBus is a software bus that implements the protocols for communication
  between the root or host OS and guest OS'es (virtual machines).

properties:
  compatible:
@@ -25,9 +25,16 @@ properties:
  '#size-cells':
    const: 1

  dma-coherent: true

  interrupts:
    maxItems: 1
    description: Interrupt is used to report a message from the host.

required:
  - compatible
  - ranges
  - interrupts
  - '#address-cells'
  - '#size-cells'

@@ -35,6 +42,8 @@ additionalProperties: false

examples:
  - |
    #include <dt-bindings/interrupt-controller/irq.h>
    #include <dt-bindings/interrupt-controller/arm-gic.h>
    soc {
        #address-cells = <2>;
        #size-cells = <1>;
@@ -49,6 +58,9 @@ examples:
                #address-cells = <2>;
                #size-cells = <1>;
                ranges = <0x0f 0xf0000000 0x0f 0xf0000000 0x10000000>;
                dma-coherent;
                interrupt-parent = <&gic>;
                interrupts = <GIC_PPI 2 IRQ_TYPE_EDGE_RISING>;
            };
        };
    };
+24 −4
Original line number Diff line number Diff line
@@ -250,10 +250,18 @@ interrupts are not Linux IRQs, there are no entries in /proc/interrupts
or /proc/irq corresponding to individual VMBus channel interrupts.

An online CPU in a Linux guest may not be taken offline if it has
VMBus channel interrupts assigned to it.  Any such channel
interrupts must first be manually reassigned to another CPU as
described above.  When no channel interrupts are assigned to the
CPU, it can be taken offline.
VMBus channel interrupts assigned to it. Starting in kernel v6.15,
any such interrupts are automatically reassigned to some other CPU
at the time of offlining. The "other" CPU is chosen by the
implementation and is not load balanced or otherwise intelligently
determined. If the CPU is onlined again, channel interrupts previously
assigned to it are not moved back. As a result, after multiple CPUs
have been offlined, and perhaps onlined again, the interrupt-to-CPU
mapping may be scrambled and non-optimal. In such a case, optimal
assignments must be re-established manually. For kernels v6.14 and
earlier, any conflicting channel interrupts must first be manually
reassigned to another CPU as described above. Then when no channel
interrupts are assigned to the CPU, it can be taken offline.

The VMBus channel interrupt handling code is designed to work
correctly even if an interrupt is received on a CPU other than the
@@ -324,3 +332,15 @@ rescinded, neither Hyper-V nor Linux retains any state about
its previous existence. Such a device might be re-added later,
in which case it is treated as an entirely new device. See
vmbus_onoffer_rescind().

For some devices, such as the KVP device, Hyper-V automatically
sends a rescind message when the primary channel is closed,
likely as a result of unbinding the device from its driver.
The rescind causes Linux to remove the device. But then Hyper-V
immediately reoffers the device to the guest, causing a new
instance of the device to be created in Linux. For other
devices, such as the synthetic SCSI and NIC devices, closing the
primary channel does *not* result in Hyper-V sending a rescind
message. The device continues to exist in Linux on the VMBus,
but with no driver bound to it. The same driver or a new driver
can subsequently be bound to the existing instance of the device.
+48 −5
Original line number Diff line number Diff line
@@ -28,6 +28,48 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
}
EXPORT_SYMBOL_GPL(hv_get_hypervisor_version);

#ifdef CONFIG_ACPI

static bool __init hyperv_detect_via_acpi(void)
{
	if (acpi_disabled)
		return false;
	/*
	 * Hypervisor ID is only available in ACPI v6+, and the
	 * structure layout was extended in v6 to accommodate that
	 * new field.
	 *
	 * At the very minimum, this check makes sure not to read
	 * past the FADT structure.
	 *
	 * It is also needed to catch running in some unknown
	 * non-Hyper-V environment that has ACPI 5.x or less.
	 * In such a case, it can't be Hyper-V.
	 */
	if (acpi_gbl_FADT.header.revision < 6)
		return false;
	return strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8) == 0;
}

#else

static bool __init hyperv_detect_via_acpi(void)
{
	return false;
}

#endif

static bool __init hyperv_detect_via_smccc(void)
{
	uuid_t hyperv_uuid = UUID_INIT(
		0x58ba324d, 0x6447, 0x24cd,
		0x75, 0x6c, 0xef, 0x8e,
		0x24, 0x70, 0x59, 0x16);

	return arm_smccc_hypervisor_has_uuid(&hyperv_uuid);
}

static int __init hyperv_init(void)
{
	struct hv_get_vp_registers_output	result;
@@ -36,13 +78,11 @@ static int __init hyperv_init(void)

	/*
	 * Allow for a kernel built with CONFIG_HYPERV to be running in
	 * a non-Hyper-V environment, including on DT instead of ACPI.
	 * a non-Hyper-V environment.
	 *
	 * In such cases, do nothing and return success.
	 */
	if (acpi_disabled)
		return 0;

	if (strncmp((char *)&acpi_gbl_FADT.hypervisor_id, "MsHyperV", 8))
	if (!hyperv_detect_via_acpi() && !hyperv_detect_via_smccc())
		return 0;

	/* Setup the guest ID */
@@ -77,6 +117,9 @@ static int __init hyperv_init(void)

	if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
		hv_get_partition_id();
	ms_hyperv.vtl = get_vtl();
	if (ms_hyperv.vtl > 0) /* non default VTL */
		pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);

	ms_hyperv_late_init();

+6 −4
Original line number Diff line number Diff line
@@ -270,6 +270,7 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
	u32 feature;
	u8 action;
	gpa_t gpa;
	uuid_t uuid;

	action = kvm_smccc_get_action(vcpu, func_id);
	switch (action) {
@@ -355,10 +356,11 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
			val[0] = gpa;
		break;
	case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
		val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0;
		val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1;
		val[2] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2;
		val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3;
		uuid = ARM_SMCCC_VENDOR_HYP_UID_KVM;
		val[0] = smccc_uuid_to_reg(&uuid, 0);
		val[1] = smccc_uuid_to_reg(&uuid, 1);
		val[2] = smccc_uuid_to_reg(&uuid, 2);
		val[3] = smccc_uuid_to_reg(&uuid, 3);
		break;
	case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
		val[0] = smccc_feat->vendor_hyp_bmap;
+2 −11
Original line number Diff line number Diff line
@@ -869,12 +869,12 @@ static void *snp_alloc_vmsa_page(int cpu)
	return page_address(p + 1);
}

static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip, unsigned int cpu)
{
	struct sev_es_save_area *cur_vmsa, *vmsa;
	struct svsm_ca *caa;
	u8 sipi_vector;
	int cpu, ret;
	int ret;
	u64 cr4;

	/*
@@ -895,15 +895,6 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)

	/* Override start_ip with known protected guest start IP */
	start_ip = real_mode_header->sev_es_trampoline_start;

	/* Find the logical CPU for the APIC ID */
	for_each_present_cpu(cpu) {
		if (arch_match_cpu_phys_id(cpu, apic_id))
			break;
	}
	if (cpu >= nr_cpu_ids)
		return -EINVAL;

	cur_vmsa = per_cpu(sev_vmsa, cpu);

	/*
Loading