config tool: ivshmem: new design for ivshmem

According to the new design of DX, implement ivshmem configuration
and generate hv related files.

Tracked-On: #6690
Signed-off-by: Yuanyuan Zhao <yuanyuan.zhao@linux.intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Yuanyuan Zhao 2022-02-14 06:33:21 +00:00 committed by acrnsi-robot
parent 3d5c3c4754
commit 9670caabf0
8 changed files with 138 additions and 89 deletions

View File

@ -139,39 +139,83 @@ Read more about the available scheduling options in :ref:`cpu_sharing`.</xs:docu
<xs:union memberTypes="None SerialConsoleType" />
</xs:simpleType>
<xs:simpleType name="IVSHMEMRegionType">
<xs:annotation>
<xs:documentation>Either empty or a string naming the shared region,
its size, and the VM IDs that can access it, such as ``hv:/shm_region_0, 2, 0:2``.
See :ref:`ivshmem-hv` for more information.</xs:documentation>
</xs:annotation>
<xs:simpleType name="VMNameType">
<xs:restriction base="xs:string">
<xs:pattern value="|((hv)|(dm)):/\w+,\s?\d+\s?,\s?\d\s?(:\s?\d\s?)+" />
<xs:pattern value="([a-zA-Z0-9_\-]){1,15}" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="VBDFType">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9A-Fa-f]{1,2}:[0-1][0-9A-Fa-f].[0-7]" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="IVSHMEMVM">
<xs:sequence>
<xs:element name="VM_NAME" type="VMNameType">
<xs:annotation>
<xs:documentation>Name of the VM which use this IVSHMEM.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="VBDF" type = "VBDFType">
<xs:annotation>
<xs:documentation>Bus, Device and function of the virtual
device in VM . Set in hex.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="IVSHMEMVMS">
<xs:sequence>
<xs:element name="IVSHMEM_VM" type="IVSHMEMVM" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Set each VM which use this IVSHMEM.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="IVSHMEMSize">
<xs:restriction base="xs:integer">
<xs:enumeration value="2" />
<xs:enumeration value="4" />
<xs:enumeration value="8" />
<xs:enumeration value="16" />
<xs:enumeration value="32" />
<xs:enumeration value="64" />
<xs:enumeration value="128" />
<xs:enumeration value="256" />
<xs:enumeration value="512" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="IVSHMEMRegionType">
<xs:sequence>
<xs:element name="IVSHMEM_SIZE" type="IVSHMEMSize" default="2">
<xs:annotation>
<xs:documentation>Memory size of inter-VM shared memory (IVSHMEM)
in megabytes. The value should be a power of 2
and no more than 512.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="IVSHMEM_VMS" type="IVSHMEMVMS">
<xs:annotation>
<xs:documentation>Set all VMs which use this IVSHMEM.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="IVSHMEMInfo">
<xs:sequence>
<xs:element name="IVSHMEM_ENABLED" type="Boolean" default="n">
<xs:annotation>
<xs:documentation>Enable inter-VM shared memory (IVSHMEM)
feature.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="IVSHMEM_REGION" type="IVSHMEMRegionType" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>A comma-separated list with the inter-VM shared memory region name,
size, and VM IDs that may communicate using this shared region:
* Prefix the region ``name`` with ``hv:/`` (for an hv-land solution).
(See :ref:`ivshmem-hld` for details.)
* Specify the region ``size`` in MB. Must be a power of 2, e.g., 2, 4,
8, 16, up to 512.
* Specify all VM IDs that may use this shared memory area,
separated by a ``:``. For example, use ``0:2`` to share this area between
VMs 0 and 2, or ``0:1:2`` (to let VMs 0, 1, and 2 share this area).</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="IVSHMEM_REGION" type="IVSHMEMRegionType" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Set a inter-VM shared memory.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>

View File

@ -38,14 +38,14 @@ def insert_vuart_to_dev_dict(scenario_etree, devdict, used):
used.append(free_bdf)
def insert_ivsheme_to_dev_dict(scenario_etree, devdict, vm_id, used):
shmem_regions = lib.lib.get_shmem_regions(scenario_etree)
shmem_regions = lib.lib.get_ivshmem_regions_by_tree(scenario_etree)
if vm_id not in shmem_regions:
return
shmems = shmem_regions.get(vm_id)
for shm in shmems.values():
free_bdf = find_unused_bdf(used)
devdict[f"{IVSHMEM}_{shm.get('id')}"] = free_bdf
used.append(free_bdf)
bdf = lib.lib.BusDevFunc.from_str(shm.get('vbdf'))
devdict[f"{IVSHMEM}_{shm.get('id')}"] = bdf
used.append(bdf)
def insert_pt_devs_to_dev_dict(vm_node_etree, devdict, used):
"""

View File

@ -126,7 +126,7 @@ def insert_legacy_vuart_to_dev_dict(vm_node, devdict_io_port):
devdict_io_port[(f"{LEGACY_VUART}_{vuart_id}", "base")] = LEGACY_VUART_IO_PORT_SIZE
def insert_ivsheme_to_dev_dict(scenario_etree, devdict_32bits, devdict_64bits, vm_id):
shmem_regions = lib.lib.get_shmem_regions(scenario_etree)
shmem_regions = lib.lib.get_ivshmem_regions_by_tree(scenario_etree)
if vm_id not in shmem_regions:
return
shmems = shmem_regions.get(vm_id)

View File

@ -89,29 +89,35 @@ def get_native_ttys():
native_ttys[tty] = tmp_dic
return native_ttys
def get_shmem_regions(etree):
ivshmem_enabled = common.get_node("//IVSHMEM_ENABLED/text()", etree)
def get_ivshmem_regions_by_tree(etree):
ivshmem_enabled = get_ivshmem_enabled_by_tree(etree)
if ivshmem_enabled == 'n':
return {}
# <IVSHMEM_REGION> format is shm_name, shm_size, VM IDs
# example: hv:/shm_region_0, 2, 0:2
ivshmem_regions = etree.xpath("//IVSHMEM_REGION")
shmem_regions = {}
for idx in range(len(ivshmem_regions)):
shm_string = ivshmem_regions[idx].text
if shm_string is None:
shm_name = ivshmem_regions[idx].get('name')
if shm_name is None:
continue
shm_string_list = shm_string.split(',')
shm_name = shm_string_list[0].strip()
shm_size = shm_string_list[1].strip()
vmid_list = [vm_id.strip() for vm_id in shm_string_list[2].split(':')]
for vm_id in vmid_list:
shm_size = common.get_node("./IVSHMEM_SIZE/text()", ivshmem_regions[idx])
shm_vm_list = ivshmem_regions[idx].xpath(".//IVSHMEM_VM")
for shm_vm in shm_vm_list:
vm_name = common.get_node("./VM_NAME/text()", shm_vm)
vm_id = common.get_node(f"//vm[name = '{vm_name}']/@id", etree)
vbdf = common.get_node("./VBDF/text()", shm_vm)
if vm_id not in shmem_regions:
shmem_regions[vm_id] = {}
shmem_regions[vm_id][shm_name] = {'id' : str(idx), 'size' : shm_size}
shmem_regions[vm_id][shm_name] = {'id' : str(idx), 'size' : shm_size, 'vbdf' : vbdf}
return shmem_regions
def get_ivshmem_enabled_by_tree(etree):
ivshmem_vms = etree.xpath("//IVSHMEM_VM")
shmem_enabled = 'n'
if len(ivshmem_vms) != 0:
shmem_enabled = 'y'
return shmem_enabled
def is_pre_launched_vm(vm_type):
if vm_type in PRE_LAUNCHED_VMS_TYPE:
return True

View File

@ -141,7 +141,7 @@
<xsl:call-template name="boolean-by-key-value">
<xsl:with-param name="key" select="'IVSHMEM_ENABLED'" />
<xsl:with-param name="value" select="IVSHMEM/IVSHMEM_ENABLED" />
<xsl:with-param name="value" select="count(//hv//IVSHMEM/IVSHMEM_REGION) > 0" />
</xsl:call-template>
</xsl:template>

20
misc/config_tools/xforms/ivshmem_cfg.h.xsl Normal file → Executable file
View File

@ -26,23 +26,22 @@
</xsl:template>
<xsl:template match="config-data/acrn-config">
<xsl:if test="./hv/FEATURES/IVSHMEM/IVSHMEM_ENABLED = 'y'">
<xsl:if test="count(//hv//IVSHMEM/IVSHMEM_REGION) > 0">
<!-- Included headers -->
<xsl:value-of select="acrn:include('ivshmem.h')" />
<xsl:value-of select="acrn:include('asm/pgtable.h')" />
<xsl:call-template name="ivshmem_shm_region_name" />
<xsl:call-template name="ivshmem_shm_mem" />
<xsl:apply-templates select="hv/FEATURES/IVSHMEM" />
<xsl:apply-templates select="hv//IVSHMEM" />
<xsl:call-template name="ivshmem_shm_region" />
</xsl:if>
</xsl:template>
<xsl:template name ="ivshmem_shm_region_name">
<xsl:for-each select="hv/FEATURES/IVSHMEM/IVSHMEM_REGION">
<xsl:if test="text()">
<xsl:value-of select="acrn:define(concat('IVSHMEM_SHM_REGION_', position() - 1), concat($quot, substring-before(text(), ','), $quot), '')" />
</xsl:if>
<xsl:for-each select="hv//IVSHMEM/IVSHMEM_REGION">
<xsl:variable name="region" select="@name" />
<xsl:value-of select="acrn:define(concat('IVSHMEM_SHM_REGION_', position() - 1), concat($quot, 'hv:/', $region, $quot), '')" />
</xsl:for-each>
<xsl:value-of select="$newline" />
</xsl:template>
@ -50,21 +49,22 @@
<xsl:template name ="ivshmem_shm_mem">
<xsl:value-of select="acrn:comment('The IVSHMEM_SHM_SIZE is the sum of all memory regions. The size range of each memory region is [2MB, 512MB] and is a power of 2.')" />
<xsl:value-of select="$newline" />
<xsl:variable name="memsize" select="sum(dyn:map(//IVSHMEM_REGION, 'acrn:parse-shmem-size(.)'))" />
<xsl:variable name="memsize" select="sum(//IVSHMEM_REGION/IVSHMEM_SIZE)" />
<xsl:value-of select="acrn:define('IVSHMEM_SHM_SIZE', concat('0x', acrn:convert-num-base(string($memsize), 10, 16), '00000UL'))" />
</xsl:template>
<xsl:template match="IVSHMEM">
<xsl:value-of select="acrn:define('IVSHMEM_DEV_NUM', sum(dyn:map(//IVSHMEM_REGION, 'acrn:count-shmem-dev-num(.)')), 'UL')" />
<xsl:variable name="dev" select="count(//hv//IVSHMEM/IVSHMEM_REGION/IVSHMEM_VMS/IVSHMEM_VM)" />
<xsl:value-of select="acrn:define('IVSHMEM_DEV_NUM', string($dev), 'UL')" />
</xsl:template>
<xsl:template name ="ivshmem_shm_region">
<xsl:value-of select="acrn:comment('All user defined memory regions')" />
<xsl:value-of select="$newline" />
<xsl:value-of select="acrn:define('IVSHMEM_SHM_REGIONS', '', ' \')" />
<xsl:for-each select="hv/FEATURES/IVSHMEM/IVSHMEM_REGION">
<xsl:for-each select="hv//IVSHMEM/IVSHMEM_REGION">
<xsl:if test="text()">
<xsl:variable name="memsize" select="acrn:parse-shmem-size(text())" />
<xsl:variable name="memsize" select="IVSHMEM_SIZE" />
<xsl:text>{ \</xsl:text>
<xsl:value-of select="$newline" />
<xsl:value-of select="acrn:initializer('name', concat('IVSHMEM_SHM_REGION_', position() - 1, ', \'), true())" />

View File

@ -304,17 +304,16 @@
</func:function>
<!-- End of C code templates-->
<!-- Scenario-specific functions-->
<func:function name="acrn:parse-shmem-size">
<func:function name="acrn:shmem-index">
<xsl:param name="v" />
<xsl:if test="$v and $v != 'n' and $v != 'y'">
<func:result select="acrn:string-to-num(substring-before(substring-after($v, ','), ','), 10)" />
</xsl:if>
</func:function>
<func:function name="acrn:count-shmem-dev-num">
<xsl:param name="v" />
<func:result select="string-length($v) - string-length(translate($v, ':', ''))" />
<xsl:variable name="idx">
<xsl:for-each select="//hv//IVSHMEM/IVSHMEM_REGION">
<xsl:if test="@name = $v">
<xsl:value-of select="position() - 1" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
<func:result select="$idx" />
</func:function>
<func:function name="acrn:pci-dev-num">
@ -323,8 +322,9 @@
<xsl:variable name="vmtype" select="./vm_type" />
<xsl:variable name="ivshmem">
<xsl:choose>
<xsl:when test="../hv/FEATURES/IVSHMEM/IVSHMEM_ENABLED = 'y'">
<xsl:value-of select="count(../hv/FEATURES/IVSHMEM/IVSHMEM_REGION[contains(substring-after(substring-after(text(), ','), ','), $vmid)])" />
<xsl:when test="count(//hv//IVSHMEM/IVSHMEM_REGION) > 0">
<xsl:variable name="vm_name" select="./name" />
<xsl:value-of select="count(//hv//IVSHMEM/IVSHMEM_REGION/IVSHMEM_VMS/IVSHMEM_VM/VM_NAME[text() = $vm_name])" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="0" />

View File

@ -141,29 +141,28 @@
<xsl:template name="ivshmem_shm_mem">
<xsl:variable name="vm_id" select="@id" />
<xsl:variable name="vm_name" select="name" />
<xsl:variable name="vm_type" select="vm_type" />
<xsl:for-each select="//hv/FEATURES/IVSHMEM/IVSHMEM_REGION/text()">
<xsl:if test="contains(substring-after(substring-after(current(), ','), ','), $vm_id)">
<xsl:variable name="dev_name" select="concat('IVSHMEM_', position() - 1)" />
<xsl:text>{</xsl:text>
<xsl:value-of select="$newline" />
<xsl:value-of select="acrn:initializer('emu_type', 'PCI_DEV_TYPE_HVEMUL', '')" />
<xsl:value-of select="acrn:initializer('vdev_ops', '&amp;vpci_ivshmem_ops', '')" />
<xsl:choose>
<xsl:when test="acrn:is-post-launched-vm($vm_type)">
<xsl:value-of select="acrn:initializer('vbdf.value', 'UNASSIGNED_VBDF', '')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="acrn:initializer('vbdf.bits', acrn:get-vbdf($vm_id, $dev_name), '')" />
<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:otherwise>
</xsl:choose>
<xsl:value-of select="acrn:initializer('shm_region_name', concat('IVSHMEM_SHM_REGION_', position() - 1), '')" />
<xsl:text>},</xsl:text>
<xsl:value-of select="$newline" />
</xsl:if>
<xsl:for-each select="//hv//IVSHMEM/IVSHMEM_REGION/IVSHMEM_VMS/IVSHMEM_VM[VM_NAME = $vm_name]">
<xsl:text>{</xsl:text>
<xsl:value-of select="$newline" />
<xsl:value-of select="acrn:initializer('emu_type', 'PCI_DEV_TYPE_HVEMUL', '')" />
<xsl:value-of select="acrn:initializer('vdev_ops', '&amp;vpci_ivshmem_ops', '')" />
<xsl:choose>
<xsl:when test="acrn:is-post-launched-vm($vm_type)">
<xsl:value-of select="acrn:initializer('vbdf.value', 'UNASSIGNED_VBDF', '')" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="dev_name" select="concat('IVSHMEM_', acrn:shmem-index(../../@name))" />
<xsl:value-of select="acrn:initializer('vbdf.bits', acrn:get-vbdf($vm_id, $dev_name), '')" />
<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:otherwise>
</xsl:choose>
<xsl:value-of select="acrn:initializer('shm_region_name', concat('IVSHMEM_SHM_REGION_', acrn:shmem-index(../../@name)), '')" />
<xsl:text>},</xsl:text>
<xsl:value-of select="$newline" />
</xsl:for-each>
</xsl:template>