misc: fix PCI vUART issue

The current code can't config PCI vUART by a unified HV Config and there
is a conflict between the HV vUART Config and PCI vUART Config.

This patch use PCI vUART Config to replace the HV vUART Config when the
vUART connection type is PCI and modify the launch scenario to make sure
the BDF is correct when user launch post launched VMs.

Tracked-On: #6690
Signed-off-by: Chenli Wei <chenli.wei@linux.intel.com>
This commit is contained in:
Chenli Wei 2022-06-21 14:27:56 +08:00 committed by acrnsi-robot
parent 40225337d2
commit 33086d5638
5 changed files with 103 additions and 71 deletions

View File

@ -55,6 +55,10 @@ class LaunchScript:
next_vbdf = self._free_slots.pop(0)
return next_vbdf
def remove_virtual_bdf(self, slot):
if slot in self._free_slots:
self._free_slots.remove(slot)
class PassThruDeviceOptions:
passthru_device_options = {
"0x0200": [".//PTM[text()='y']", "enable_ptm"], # Ethernet controller, added if PTM is enabled for the VM
@ -165,6 +169,8 @@ class LaunchScript:
if vbdf is None:
vbdf = self._vbdf_allocator.get_virtual_bdf()
else:
self._vbdf_allocator.remove_virtual_bdf(vbdf)
self.add_dynamic_dm_parameter("add_virtual_device", f"{vbdf} {kind} {options}")
def add_passthru_device(self, bus, dev, fun, options=""):
@ -253,6 +259,9 @@ def generate_for_one_vm(board_etree, hv_scenario_etree, vm_scenario_etree, vm_id
# Emulated PCI devices
script.add_virtual_device("hostbridge", vbdf="0:0")
#ivshmem and vuart must be the first virtual devices generated before the others except hostbridge and LPC
#ivshmem and vuart own reserved slots which setting by user
for ivshmem in eval_xpath_all(vm_scenario_etree, f"//IVSHMEM_REGION[PROVIDED_BY = 'Device Model' and .//VM_NAME = '{vm_name}']"):
script.add_virtual_device("ivshmem", options=f"dm:/{ivshmem.find('NAME').text},{ivshmem.find('IVSHMEM_SIZE').text}")
@ -262,9 +271,14 @@ def generate_for_one_vm(board_etree, hv_scenario_etree, vm_scenario_etree, vm_id
if eval_xpath(vm_scenario_etree, ".//console_vuart/text()") == "PCI":
script.add_virtual_device("uart", options="vuart_idx:0")
for idx, conn in enumerate(eval_xpath_all(hv_scenario_etree, f".//vuart_connection[endpoint/vm_name = '{vm_name}']"), start=1):
if eval_xpath(conn, "./type/text()") == "pci":
script.add_virtual_device("uart", options=f"vuart_idx:{idx}")
for idx, conn in enumerate(eval_xpath_all(hv_scenario_etree, f"//vuart_connection[endpoint/vm_name/text() = '{vm_name}']"), start=1):
if eval_xpath(conn, f"./type/text()") == "pci":
vbdf = eval_xpath(conn, f"./endpoint[vm_name/text() = '{vm_name}']/vbdf/text()")
if vbdf is not None:
slot = int((vbdf.split(":")[1].split(".")[0]), 16)
else:
slot = None
script.add_virtual_device("uart", slot, options=f"vuart_idx:{idx}")
# Mediated PCI devices, including virtio
for usb_xhci in eval_xpath_all(vm_scenario_etree, ".//usb_xhci/usb_dev[text() != '']/text()"):

View File

@ -109,15 +109,20 @@ class AddrWindow(namedtuple(
return False
return True
def insert_vuart_to_dev_dict(scenario_etree, devdict_32bits):
def insert_vuart_to_dev_dict(scenario_etree, vm_id, devdict_32bits):
console_vuart = scenario_etree.xpath(f"./console_vuart[base != 'INVALID_PCI_BASE']/@id")
communication_vuarts = scenario_etree.xpath(f".//communication_vuart[base != 'INVALID_PCI_BASE']/@id")
for vuart_id in console_vuart:
devdict_32bits[(f"{VUART}_{vuart_id}", "bar0")] = PCI_VUART_VBAR0_SIZE
devdict_32bits[(f"{VUART}_{vuart_id}", "bar1")] = PCI_VUART_VBAR1_SIZE
for vuart_id in communication_vuarts:
devdict_32bits[(f"{VUART}_{vuart_id}", "bar0")] = PCI_VUART_VBAR0_SIZE
devdict_32bits[(f"{VUART}_{vuart_id}", "bar1")] = PCI_VUART_VBAR1_SIZE
vm_name = common.get_node(f"//vm[@id = '{vm_id}']/name/text()", scenario_etree)
communication_vuarts = scenario_etree.xpath(f"//vuart_connection[endpoint/vm_name/text() = '{vm_name}']")
for vuart_id, vuart in enumerate(communication_vuarts, start=1):
connection_type = common.get_node(f"./type/text()", vuart)
if connection_type == "pci":
devdict_32bits[(f"{VUART}_{vuart_id}", "bar0")] = PCI_VUART_VBAR0_SIZE
devdict_32bits[(f"{VUART}_{vuart_id}", "bar1")] = PCI_VUART_VBAR1_SIZE
def insert_legacy_vuart_to_dev_dict(vm_node, devdict_io_port):
legacy_vuart = vm_node.xpath(f".//legacy_vuart[base = 'CONFIG_COM_BASE']/@id")
@ -409,7 +414,7 @@ def allocate_pci_bar(board_etree, scenario_etree, allocation_etree):
devdict_32bits = {}
devdict_64bits = {}
insert_vuart_to_dev_dict(vm_node, devdict_32bits)
insert_vuart_to_dev_dict(scenario_etree, vm_id, devdict_32bits)
insert_ivsheme_to_dev_dict(scenario_etree, devdict_32bits, devdict_64bits, vm_id)
insert_pt_devs_to_dev_dict(board_etree, vm_node, devdict_32bits, devdict_64bits)

View File

@ -331,8 +331,13 @@
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="console_vuart" select="count(./console_vuart/base[text() = 'PCI_VUART'])" />
<xsl:variable name="communication_vuart" select="count(./communication_vuart/base[text() = 'PCI_VUART'])" />
<xsl:variable name="vm_name" select="./name" />
<xsl:variable name="communication_vuart">
<xsl:value-of select="count(//vuart_connection[type = 'pci']/endpoint[vm_name/text() = $vm_name])" />
</xsl:variable>
<xsl:variable name="pci_devs" select="count(./pci_devs/pci_dev[text() != ''])" />
<xsl:variable name="pci_hostbridge" select="1" />
<xsl:variable name="virtual_root_port">

View File

@ -46,7 +46,7 @@
</xsl:if>
<xsl:call-template name="ivshmem_shm_mem" />
<xsl:apply-templates select="console_vuart" />
<xsl:apply-templates select="communication_vuart" />
<xsl:call-template name="communication_vuart" />
<xsl:if test="acrn:is-pre-launched-vm(load_order)">
<xsl:apply-templates select="pci_devs" />
</xsl:if>
@ -95,32 +95,55 @@
</xsl:if>
</xsl:template>
<xsl:template match="communication_vuart">
<xsl:if test="base != 'INVALID_PCI_BASE'">
<xsl:variable name="vm_id" select="../@id" />
<xsl:variable name="dev_name" select="concat('VUART_', @id)" />
<xsl:text>{</xsl:text>
<xsl:value-of select="$newline" />
<xsl:value-of select="acrn:initializer('vuart_idx', @id, '')" />
<xsl:value-of select="acrn:initializer('emu_type', 'PCI_DEV_TYPE_HVEMUL', '')" />
<xsl:value-of select="acrn:initializer('vdev_ops', '&amp;vmcs9900_ops', '')" />
<xsl:choose>
<xsl:when test="acrn:is-post-launched-vm(../load_order)">
<xsl:value-of select="acrn:initializer('vbar_base[0]', 'INVALID_PCI_BASE', '')" />
<xsl:value-of select="acrn:initializer('vbdf.value', 'UNASSIGNED_VBDF', '')" />
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="//vm[@id = $vm_id]/device[@name = $dev_name]/bar">
<xsl:value-of select="acrn:initializer(concat('vbar_base[', @id,']'), concat(text(), 'UL'), '')" />
</xsl:for-each>
<xsl:value-of select="acrn:initializer('vbdf.bits', acrn:get-vbdf(../@id, $dev_name), '')" />
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="acrn:initializer('t_vuart.vm_id', target_vm_id, '')" />
<xsl:value-of select="acrn:initializer('t_vuart.vuart_id', target_uart_id, '')" />
<xsl:template name="communication_vuart">
<xsl:variable name="vm_id" select="@id" />
<xsl:variable name="vm_name" select="name/text()" />
<xsl:variable name="load_order" select="load_order/text()" />
<xsl:for-each select="//vuart_connection[endpoint/vm_name/text() = $vm_name]">
<xsl:variable name="connection_name" select="name/text()" />
<xsl:if test="./type/text() = 'pci'">
<xsl:variable name="vuart_id" select="position()"/>
<xsl:variable name="dev_name" select="concat('VUART_', $vuart_id)" />
<xsl:text>{</xsl:text>
<xsl:value-of select="$newline" />
<xsl:value-of select="acrn:initializer('vuart_idx', $vuart_id, '')" />
<xsl:value-of select="acrn:initializer('emu_type', 'PCI_DEV_TYPE_HVEMUL', '')" />
<xsl:value-of select="acrn:initializer('vdev_ops', '&amp;vmcs9900_ops', '')" />
<xsl:for-each select="endpoint">
<xsl:choose>
<xsl:when test="vm_name = $vm_name">
<xsl:choose>
<xsl:when test="acrn:is-post-launched-vm($load_order)">
<xsl:value-of select="acrn:initializer('vbar_base[0]', 'INVALID_PCI_BASE', '')" />
<xsl:value-of select="acrn:initializer('vbdf.value', 'UNASSIGNED_VBDF')" />
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="//vm[@id = $vm_id]/device[@name = $dev_name]/bar">
<xsl:value-of select="acrn:initializer(concat('vbar_base[', @id,']'), concat(text(), 'UL'), '')" />
</xsl:for-each>
<xsl:variable name="b" select="substring-before(vbdf/text(), ':')" />
<xsl:variable name="d" select="substring-before(substring-after(vbdf/text(), ':'), '.')" />
<xsl:variable name="f" select="substring-after(vbdf/text(), '.')" />
<xsl:value-of select="acrn:initializer('vbdf.bits', concat('{', '0x', $b, ', ', '0x', $d, ', ', '0x', $f, '}'))" />
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="target_name" select="vm_name" />
<xsl:value-of select="acrn:initializer('t_vuart.vm_id', concat(//vm[name = $target_name]/@id, 'U'))" />
<xsl:for-each select="//vuart_connection[endpoint/vm_name = $target_name]">
<xsl:variable name="uart_num" select="position()"/>
<xsl:if test="name = $connection_name">
<xsl:value-of select="acrn:initializer('t_vuart.vuart_id', concat($uart_num, 'U'))" />
</xsl:if>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:text>},</xsl:text>
<xsl:value-of select="$newline" />
</xsl:if>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="pci_devs">

View File

@ -296,42 +296,27 @@
<xsl:variable name="type" select="type/text()" />
<xsl:variable name="vuart_id" select="position()"/>
<xsl:value-of select="acrn:initializer(concat('vuart[', $vuart_id, ']'), '{', true())" />
<xsl:choose>
<xsl:when test="$type = 'legacy'">
<xsl:value-of select="acrn:initializer('type', 'VUART_LEGACY_PIO')" />
</xsl:when>
<xsl:when test="$type = 'pci'">
<xsl:value-of select="acrn:initializer('type', 'VUART_PCI')" />
</xsl:when>
</xsl:choose>
<xsl:value-of select="acrn:initializer('irq', concat(//allocation-data/acrn-config/vm[@id=$vm_id]/legacy_vuart[@id=$vuart_id]/irq, 'U'))" />
<xsl:for-each select="endpoint">
<xsl:choose>
<xsl:when test="vm_name = $vmname">
<xsl:choose>
<xsl:when test="$type = 'legacy'">
<xsl:value-of select="acrn:initializer('addr.port_base', concat(io_port, 'U'))" />
</xsl:when>
<xsl:when test="$type = 'pci'">
<xsl:variable name="b" select="substring-before(vbdf/text(), ':')" />
<xsl:variable name="d" select="substring-before(substring-after(vbdf/text(), ':'), '.')" />
<xsl:variable name="f" select="substring-after(vbdf/text(), '.')" />
<xsl:value-of select="acrn:initializer('addr.bdf', concat('{', $b, ', ', $d, ', ', $f, '}'))" />
</xsl:when>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="target_name" select="vm_name" />
<xsl:value-of select="acrn:initializer('t_vuart.vm_id', concat(//vm[name = $target_name]/@id, 'U'))" />
<xsl:for-each select="//vuart_connection[endpoint/vm_name = $target_name]">
<xsl:variable name="uart_num" select="position()"/>
<xsl:if test="name = $connection_name">
<xsl:value-of select="acrn:initializer('t_vuart.vuart_id', concat($uart_num, 'U'))" />
</xsl:if>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:if test="$type = 'legacy'">
<xsl:value-of select="acrn:initializer('irq', concat(//allocation-data/acrn-config/vm[@id=$vm_id]/legacy_vuart[@id=$vuart_id]/irq, 'U'))" />
<xsl:value-of select="acrn:initializer('type', 'VUART_LEGACY_PIO')" />
<xsl:for-each select="endpoint">
<xsl:choose>
<xsl:when test="vm_name = $vmname">
<xsl:value-of select="acrn:initializer('addr.port_base', concat(io_port, 'U'))" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="target_name" select="vm_name" />
<xsl:value-of select="acrn:initializer('t_vuart.vm_id', concat(//vm[name = $target_name]/@id, 'U'))" />
<xsl:for-each select="//vuart_connection[endpoint/vm_name = $target_name]">
<xsl:variable name="uart_num" select="position()"/>
<xsl:if test="name = $connection_name">
<xsl:value-of select="acrn:initializer('t_vuart.vuart_id', concat($uart_num, 'U'))" />
</xsl:if>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:if>
<xsl:text>},</xsl:text>
<xsl:value-of select="$newline" />
</xsl:for-each>