config_tools: add ivshmem providers

A shared memory region can be provided either by the hypervisor or by the
device model. Before recent schema changes this is telled by the "hv:/" or
"dm:/" prefix.

This patch adds another node under an IVSHMEM region to represent the
provider, following the practice that information in the old-school
encodings is split and put as separate XML nodes.

Tracked-On: #6690
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Junjie Mao 2022-03-02 17:13:12 +08:00 committed by acrnsi-robot
parent 609e09cf37
commit f392164b40
10 changed files with 73 additions and 35 deletions

View File

@ -25,7 +25,9 @@
<L1D_VMENTRY_ENABLED>n</L1D_VMENTRY_ENABLED> <L1D_VMENTRY_ENABLED>n</L1D_VMENTRY_ENABLED>
<MCE_ON_PSC_DISABLED>n</MCE_ON_PSC_DISABLED> <MCE_ON_PSC_DISABLED>n</MCE_ON_PSC_DISABLED>
<IVSHMEM> <IVSHMEM>
<IVSHMEM_REGION name="shm_region_0"> <IVSHMEM_REGION>
<NAME>shm_region_0</NAME>
<PROVIDED_BY>Hypervisor</PROVIDED_BY>
<IVSHMEM_SIZE>2</IVSHMEM_SIZE> <IVSHMEM_SIZE>2</IVSHMEM_SIZE>
<IVSHMEM_VMS> <IVSHMEM_VMS>
<IVSHMEM_VM> <IVSHMEM_VM>

View File

@ -38,7 +38,9 @@
<L1D_VMENTRY_ENABLED>n</L1D_VMENTRY_ENABLED> <L1D_VMENTRY_ENABLED>n</L1D_VMENTRY_ENABLED>
<MCE_ON_PSC_DISABLED>n</MCE_ON_PSC_DISABLED> <MCE_ON_PSC_DISABLED>n</MCE_ON_PSC_DISABLED>
<IVSHMEM> <IVSHMEM>
<IVSHMEM_REGION name="shm_region_0"> <IVSHMEM_REGION>
<NAME>shm_region_0</NAME>
<PROVIDED_BY>Hypervisor</PROVIDED_BY>
<IVSHMEM_SIZE>2</IVSHMEM_SIZE> <IVSHMEM_SIZE>2</IVSHMEM_SIZE>
<IVSHMEM_VMS> <IVSHMEM_VMS>
<IVSHMEM_VM> <IVSHMEM_VM>

View File

@ -25,7 +25,9 @@
<L1D_VMENTRY_ENABLED>n</L1D_VMENTRY_ENABLED> <L1D_VMENTRY_ENABLED>n</L1D_VMENTRY_ENABLED>
<MCE_ON_PSC_DISABLED>n</MCE_ON_PSC_DISABLED> <MCE_ON_PSC_DISABLED>n</MCE_ON_PSC_DISABLED>
<IVSHMEM> <IVSHMEM>
<IVSHMEM_REGION name="shm_region_0"> <IVSHMEM_REGION>
<NAME>shm_region_0</NAME>
<PROVIDED_BY>Hypervisor</PROVIDED_BY>
<IVSHMEM_SIZE>2</IVSHMEM_SIZE> <IVSHMEM_SIZE>2</IVSHMEM_SIZE>
<IVSHMEM_VMS> <IVSHMEM_VMS>
<IVSHMEM_VM> <IVSHMEM_VM>

View File

@ -124,12 +124,14 @@ class VirtualUartConnections:
return [new_parent_node] return [new_parent_node]
class SharedMemoryRegions: class SharedMemoryRegions:
class SharedMemoryRegion(namedtuple("SharedMemoryRegion", ["name", "size", "shared_vms"])): class SharedMemoryRegion(namedtuple("SharedMemoryRegion", ["provided_by", "name", "size", "shared_vms"])):
# The BDF of IVSHMEM PCI functions starts from 00:08.0 # The BDF of IVSHMEM PCI functions starts from 00:08.0
next_dev = defaultdict(lambda: 8) next_dev = defaultdict(lambda: 8)
nr_regions = 0
@classmethod @classmethod
def from_hypervisor_encoding(cls, text, old_xml_etree): def from_encoding(cls, text, old_xml_etree):
provided_by = "Device Model" if text.startswith("dm:/") else "Hypervisor"
parts = [p.strip() for p in text[text.find("/") + 1 :].split(",")] parts = [p.strip() for p in text[text.find("/") + 1 :].split(",")]
name = parts[0] name = parts[0]
size = parts[1] size = parts[1]
@ -147,22 +149,27 @@ class SharedMemoryRegions:
cls.next_dev[vm_name] += 1 cls.next_dev[vm_name] += 1
shared_vms.append((vm_name, f"00:{dev:02x}.0")) shared_vms.append((vm_name, f"00:{dev:02x}.0"))
return cls(name, size, shared_vms) return cls(provided_by, name, size, shared_vms)
@classmethod @classmethod
def from_xml_node(cls, node): def from_xml_node(cls, node):
name = node.get("name") cls.nr_regions += 1
name = node.get("name") if "name" in node.keys() else \
node.find("NAME").text if node.find("NAME") is not None else \
f"shared_memory_region_{nr_regions}"
provided_by = node.find("PROVIDED_BY").text if node.find("PROVIDED_BY") is not None else "Hypervisor"
size = node.find("IVSHMEM_SIZE").text size = node.find("IVSHMEM_SIZE").text
shared_vms = [] shared_vms = []
for shared_vm_node in node.find("IVSHMEM_VMS"): for shared_vm_node in node.find("IVSHMEM_VMS"):
vm_name = shared_vm_node.find("VM_NAME").text vm_name = shared_vm_node.find("VM_NAME").text
vbdf = shared_vm_node.find("VBDF").text vbdf = shared_vm_node.find("VBDF").text
shared_vms.append((vm_name, vbdf)) shared_vms.append((vm_name, vbdf))
return cls(name, size, shared_vms) return cls(provided_by, name, size, shared_vms)
def format_xml_element(self): def format_xml_element(self):
node = etree.Element("IVSHMEM_REGION") node = etree.Element("IVSHMEM_REGION")
node.set("name", self.name) etree.SubElement(node, "NAME").text = self.name
etree.SubElement(node, "PROVIDED_BY").text = self.provided_by
etree.SubElement(node, "IVSHMEM_SIZE").text = self.size etree.SubElement(node, "IVSHMEM_SIZE").text = self.size
vms_node = etree.SubElement(node, "IVSHMEM_VMS") vms_node = etree.SubElement(node, "IVSHMEM_VMS")
@ -182,7 +189,7 @@ class SharedMemoryRegions:
if len(ivshmem_region_node) == 0: if len(ivshmem_region_node) == 0:
# ACRN v2.x format # ACRN v2.x format
region = self.SharedMemoryRegion.from_hypervisor_encoding(ivshmem_region_node.text, self.old_xml_etree) region = self.SharedMemoryRegion.from_encoding(ivshmem_region_node.text, self.old_xml_etree)
self.regions[region.name] = region self.regions[region.name] = region
else: else:
# ACRN v3.x format # ACRN v3.x format

View File

@ -1,5 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<xs:schema xml:id="root" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:schema xml:id="root"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:acrn="https://projectacrn.org">
<xs:simpleType name="Boolean"> <xs:simpleType name="Boolean">
<xs:annotation> <xs:annotation>
@ -152,7 +154,7 @@ Read more about the available scheduling options in :ref:`cpu_sharing`.</xs:docu
<xs:simpleType name="VMNameType"> <xs:simpleType name="VMNameType">
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:pattern value="([a-zA-Z0-9_\-]){1,15}" /> <xs:pattern value="([a-zA-Z0-9_\-]){1,15}" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
<xs:simpleType name="VBDFType"> <xs:simpleType name="VBDFType">
@ -161,10 +163,17 @@ Read more about the available scheduling options in :ref:`cpu_sharing`.</xs:docu
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
<xs:simpleType name="ProviderType">
<xs:restriction base="xs:string">
<xs:enumeration value="Hypervisor" />
<xs:enumeration value="Device Model" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="IVSHMEMVM"> <xs:complexType name="IVSHMEMVM">
<xs:sequence> <xs:sequence>
<xs:element name="VM_NAME" type="VMNameType"> <xs:element name="VM_NAME" type="VMNameType">
<xs:annotation> <xs:annotation>
<xs:documentation>Name of the VM which use this IVSHMEM.</xs:documentation> <xs:documentation>Name of the VM which use this IVSHMEM.</xs:documentation>
</xs:annotation> </xs:annotation>
</xs:element> </xs:element>
@ -202,21 +211,35 @@ device in VM . Set in hex.</xs:documentation>
</xs:simpleType> </xs:simpleType>
<xs:complexType name="IVSHMEMRegionType"> <xs:complexType name="IVSHMEMRegionType">
<xs:sequence> <xs:all>
<xs:element name="NAME">
<xs:annotation acrn:title="Name">
<xs:documentation>Name of the shared memory region.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="\w+" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="PROVIDED_BY" type="ProviderType" default="Hypervisor">
<xs:annotation acrn:title="Emulated by">
<xs:documentation>Whether the shared memory region is emulated by the hypervisor or device model.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="IVSHMEM_SIZE" type="IVSHMEMSize" default="2"> <xs:element name="IVSHMEM_SIZE" type="IVSHMEMSize" default="2">
<xs:annotation> <xs:annotation acrn:title="Size">
<xs:documentation>Memory size of inter-VM shared memory (IVSHMEM) <xs:documentation>Memory size of inter-VM shared memory (IVSHMEM)
in megabytes. The value should be a power of 2 in megabytes. The value should be a power of 2
and no more than 512.</xs:documentation> and no more than 512.</xs:documentation>
</xs:annotation> </xs:annotation>
</xs:element> </xs:element>
<xs:element name="IVSHMEM_VMS" type="IVSHMEMVMS"> <xs:element name="IVSHMEM_VMS" type="IVSHMEMVMS">
<xs:annotation> <xs:annotation acrn:title="Shared VMs">
<xs:documentation>Set all VMs which use this IVSHMEM.</xs:documentation> <xs:documentation>Set all VMs which use this IVSHMEM.</xs:documentation>
</xs:annotation> </xs:annotation>
</xs:element> </xs:element>
</xs:sequence> </xs:all>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType> </xs:complexType>
<xs:complexType name="IVSHMEMInfo"> <xs:complexType name="IVSHMEMInfo">

View File

@ -97,7 +97,10 @@ def get_ivshmem_regions_by_tree(etree):
ivshmem_regions = etree.xpath("//IVSHMEM_REGION") ivshmem_regions = etree.xpath("//IVSHMEM_REGION")
shmem_regions = {} shmem_regions = {}
for idx in range(len(ivshmem_regions)): for idx in range(len(ivshmem_regions)):
shm_name = ivshmem_regions[idx].get('name') provided_by = common.get_node("./PROVIDED_BY/text()", ivshmem_regions[idx])
if provided_by != "Hypervisor":
continue
shm_name = common.get_node("./NAME/text()", ivshmem_regions[idx])
if shm_name is None: if shm_name is None:
continue continue
shm_size = common.get_node("./IVSHMEM_SIZE/text()", ivshmem_regions[idx]) shm_size = common.get_node("./IVSHMEM_SIZE/text()", ivshmem_regions[idx])
@ -117,7 +120,7 @@ def get_ivshmem_enabled_by_tree(etree):
if len(ivshmem_vms) != 0: if len(ivshmem_vms) != 0:
shmem_enabled = 'y' shmem_enabled = 'y'
return shmem_enabled return shmem_enabled
def is_pre_launched_vm(vm_type): def is_pre_launched_vm(vm_type):
if vm_type == 'PRE_LAUNCHED_VM': if vm_type == 'PRE_LAUNCHED_VM':
return True return True

View File

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

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

@ -26,7 +26,7 @@
</xsl:template> </xsl:template>
<xsl:template match="config-data/acrn-config"> <xsl:template match="config-data/acrn-config">
<xsl:if test="count(//hv//IVSHMEM/IVSHMEM_REGION) > 0"> <xsl:if test="count(//hv//IVSHMEM/IVSHMEM_REGION[PROVIDED_BY = 'Hypervisor']) > 0">
<!-- Included headers --> <!-- Included headers -->
<xsl:value-of select="acrn:include('ivshmem.h')" /> <xsl:value-of select="acrn:include('ivshmem.h')" />
<xsl:value-of select="acrn:include('asm/pgtable.h')" /> <xsl:value-of select="acrn:include('asm/pgtable.h')" />
@ -39,9 +39,8 @@
</xsl:template> </xsl:template>
<xsl:template name ="ivshmem_shm_region_name"> <xsl:template name ="ivshmem_shm_region_name">
<xsl:for-each select="hv//IVSHMEM/IVSHMEM_REGION"> <xsl:for-each select="hv//IVSHMEM/IVSHMEM_REGION[PROVIDED_BY = 'Hypervisor']">
<xsl:variable name="region" select="@name" /> <xsl:value-of select="acrn:define(concat('IVSHMEM_SHM_REGION_', position() - 1), concat($quot, 'hv:/', NAME, $quot), '')" />
<xsl:value-of select="acrn:define(concat('IVSHMEM_SHM_REGION_', position() - 1), concat($quot, 'hv:/', $region, $quot), '')" />
</xsl:for-each> </xsl:for-each>
<xsl:value-of select="$newline" /> <xsl:value-of select="$newline" />
</xsl:template> </xsl:template>
@ -49,12 +48,12 @@
<xsl:template name ="ivshmem_shm_mem"> <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="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:value-of select="$newline" />
<xsl:variable name="memsize" select="sum(//IVSHMEM_REGION/IVSHMEM_SIZE)" /> <xsl:variable name="memsize" select="sum(//IVSHMEM_REGION[PROVIDED_BY = 'Hypervisor']/IVSHMEM_SIZE)" />
<xsl:value-of select="acrn:define('IVSHMEM_SHM_SIZE', concat('0x', acrn:convert-num-base(string($memsize), 10, 16), '00000UL'))" /> <xsl:value-of select="acrn:define('IVSHMEM_SHM_SIZE', concat('0x', acrn:convert-num-base(string($memsize), 10, 16), '00000UL'))" />
</xsl:template> </xsl:template>
<xsl:template match="IVSHMEM"> <xsl:template match="IVSHMEM">
<xsl:variable name="dev" select="count(//hv//IVSHMEM/IVSHMEM_REGION/IVSHMEM_VMS/IVSHMEM_VM)" /> <xsl:variable name="dev" select="count(//hv//IVSHMEM/IVSHMEM_REGION[PROVIDED_BY = 'Hypervisor']/IVSHMEM_VMS/IVSHMEM_VM)" />
<xsl:value-of select="acrn:define('IVSHMEM_DEV_NUM', string($dev), 'UL')" /> <xsl:value-of select="acrn:define('IVSHMEM_DEV_NUM', string($dev), 'UL')" />
</xsl:template> </xsl:template>
@ -62,7 +61,7 @@
<xsl:value-of select="acrn:comment('All user defined memory regions')" /> <xsl:value-of select="acrn:comment('All user defined memory regions')" />
<xsl:value-of select="$newline" /> <xsl:value-of select="$newline" />
<xsl:value-of select="acrn:define('IVSHMEM_SHM_REGIONS', '', ' \')" /> <xsl:value-of select="acrn:define('IVSHMEM_SHM_REGIONS', '', ' \')" />
<xsl:for-each select="hv//IVSHMEM/IVSHMEM_REGION"> <xsl:for-each select="hv//IVSHMEM/IVSHMEM_REGION[PROVIDED_BY = 'Hypervisor']">
<xsl:if test="text()"> <xsl:if test="text()">
<xsl:variable name="memsize" select="IVSHMEM_SIZE" /> <xsl:variable name="memsize" select="IVSHMEM_SIZE" />
<xsl:text>{ \</xsl:text> <xsl:text>{ \</xsl:text>

View File

@ -307,8 +307,8 @@
<func:function name="acrn:shmem-index"> <func:function name="acrn:shmem-index">
<xsl:param name="v" /> <xsl:param name="v" />
<xsl:variable name="idx"> <xsl:variable name="idx">
<xsl:for-each select="//hv//IVSHMEM/IVSHMEM_REGION"> <xsl:for-each select="//hv//IVSHMEM/IVSHMEM_REGION[PROVIDED_BY = 'Hypervisor']">
<xsl:if test="@name = $v"> <xsl:if test="NAME = $v">
<xsl:value-of select="position() - 1" /> <xsl:value-of select="position() - 1" />
</xsl:if> </xsl:if>
</xsl:for-each> </xsl:for-each>
@ -322,9 +322,9 @@
<xsl:variable name="vmtype" select="./load_order" /> <xsl:variable name="vmtype" select="./load_order" />
<xsl:variable name="ivshmem"> <xsl:variable name="ivshmem">
<xsl:choose> <xsl:choose>
<xsl:when test="count(//hv//IVSHMEM/IVSHMEM_REGION) > 0"> <xsl:when test="count(//hv//IVSHMEM/IVSHMEM_REGION[PROVIDED_BY = 'Hypervisor']) > 0">
<xsl:variable name="vm_name" select="./name" /> <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:value-of select="count(//hv//IVSHMEM/IVSHMEM_REGION[PROVIDED_BY = 'Hypervisor']/IVSHMEM_VMS/IVSHMEM_VM/VM_NAME[text() = $vm_name])" />
</xsl:when> </xsl:when>
<xsl:otherwise> <xsl:otherwise>
<xsl:value-of select="0" /> <xsl:value-of select="0" />

View File

@ -143,7 +143,7 @@
<xsl:variable name="vm_id" select="@id" /> <xsl:variable name="vm_id" select="@id" />
<xsl:variable name="vm_name" select="name" /> <xsl:variable name="vm_name" select="name" />
<xsl:variable name="load_order" select="load_order" /> <xsl:variable name="load_order" select="load_order" />
<xsl:for-each select="//hv//IVSHMEM/IVSHMEM_REGION/IVSHMEM_VMS/IVSHMEM_VM[VM_NAME = $vm_name]"> <xsl:for-each select="//hv//IVSHMEM/IVSHMEM_REGION[PROVIDED_BY = 'Hypervisor']/IVSHMEM_VMS/IVSHMEM_VM[VM_NAME = $vm_name]">
<xsl:text>{</xsl:text> <xsl:text>{</xsl:text>
<xsl:value-of select="$newline" /> <xsl:value-of select="$newline" />
<xsl:value-of select="acrn:initializer('emu_type', 'PCI_DEV_TYPE_HVEMUL', '')" /> <xsl:value-of select="acrn:initializer('emu_type', 'PCI_DEV_TYPE_HVEMUL', '')" />
@ -153,14 +153,14 @@
<xsl:value-of select="acrn:initializer('vbdf.value', 'UNASSIGNED_VBDF', '')" /> <xsl:value-of select="acrn:initializer('vbdf.value', 'UNASSIGNED_VBDF', '')" />
</xsl:when> </xsl:when>
<xsl:otherwise> <xsl:otherwise>
<xsl:variable name="dev_name" select="concat('IVSHMEM_', acrn:shmem-index(../../@name))" /> <xsl:variable name="dev_name" select="concat('IVSHMEM_', acrn:shmem-index(ancestor::IVSHMEM_REGION/NAME))" />
<xsl:value-of select="acrn:initializer('vbdf.bits', acrn:get-vbdf($vm_id, $dev_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: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:value-of select="acrn:initializer(concat('vbar_base[', @id,']'), concat(text(), 'UL'), '')" />
</xsl:for-each> </xsl:for-each>
</xsl:otherwise> </xsl:otherwise>
</xsl:choose> </xsl:choose>
<xsl:value-of select="acrn:initializer('shm_region_name', concat('IVSHMEM_SHM_REGION_', acrn:shmem-index(../../@name)), '')" /> <xsl:value-of select="acrn:initializer('shm_region_name', concat('IVSHMEM_SHM_REGION_', acrn:shmem-index(ancestor::IVSHMEM_REGION/NAME)), '')" />
<xsl:text>},</xsl:text> <xsl:text>},</xsl:text>
<xsl:value-of select="$newline" /> <xsl:value-of select="$newline" />
</xsl:for-each> </xsl:for-each>