mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-23 05:57:33 +00:00
config_tools: abstract BusDevFunc to the common library module
It is a common practice to parse PCI BDF in the static allocators. This patch moves the BusDevFunc class (which is a named tuple encoding a BDF) to lib.py and uses it for BDF parsing throughout the static allocators. Tracked-On: #6287 Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
parent
edfac3ce62
commit
692ab1d529
@ -8,57 +8,19 @@
|
|||||||
import sys, os, re
|
import sys, os, re
|
||||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library'))
|
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library'))
|
||||||
import common, lib.error, lib.lib
|
import common, lib.error, lib.lib
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
# Constants for device name prefix
|
# Constants for device name prefix
|
||||||
IVSHMEM = "IVSHMEM"
|
IVSHMEM = "IVSHMEM"
|
||||||
VUART = "VUART"
|
VUART = "VUART"
|
||||||
PTDEV = "PTDEV"
|
|
||||||
|
|
||||||
# Exception bdf list
|
# Exception bdf list
|
||||||
# Some hardware drivers' bdf is hardcoded, the bdf cannot be changed even it is passtrhough devices.
|
# Some hardware drivers' bdf is hardcoded, the bdf cannot be changed even it is passtrhough devices.
|
||||||
HARDCODED_BDF_LIST = ["00:0e.0"]
|
HARDCODED_BDF_LIST = ["00:0e.0"]
|
||||||
|
|
||||||
class BusDevFunc(namedtuple(
|
|
||||||
"BusDevFunc", [
|
|
||||||
"bus",
|
|
||||||
"dev",
|
|
||||||
"func"])):
|
|
||||||
|
|
||||||
PATTERN = re.compile(r"(?P<bus>[0-9a-f]{2}):(?P<dev>[0-9a-f]{2})\.(?P<func>[0-7]{1})")
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_str(cls, value):
|
|
||||||
if not(isinstance(value, str)):
|
|
||||||
raise ValueError("value must be a str: {}".format(type(value)))
|
|
||||||
|
|
||||||
match = cls.PATTERN.fullmatch(value)
|
|
||||||
if match:
|
|
||||||
return BusDevFunc(
|
|
||||||
bus=int(match.group("bus"), 16),
|
|
||||||
dev=int(match.group("dev"), 16),
|
|
||||||
func=int(match.group("func"), 16))
|
|
||||||
else:
|
|
||||||
raise ValueError("not a bdf: {!r}".format(value))
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
if not (0x00 <= self.bus <= 0xff):
|
|
||||||
raise ValueError(f"Invalid bus number (0x00 ~ 0xff): {self.bus:#04x}")
|
|
||||||
if not (0x00 <= self.dev <= 0x1f):
|
|
||||||
raise ValueError(f"Invalid device number (0x00 ~ 0x1f): {self.dev:#04x}")
|
|
||||||
if not (0x0 <= self.func <= 0x7):
|
|
||||||
raise ValueError(f"Invalid function number (0 ~ 7): {self.func:#x}")
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"{self.bus:02x}:{self.dev:02x}.{self.func:x}"
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "BusDevFunc.from_str({!r})".format(str(self))
|
|
||||||
|
|
||||||
def find_unused_bdf(used_bdf):
|
def find_unused_bdf(used_bdf):
|
||||||
# never assign 0:00.0 to any emulated devices, it's reserved for pci hostbridge
|
# never assign 0:00.0 to any emulated devices, it's reserved for pci hostbridge
|
||||||
for dev in range(0x1, 0x20):
|
for dev in range(0x1, 0x20):
|
||||||
bdf = BusDevFunc(bus=0x00, dev=dev, func=0x0)
|
bdf = lib.lib.BusDevFunc(bus=0x00, dev=dev, func=0x0)
|
||||||
if all((bdf.dev != in_use_bdf.dev for in_use_bdf in used_bdf)):
|
if all((bdf.dev != in_use_bdf.dev for in_use_bdf in used_bdf)):
|
||||||
return bdf
|
return bdf
|
||||||
raise lib.error.ResourceError(f"Cannot find free bdf, used bdf: {sorted(used_bdf)}")
|
raise lib.error.ResourceError(f"Cannot find free bdf, used bdf: {sorted(used_bdf)}")
|
||||||
@ -96,19 +58,19 @@ def insert_pt_devs_to_dev_dict(vm_node_etree, devdict, used):
|
|||||||
for pt_dev in pt_devs:
|
for pt_dev in pt_devs:
|
||||||
bdf_string = pt_dev.split()[0]
|
bdf_string = pt_dev.split()[0]
|
||||||
if bdf_string in HARDCODED_BDF_LIST:
|
if bdf_string in HARDCODED_BDF_LIST:
|
||||||
bdf = BusDevFunc.from_str(bdf_string)
|
bdf = lib.lib.BusDevFunc.from_str(bdf_string)
|
||||||
dev_name = f"{PTDEV}_{bdf.bus:#04x}_{((bdf.dev << 16) | bdf.func):#08x}".upper()
|
dev_name = str(bdf)
|
||||||
devdict[dev_name] = bdf
|
devdict[dev_name] = bdf
|
||||||
used.append(bdf)
|
used.append(bdf)
|
||||||
|
|
||||||
# remove the pt_dev nodes which are in HARDCODED_BDF_LIST
|
# remove the pt_dev nodes which are in HARDCODED_BDF_LIST
|
||||||
pt_devs = [pt_dev for pt_dev in pt_devs if BusDevFunc.from_str(bdf_string) not in used]
|
pt_devs = [pt_dev for pt_dev in pt_devs if lib.lib.BusDevFunc.from_str(bdf_string) not in used]
|
||||||
|
|
||||||
# call find_unused_bdf to assign an unused bdf for other passthrough devices except the ones in HARDCODED_BDF_LIST
|
# call find_unused_bdf to assign an unused bdf for other passthrough devices except the ones in HARDCODED_BDF_LIST
|
||||||
for pt_dev in pt_devs:
|
for pt_dev in pt_devs:
|
||||||
bdf = BusDevFunc.from_str(pt_dev.split()[0])
|
bdf = lib.lib.BusDevFunc.from_str(pt_dev.split()[0])
|
||||||
free_bdf = find_unused_bdf(used)
|
free_bdf = find_unused_bdf(used)
|
||||||
dev_name = f"{PTDEV}_{bdf.bus:#04x}_{((bdf.dev << 16) | bdf.func):#08x}".upper()
|
dev_name = str(bdf)
|
||||||
devdict[dev_name] = free_bdf
|
devdict[dev_name] = free_bdf
|
||||||
used.append(free_bdf)
|
used.append(free_bdf)
|
||||||
|
|
||||||
@ -124,7 +86,7 @@ def get_devs_bdf_native(board_etree):
|
|||||||
bus = int(common.get_node("../@address", node), 16)
|
bus = int(common.get_node("../@address", node), 16)
|
||||||
dev = int(address, 16) >> 16
|
dev = int(address, 16) >> 16
|
||||||
func = int(address, 16) & 0xffff
|
func = int(address, 16) & 0xffff
|
||||||
dev_list.append(BusDevFunc(bus = bus, dev = dev, func = func))
|
dev_list.append(lib.lib.BusDevFunc(bus = bus, dev = dev, func = func))
|
||||||
return dev_list
|
return dev_list
|
||||||
|
|
||||||
def get_devs_bdf_passthrough(scenario_etree):
|
def get_devs_bdf_passthrough(scenario_etree):
|
||||||
@ -136,7 +98,7 @@ def get_devs_bdf_passthrough(scenario_etree):
|
|||||||
for vm_type in lib.lib.PRE_LAUNCHED_VMS_TYPE:
|
for vm_type in lib.lib.PRE_LAUNCHED_VMS_TYPE:
|
||||||
pt_devs = scenario_etree.xpath(f"//vm[vm_type = '{vm_type}']/pci_devs/pci_dev/text()")
|
pt_devs = scenario_etree.xpath(f"//vm[vm_type = '{vm_type}']/pci_devs/pci_dev/text()")
|
||||||
for pt_dev in pt_devs:
|
for pt_dev in pt_devs:
|
||||||
bdf = BusDevFunc.from_str(pt_dev.split()[0])
|
bdf = lib.lib.BusDevFunc.from_str(pt_dev.split()[0])
|
||||||
dev_list.append(bdf)
|
dev_list.append(bdf)
|
||||||
return dev_list
|
return dev_list
|
||||||
|
|
||||||
@ -151,11 +113,11 @@ def create_device_node(allocation_etree, vm_id, devdict):
|
|||||||
if dev_node is None:
|
if dev_node is None:
|
||||||
dev_node = common.append_node("./device", None, vm_node, name = dev_name)
|
dev_node = common.append_node("./device", None, vm_node, name = dev_name)
|
||||||
if common.get_node(f"./bus", dev_node) is None:
|
if common.get_node(f"./bus", dev_node) is None:
|
||||||
common.append_node(f"./bus", f"{bdf.bus:#04x}".upper(), dev_node)
|
common.append_node(f"./bus", f"{bdf.bus:#04x}", dev_node)
|
||||||
if common.get_node(f"./dev", dev_node) is None:
|
if common.get_node(f"./dev", dev_node) is None:
|
||||||
common.append_node(f"./dev", f"{bdf.dev:#04x}".upper(), dev_node)
|
common.append_node(f"./dev", f"{bdf.dev:#04x}", dev_node)
|
||||||
if common.get_node(f"./func", dev_node) is None:
|
if common.get_node(f"./func", dev_node) is None:
|
||||||
common.append_node(f"./func", f"{bdf.func:#04x}".upper(), dev_node)
|
common.append_node(f"./func", f"{bdf.func:#04x}", dev_node)
|
||||||
|
|
||||||
def fn(board_etree, scenario_etree, allocation_etree):
|
def fn(board_etree, scenario_etree, allocation_etree):
|
||||||
vm_nodes = scenario_etree.xpath("//vm")
|
vm_nodes = scenario_etree.xpath("//vm")
|
||||||
@ -172,7 +134,7 @@ def fn(board_etree, scenario_etree, allocation_etree):
|
|||||||
passthrough_used = get_devs_bdf_passthrough(scenario_etree)
|
passthrough_used = get_devs_bdf_passthrough(scenario_etree)
|
||||||
used = [bdf for bdf in native_used if bdf not in passthrough_used]
|
used = [bdf for bdf in native_used if bdf not in passthrough_used]
|
||||||
if common.get_node("//@board", scenario_etree) == "tgl-rvp":
|
if common.get_node("//@board", scenario_etree) == "tgl-rvp":
|
||||||
used.append(BusDevFunc(bus = 0, dev = 1, func = 0))
|
used.append(lib.lib.BusDevFunc(bus = 0, dev = 1, func = 0))
|
||||||
|
|
||||||
insert_vuart_to_dev_dict(vm_node, devdict, used)
|
insert_vuart_to_dev_dict(vm_node, devdict, used)
|
||||||
insert_ivsheme_to_dev_dict(scenario_etree, devdict, vm_id, used)
|
insert_ivsheme_to_dev_dict(scenario_etree, devdict, vm_id, used)
|
||||||
|
@ -120,6 +120,7 @@ def insert_pt_devs_to_dev_dict(board_etree, vm_node_etree, devdict_32bits, devdi
|
|||||||
bus = int(bdf.split(':')[0], 16)
|
bus = int(bdf.split(':')[0], 16)
|
||||||
dev = int(bdf.split(":")[1].split('.')[0], 16)
|
dev = int(bdf.split(":")[1].split('.')[0], 16)
|
||||||
func = int(bdf.split(":")[1].split('.')[1], 16)
|
func = int(bdf.split(":")[1].split('.')[1], 16)
|
||||||
|
bdf = lib.lib.BusDevFunc(bus=bus, dev=dev, func=func)
|
||||||
pt_dev_node = common.get_node(f"//bus[@type = 'pci' and @address = '{hex(bus)}']/device[@address = '{hex((dev << 16) | func)}']", board_etree)
|
pt_dev_node = common.get_node(f"//bus[@type = 'pci' and @address = '{hex(bus)}']/device[@address = '{hex((dev << 16) | func)}']", board_etree)
|
||||||
if pt_dev_node is not None:
|
if pt_dev_node is not None:
|
||||||
insert_vmsix_to_dev_dict(pt_dev_node, devdict_32bits)
|
insert_vmsix_to_dev_dict(pt_dev_node, devdict_32bits)
|
||||||
@ -127,7 +128,7 @@ def insert_pt_devs_to_dev_dict(board_etree, vm_node_etree, devdict_32bits, devdi
|
|||||||
for pt_dev_resource in pt_dev_resources:
|
for pt_dev_resource in pt_dev_resources:
|
||||||
if int(pt_dev_resource.get('min'), 16) < PCI_HOLE_THRESHOLD:
|
if int(pt_dev_resource.get('min'), 16) < PCI_HOLE_THRESHOLD:
|
||||||
continue
|
continue
|
||||||
dev_name = f"{PTDEV}_{bus:#04x}_{((dev << 16) | func):#08x}".upper()
|
dev_name = str(bdf)
|
||||||
bar_len = pt_dev_resource.get('len')
|
bar_len = pt_dev_resource.get('len')
|
||||||
bar_region = pt_dev_resource.get('id')
|
bar_region = pt_dev_resource.get('id')
|
||||||
bar_width = pt_dev_resource.get('width')
|
bar_width = pt_dev_resource.get('width')
|
||||||
@ -164,7 +165,8 @@ def insert_vmsix_to_dev_dict(pt_dev_node, devdict):
|
|||||||
address = common.get_node("./@address", pt_dev_node)
|
address = common.get_node("./@address", pt_dev_node)
|
||||||
bus = common.get_node(f"../@address", pt_dev_node)
|
bus = common.get_node(f"../@address", pt_dev_node)
|
||||||
if bus is not None and address is not None:
|
if bus is not None and address is not None:
|
||||||
dev_name = f"{PTDEV}_{int(bus, 16):#04x}_{int(address, 16):#08x}".upper()
|
bdf = lib.lib.BusDevFunc(bus=int(bus, 16), dev=int(address, 16) >> 16, func=int(address, 16) & 0xffff)
|
||||||
|
dev_name = str(bdf)
|
||||||
devdict[(f"{dev_name}", f"bar{next_bar_region}")] = VMSIX_VBAR_SIZE
|
devdict[(f"{dev_name}", f"bar{next_bar_region}")] = VMSIX_VBAR_SIZE
|
||||||
|
|
||||||
def get_devs_mem_native(board_etree, mems):
|
def get_devs_mem_native(board_etree, mems):
|
||||||
|
@ -6,14 +6,51 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
import sys, os
|
import sys, os, re
|
||||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library'))
|
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library'))
|
||||||
import common, board_cfg_lib
|
import common, board_cfg_lib
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
PRE_LAUNCHED_VMS_TYPE = ["SAFETY_VM", "PRE_RT_VM", "PRE_STD_VM"]
|
PRE_LAUNCHED_VMS_TYPE = ["SAFETY_VM", "PRE_RT_VM", "PRE_STD_VM"]
|
||||||
POST_LAUNCHED_VMS_TYPE = ["POST_STD_VM", "POST_RT_VM", "KATA_VM"]
|
POST_LAUNCHED_VMS_TYPE = ["POST_STD_VM", "POST_RT_VM", "KATA_VM"]
|
||||||
SOS_VM_TYPE = ["SOS_VM"]
|
SOS_VM_TYPE = ["SOS_VM"]
|
||||||
|
|
||||||
|
class BusDevFunc(namedtuple(
|
||||||
|
"BusDevFunc", [
|
||||||
|
"bus",
|
||||||
|
"dev",
|
||||||
|
"func"])):
|
||||||
|
|
||||||
|
PATTERN = re.compile(r"(?P<bus>[0-9a-f]{2}):(?P<dev>[0-9a-f]{2})\.(?P<func>[0-7]{1})")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_str(cls, value):
|
||||||
|
if not(isinstance(value, str)):
|
||||||
|
raise ValueError("value must be a str: {}".format(type(value)))
|
||||||
|
|
||||||
|
match = cls.PATTERN.fullmatch(value)
|
||||||
|
if match:
|
||||||
|
return BusDevFunc(
|
||||||
|
bus=int(match.group("bus"), 16),
|
||||||
|
dev=int(match.group("dev"), 16),
|
||||||
|
func=int(match.group("func"), 16))
|
||||||
|
else:
|
||||||
|
raise ValueError("not a bdf: {!r}".format(value))
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
if not (0x00 <= self.bus <= 0xff):
|
||||||
|
raise ValueError(f"Invalid bus number (0x00 ~ 0xff): {self.bus:#04x}")
|
||||||
|
if not (0x00 <= self.dev <= 0x1f):
|
||||||
|
raise ValueError(f"Invalid device number (0x00 ~ 0x1f): {self.dev:#04x}")
|
||||||
|
if not (0x0 <= self.func <= 0x7):
|
||||||
|
raise ValueError(f"Invalid function number (0 ~ 7): {self.func:#x}")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"PTDEV_{self.bus:02x}:{self.dev:02x}.{self.func:x}"
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "BusDevFunc.from_str({!r})".format(str(self))
|
||||||
|
|
||||||
def parse_hv_console(scenario_etree):
|
def parse_hv_console(scenario_etree):
|
||||||
"""
|
"""
|
||||||
There may be 3 types in the console item
|
There may be 3 types in the console item
|
||||||
|
@ -605,10 +605,10 @@
|
|||||||
|
|
||||||
<func:function name="acrn:ptdev-name-suffix">
|
<func:function name="acrn:ptdev-name-suffix">
|
||||||
<xsl:param name="pci_dev" />
|
<xsl:param name="pci_dev" />
|
||||||
<xsl:variable name="bus" select="translate(substring-before($pci_dev, ':'), $lowercase, $uppercase)" />
|
<xsl:variable name="bus" select="translate(substring-before($pci_dev, ':'), $uppercase, $lowercase)" />
|
||||||
<xsl:variable name="dev" select="translate(substring-before(substring-after($pci_dev, ':'), '.'), $lowercase, $uppercase)" />
|
<xsl:variable name="dev" select="translate(substring-before(substring-after($pci_dev, ':'), '.'), $uppercase, $lowercase)" />
|
||||||
<xsl:variable name="func" select="translate(substring-after(substring-before($pci_dev, ' '), '.'), $lowercase, $uppercase)" />
|
<xsl:variable name="func" select="translate(substring-after(substring-before($pci_dev, ' '), '.'), $uppercase, $lowercase)" />
|
||||||
<func:result select="concat('0X', $bus, '_0X', $dev, '000', $func)" />
|
<func:result select="concat($bus, ':', $dev, '.', $func)" />
|
||||||
</func:function>
|
</func:function>
|
||||||
<!-- End of scenario-specific functions-->
|
<!-- End of scenario-specific functions-->
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user