config_tools: add default values to vBDF of vUART and IVSHMEM

Different from other nodes which have static default values, the virtual
BDF nodes of virtual UART endpoints or IVSHMEM interfaces have a set of
default values and should be used with uniqueness guaranteed. The existing
default value mechanism in XSD does not include support for this.

This patch adds two more ACRN-specific annotations, namely `acrn:defaults`
and `acrn:unique-among`, that have the following semantics.

  - `acrn:defaults` is a Python expression that evaluates to an iterable.

  - `acrn:unique-among` is an xpath that specifies the nodes. Each node
    within the select ones shall have a value unique among them. The xpath
    is evaluated with the variable `parent` defined as the parent node
    under which the vBDF node is to be appended.

Tracked-On: #7330
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Junjie Mao 2022-04-19 09:20:47 +08:00 committed by acrnsi-robot
parent e246ada6b0
commit 5bd3e96426
5 changed files with 50 additions and 4 deletions

View File

@ -7,6 +7,7 @@
import os
import argparse
import elementpath
from scenario_transformer import ScenarioTransformer
@ -14,9 +15,32 @@ from pipeline import PipelineObject, PipelineStage, PipelineEngine
from schema_slicer import SlicingSchemaByVMTypeStage
class DefaultValuePopulator(ScenarioTransformer):
def get_default_value(self, xsd_element_node, xml_parent_node):
# The attribute @default of the xsd:element node
v = xsd_element_node.get("default")
if v is not None:
return v
# The acrn:defaults and acrn:unique-among annotations which define a set of default values that shall be unique
# among a collection of nodes
annot_node = self.get_node(xsd_element_node, "xs:annotation")
if annot_node is not None:
defaults = annot_node.get("{https://projectacrn.org}defaults")
unique_among = annot_node.get("{https://projectacrn.org}unique-among")
if defaults is not None and unique_among is not None:
try:
default_values = set(eval(defaults))
existing_values = set(elementpath.select(self.xml_etree, unique_among, variables={"parent": xml_parent_node}))
available_defaults = default_values - existing_values
return sorted(list(available_defaults))[0]
except:
pass
return None
def add_missing_nodes(self, xsd_element_node, xml_parent_node, new_node_index):
element_name = xsd_element_node.get("name")
default_value = xsd_element_node.get("default")
default_value = self.get_default_value(xsd_element_node, xml_parent_node)
# If the node is neither of a complex type (i.e. it does not have an child node) nor has a default value, do not
# create the node at all. Users are required to fill in proper values in such nodes, and missing any of them

View File

@ -18,6 +18,7 @@ class ScenarioTransformer:
def __init__(self, xsd_etree, visit_optional_node=False):
self.xsd_etree = xsd_etree
self.xml_etree = None
self._visit_optional_node = visit_optional_node
@ -92,7 +93,11 @@ class ScenarioTransformer:
return []
def transform(self, xml_etree):
self.xml_etree = xml_etree
xml_root_node = xml_etree.getroot()
xsd_root_node = self.get_node(self.xsd_etree, f".//xs:element[@name='{xml_root_node.tag}']")
if xsd_root_node is not None:
self.transform_node(xsd_root_node, xml_root_node)
self.xml_etree = None

View File

@ -203,8 +203,8 @@ CLOSID 0 and the second is mapped to virtual CLOSID 1, etc.</xs:documentation>
<xs:documentation>Specify the COM base for each legacy virtual UART.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="vbdf" type="VBDFType" minOccurs="0" maxOccurs="1">
<xs:annotation acrn:title="Virtual BDF">
<xs:element name="vbdf" type="VBDFType">
<xs:annotation acrn:title="Virtual BDF" acrn:defaults="[f'00:{i:02x}.0' for i in range(16, 24)]" acrn:unique-among="//vuart_connection/endpoint[vm_name=$parent/vm_name]/vbdf/text()">
<xs:documentation>Specify the virtual Bus:Device.Function (BDF) for each PCI virtual UART. Virtual BDF is automatically assigned when the configuration is saved and can be changed if needed.</xs:documentation>
</xs:annotation>
</xs:element>

View File

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2022 Intel Corporation. -->
<!-- SPDX-License-Identifier: BSD-3-Clause -->
<xs:schema xml:id="root"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:acrn="https://projectacrn.org">
<xs:assert test="every $root in /acrn-config satisfies
every $vm in $root/vm satisfies
every $vbdf in distinct-values($root/hv//vuart_connection[type='pci']/endpoint[vm_name=$vm/name]/vbdf/text() | $root/hv//IVSHMEM_VM[VM_NAME=$vm/name]/VBDF/text()) satisfies
count($root/hv//vuart_connection[type='pci']/endpoint[vm_name=$vm/name and vbdf=$vbdf] | $root/hv//IVSHMEM_VM[VM_NAME=$vm/name and VBDF=$vbdf]) = 1">
<xs:annotation acrn:severity="error" acrn:report-on="$root/hv//vuart_connection[type='pci']/endpoint[vm_name=$vm/name and vbdf=$vbdf] | $root/hv//IVSHMEM_VM[VM_NAME=$vm/name and VBDF=$vbdf]">
<xs:documentation>VM "{$vm/name}" contains multiple virtual UART controllers and/or IVSHMEM interfaces using BDF {$vbdf}. Adjust the BDF of those devices.</xs:documentation>
</xs:annotation>
</xs:assert>
</xs:schema>

View File

@ -219,7 +219,7 @@ Read more about the available scheduling options in :ref:`cpu_sharing`.</xs:docu
</xs:annotation>
</xs:element>
<xs:element name="VBDF" type = "VBDFType">
<xs:annotation acrn:title="Virtual BDF">
<xs:annotation acrn:title="Virtual BDF" acrn:defaults="[f'00:{i:02x}.0' for i in range(8, 16)]" acrn:unique-among="//IVSHMEM_VM[VM_NAME=$parent/VM_NAME]/VBDF/text()">
<xs:documentation>Virtual BDF (Bus Device Function) is automatically assigned and can be changed if needed. Set in Hex.</xs:documentation>
</xs:annotation>
</xs:element>