mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-18 15:28:43 +00:00
board_inspector: collect inter-device dependency in board XMLs
AML allows devices defined in an ACPI namespace to have inter-dependency, i.e. a method defined in one device can refer to objects in other devices. While such inter-dependency is common in device manipulation methods, device identification and configuration methods, such as _CRS, may depend on other devices as well. An example we have already met is a PCS (Physical Coding Sublayer) which calculates resource descriptors by accessing the PCI configuration space of the accompanying Ethernet controller. Without the ACPI object describing the PCS, a driver of the Ethernet controller may refuse to initialize. This patch adds a preliminary dependency analyzer to detect such inter-device dependency. The analyzer walks through the reference chains of an object, identifying whether the referenced objects are operation fields of a device. Depending on the result of this analysis, the board XML is refined as follows. * When an object (probably a method) references such fields, the original object definition in host DSDT/SSDTs will be copied in the AML template so that they still work in VMs where the operation fields may be virtualized. Such objects will be referred to as "copied objects" hereinafter. * The objects that are **directly** referenced by a copied object is added in the AML template as well. Such objects still belong to devices where they are originally defined in the host ACPI namespace. Their definition, however, may be copied or replaced with constant values, depending on the dependency analysis on these objects. * Nodes with the "dependency" tag are added under "device" nodes in the board XML, allowing the configuration tools to follow the device dependency chain when generating vACPI tables. These nodes only represent direct dependencies; indirect dependencies can be inferred by following those direct ones. The current implementation does not allow objects being added to AML templates if they refer to any of the following. * Global objects, i.e. objects not belonging to any device. Such objects tend to encode system-wide information, such as the ACPI NVS (Non-Volatile Storage) or its fields. * Methods with parameters. Objects with such references are thus being hidden from guest software, just like how they are invisible in the current implementation. This patch is added in v2 of the series. v2 -> v3: * Also collect dependencies due to providing or consuming resources. * Refactor the dependency detection logic for clarity. Tracked-On: #6287 Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
@@ -30,6 +30,14 @@ class FieldDecl(NamedDecl):
|
||||
def dump(self):
|
||||
print(f"{self.name}: {self.__class__.__name__}, {self.length} bits")
|
||||
|
||||
class OperationRegionDecl(NamedDecl):
|
||||
@staticmethod
|
||||
def object_type():
|
||||
return 10
|
||||
|
||||
def __init__(self, name, tree):
|
||||
super().__init__(name, tree)
|
||||
|
||||
class OperationFieldDecl(NamedDecl):
|
||||
def __init__(self, name, length, tree):
|
||||
super().__init__(name, tree)
|
||||
@@ -37,6 +45,7 @@ class OperationFieldDecl(NamedDecl):
|
||||
self.offset = None
|
||||
self.length = length
|
||||
self.access_width = None
|
||||
self.parent_tree = None
|
||||
|
||||
def set_location(self, region, offset, access_width):
|
||||
self.region = region
|
||||
@@ -155,6 +164,13 @@ class Context:
|
||||
else:
|
||||
return parent
|
||||
|
||||
@staticmethod
|
||||
def normalize_namepath(namepath):
|
||||
path = namepath.lstrip("\\^")
|
||||
prefix = namepath[:(len(namepath) - len(path))]
|
||||
parts = '.'.join(map(lambda x: x[:4].ljust(4, '_'), path.split(".")))
|
||||
return prefix + parts
|
||||
|
||||
def __init__(self):
|
||||
self.streams = {}
|
||||
self.current_stream = None
|
||||
@@ -266,18 +282,25 @@ class Context:
|
||||
prefix_len -= 1
|
||||
raise KeyError(name)
|
||||
|
||||
def lookup_symbol(self, name):
|
||||
def lookup_symbol(self, name, scope=None):
|
||||
if scope:
|
||||
self.change_scope(scope)
|
||||
try:
|
||||
if name.startswith("\\"):
|
||||
return self.__symbol_table[name]
|
||||
ret = self.__symbol_table[name]
|
||||
elif name.startswith("^") or name.find(".") >= 0:
|
||||
realpath = self.realpath(self.__current_scope, name)
|
||||
return self.__symbol_table[realpath]
|
||||
ret = self.__symbol_table[realpath]
|
||||
else:
|
||||
return self.__lookup_symbol_in_parents(self.__symbol_table, name)
|
||||
ret = self.__lookup_symbol_in_parents(self.__symbol_table, name)
|
||||
except KeyError:
|
||||
logging.debug(f"Cannot find definition of {name}")
|
||||
raise UndefinedSymbol(name, self.get_scope())
|
||||
ret = None
|
||||
|
||||
if scope:
|
||||
self.pop_scope()
|
||||
if not ret:
|
||||
raise UndefinedSymbol(name, scope if scope else self.get_scope())
|
||||
return ret
|
||||
|
||||
def has_symbol(self, name):
|
||||
try:
|
||||
|
@@ -531,6 +531,7 @@ def DefField_hook_post(context, tree):
|
||||
sym = context.lookup_symbol(name)
|
||||
assert isinstance(sym, OperationFieldDecl)
|
||||
sym.set_location(region_name, bit_offset, access_width)
|
||||
sym.parent_tree = tree
|
||||
bit_offset += length
|
||||
elif field.label == "ReservedField":
|
||||
length = field.FieldLength.value
|
||||
@@ -580,7 +581,7 @@ def DefMethod_hook_post(context, tree):
|
||||
context.register_symbol(sym)
|
||||
|
||||
def DefOpRegion_hook_named(context, tree, name):
|
||||
sym = NamedDecl(name, tree)
|
||||
sym = OperationRegionDecl(name, tree)
|
||||
context.register_symbol(sym)
|
||||
|
||||
def DefPowerRes_hook_named(context, tree, name):
|
||||
|
Reference in New Issue
Block a user