FW: newbus and acpi issue on Hyper-V

From: Wei Hu <weh_at_microsoft.com>
Date: Fri, 14 Oct 2022 06:03:19 UTC
Hi,



We are working on enabling FreeBSD running on ARM64 Hyper-V at Microsoft. Right now we are hitting a road blocker which seems only happening on FreeBSD guest, due to its newbus architecture and how resources are presented in Hyper-V's ACPI tables. I am writing in hope to find a short term solution or workaround. Without it, it would be hard to make SRIOV work on ARM64 FreeBSD guests. Appreciate any inputs.



Here are the details. Hyper-V presents two system resources at two different places/nodes in its ACPI table.



1) PCI mmio resource in HID "ACPI0004", which is needed by the FreeBSD guest for SRIOV devices.



   Device (\_SB.VMOD)    <-- This is currently owned by acpi_syscontainer module on FreeBSD

    {

        Name (_HID, "ACPI0004" /* Module Device */)  // _HID: Hardware ID

        Name (_UID, Zero)  // _UID: Unique ID

        Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings

        {

            ...

        }

        CreateDWordField (_CRS, \_SB.VMOD._Y00._MIN, MIN6)  // _MIN: Minimum Base Address

        CreateDWordField (_CRS, \_SB.VMOD._Y00._MAX, MAX6)  // _MAX: Maximum Base Address

        CreateDWordField (_CRS, \_SB.VMOD._Y00._LEN, LEN6)  // _LEN: Length

        CreateQWordField (_CRS, \_SB.VMOD._Y01._MIN, MIN7)  // _MIN: Minimum Base Address

        CreateQWordField (_CRS, \_SB.VMOD._Y01._MAX, MAX7)  // _MAX: Maximum Base Address

        CreateQWordField (_CRS, \_SB.VMOD._Y01._LEN, LEN7)  // _LEN: Length

        Method (_INI, 0, NotSerialized)  // _INI: Initialize

        {

            MIN6 = MG2B /* \MG2B */

            LEN6 = MG2L /* \MG2L */

            Local0 = MG2L /* \MG2L */

            MAX6 = (MIN6 + Local0--)

            Local1 = (HMIB << 0x14)

            Local2 = (HMIL << 0x14)

            MIN7 = Local1

            LEN7 = Local2

            Local0 = Local2

            MAX7 = (MIN7 + Local0--)

        }

    }



2) Vmbus IRQ resource in HID "VMBus", which is needed to get Hyper-V vmbus interrupt to work on guests.

Device (\_SB.VMOD.VMBS)   <--- currently owned by vmbus_res module on FreeBSD

    {

        ...

        Name (_HID, "VMBus")  // _HID: Hardware ID

        Name (_UID, Zero)  // _UID: Unique ID

        ...

        Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings

        {

            Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, ,, )

            {

                0x00000012,

            }

        })

    }



On x86, FreeBSD just needs PCI mmio resource 1). We ignore the vmbus IRQ resource in the ACPI and pick a fixed vector for all cpu interrupt. But on ARM64, the guest needs all the information in order to make bus_alloc_resouce() to work for both interrupt and mmio. Therefore, the main Hyper-V device driver vmbus needs to be the child for both these nodes to make the resource allocation to work. But it seems to us that one device driver can only have one parent in the newbus architecture, we can only make one resource allocation to work in this scenario, either IRQ or mmio, but not both.



Following is a picture of current device tree on a AMD64 FreeBSD guest on Hyper-V



[cid:image002.png@01D8DF2F.A3DB8800]



As you can see vmbus module is under acpi_syscontainer which owns PCI mmio resource. The vmbus IRQ resouce is owned by vmbus_res module, which is just a place holder for this resouce and never been used on am64. On ARM64, vmbus module needs to be the child for both vmbus_res and acpi_syscontainer to get the both resources, which doesn't seem to be possible under newbus architecture.



Any suggestions or workarounds are welcome. Thanks in advacne.



Wei