config_tools: board_inspector: record all details from RTCT in board XML
Today users still need to manually copy the RTCT binary file when they want to passthrough software SRAM to a pre-launched RTVM, which is far from being user friendly. To get rid of that step, this patch extracts all information from the RTCT table and format them in the board XML which is the only file users need to copy from their target platform to build the hypervisor. The patch that immediately follows will then use such information to generate vRTCT for the pre-launched VM. A side effect of this change is that more ranges, which represents those reported by RTCT such as the CRL binary or the error log area, will be added to the `memory` section of the board XML. The `id` attributes of those range will be used to identify what that range is for. As a result, getting RAM of the physical platform from the board XML requires additional conditions on the `id` attributes to avoid counting non-RAM regions unintendedly. Tracked-On: #7947 Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
parent
d7bac88e5e
commit
89d54aa5d1
|
@ -67,39 +67,10 @@ def extract_topology(root_node, caches_node):
|
|||
return (level, id, type)
|
||||
caches_node[:] = sorted(caches_node, key=getkey)
|
||||
|
||||
def extract_tcc_capabilities(caches_node):
|
||||
try:
|
||||
rtct = parse_rtct()
|
||||
if rtct.version == 1:
|
||||
for entry in rtct.entries:
|
||||
if entry.type == acpiparser.rtct.ACPI_RTCT_V1_TYPE_SoftwareSRAM:
|
||||
cache_node = get_node(caches_node, f"cache[@level='{entry.cache_level}' and processors/processor='{hex(entry.apic_id_tbl[0])}']")
|
||||
if cache_node is None:
|
||||
logging.debug(f"Cannot find the level {entry.cache_level} cache of physical processor with apic ID {entry.apic_id_tbl[0]}")
|
||||
continue
|
||||
cap = add_child(cache_node, "capability", None, id="Software SRAM")
|
||||
add_child(cap, "start", "0x{:08x}".format(entry.base))
|
||||
add_child(cap, "end", "0x{:08x}".format(entry.base + entry.size - 1))
|
||||
add_child(cap, "size", str(entry.size))
|
||||
elif rtct.version == 2:
|
||||
for entry in rtct.entries:
|
||||
if entry.type == acpiparser.rtct.ACPI_RTCT_V2_TYPE_SoftwareSRAM:
|
||||
cache_node = get_node(caches_node, f"cache[@level='{entry.level}' and @id='{hex(entry.cache_id)}']")
|
||||
if cache_node is None:
|
||||
logging.debug(f"Cannot find the level {entry.level} cache with cache ID {entry.cache_id}")
|
||||
continue
|
||||
cap = add_child(cache_node, "capability", None, id="Software SRAM")
|
||||
add_child(cap, "start", "0x{:08x}".format(entry.base))
|
||||
add_child(cap, "end", "0x{:08x}".format(entry.base + entry.size - 1))
|
||||
add_child(cap, "size", str(entry.size))
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
def extract(args, board_etree):
|
||||
root_node = board_etree.getroot()
|
||||
caches_node = get_node(board_etree, "//caches")
|
||||
extract_topology(root_node, caches_node)
|
||||
extract_tcc_capabilities(caches_node)
|
||||
|
||||
# Inject the explicitly specified CAT capability if exists
|
||||
if args.add_llc_cat:
|
||||
|
|
|
@ -9,7 +9,7 @@ import re, os, fcntl, errno
|
|||
import lxml.etree
|
||||
from extractors.helpers import add_child, get_node
|
||||
|
||||
from acpiparser import parse_apic, apic
|
||||
import acpiparser
|
||||
|
||||
DEFAULT_MAX_IOAPIC_LINES = 240
|
||||
|
||||
|
@ -40,16 +40,113 @@ def extract_gsi_number(ioapic_node, apic_id):
|
|||
|
||||
def extract_topology(ioapics_node, tables):
|
||||
for subtable in tables.interrupt_controller_structures:
|
||||
if subtable.subtype == apic.MADT_TYPE_IO_APIC:
|
||||
if subtable.subtype == acpiparser.apic.MADT_TYPE_IO_APIC:
|
||||
apic_id = subtable.io_apic_id
|
||||
ioapic_node = add_child(ioapics_node, "ioapic", None, id=hex(apic_id))
|
||||
add_child(ioapic_node, "address", hex(subtable.io_apic_addr))
|
||||
add_child(ioapic_node, "gsi_base", hex(subtable.global_sys_int_base))
|
||||
extract_gsi_number(ioapic_node, apic_id)
|
||||
|
||||
def extract_tcc_capabilities_from_rtct_v1(board_etree, rtct):
|
||||
caches_node = get_node(board_etree, "//caches")
|
||||
|
||||
for entry in rtct.entries:
|
||||
if entry.type == acpiparser.rtct.ACPI_RTCT_V1_TYPE_SoftwareSRAM:
|
||||
cache_node = get_node(caches_node, f"cache[@level='{entry.cache_level}' and processors/processor='{hex(entry.apic_id_tbl[0])}']")
|
||||
if cache_node is None:
|
||||
logging.debug(f"Cannot find the level {entry.cache_level} cache of physical processor with apic ID {entry.apic_id_tbl[0]}")
|
||||
continue
|
||||
cap = add_child(cache_node, "capability", None, id="Software SRAM")
|
||||
add_child(cap, "start", "0x{:08x}".format(entry.base))
|
||||
add_child(cap, "end", "0x{:08x}".format(entry.base + entry.size - 1))
|
||||
add_child(cap, "size", str(entry.size))
|
||||
|
||||
def extract_tcc_capabilities_from_rtct_v2(board_etree, rtct):
|
||||
def get_or_create_ssram_node(cache_node):
|
||||
ssram_node = get_node(cache_node, "capability[@id = 'Software SRAM']")
|
||||
if ssram_node is None:
|
||||
ssram_node = add_child(cache_node, "capability", None, id="Software SRAM")
|
||||
return ssram_node
|
||||
|
||||
caches_node = get_node(board_etree, "//caches")
|
||||
memory_node = get_node(board_etree, "//memory")
|
||||
devices_node = get_node(board_etree, "//devices")
|
||||
|
||||
for entry in rtct.entries:
|
||||
cache_node = None
|
||||
if hasattr(entry, "level") and hasattr(entry, "cache_id"):
|
||||
cache_node = get_node(caches_node, f"cache[@level='{entry.level}' and @id='{hex(entry.cache_id)}']")
|
||||
if cache_node is None:
|
||||
logging.debug(f"Cannot find the level {entry.level} cache with cache ID {entry.cache_id}")
|
||||
continue
|
||||
|
||||
if entry.type == acpiparser.rtct.ACPI_RTCT_TYPE_COMPATIBILITY:
|
||||
rtct_version_node = add_child(caches_node, "parameter", None, id="RTCT Version")
|
||||
add_child(rtct_version_node, "major", str(entry.rtct_version_major))
|
||||
add_child(rtct_version_node, "minor", str(entry.rtct_version_minor))
|
||||
rtcd_version_node = add_child(caches_node, "parameter", None, id="RTCD Version")
|
||||
add_child(rtcd_version_node, "major", str(entry.rtcd_version_major))
|
||||
add_child(rtcd_version_node, "minor", str(entry.rtcd_version_minor))
|
||||
elif entry.type == acpiparser.rtct.ACPI_RTCT_V2_TYPE_RTCD_Limits:
|
||||
add_child(caches_node, "parameter", str(entry.total_ia_l2_clos), id="Total IA L2 CLOS")
|
||||
add_child(caches_node, "parameter", str(entry.total_ia_l3_clos), id="Total IA L3 CLOS")
|
||||
add_child(caches_node, "parameter", str(entry.total_l2_instances), id="Total IA L2 Instances")
|
||||
add_child(caches_node, "parameter", str(entry.total_l3_instances), id="Total IA L2 Instances")
|
||||
add_child(caches_node, "parameter", str(entry.total_gt_clos), id="Total GT CLOS")
|
||||
add_child(caches_node, "parameter", str(entry.total_wrc_clos), id="Total WRC CLOS")
|
||||
add_child(devices_node, "parameter", str(entry.max_tcc_streams), id="Maximum TCC Streams")
|
||||
add_child(devices_node, "parameter", str(entry.max_tcc_registers), id="Maximum TCC Registers")
|
||||
elif entry.type == acpiparser.rtct.ACPI_RTCT_V2_TYPE_CRL_Binary:
|
||||
start = "0x{:016x}".format(entry.address)
|
||||
end = "0x{:016x}".format(entry.address + entry.size - 1)
|
||||
size = str(entry.size)
|
||||
region = add_child(memory_node, "range", None, id="CRL Binary", start=start, end=end, size=size)
|
||||
elif entry.type == acpiparser.rtct.ACPI_RTCT_V2_TYPE_IA_WayMasks:
|
||||
cap = add_child(cache_node, "parameter", None, id="IA Waymask")
|
||||
for waymask in entry.waymask:
|
||||
add_child(cap, "waymask", hex(waymask))
|
||||
elif entry.type == acpiparser.rtct.ACPI_RTCT_V2_TYPE_WRC_WayMasks:
|
||||
cap = add_child(cache_node, "parameter", None, id="WRC Waymask")
|
||||
add_child(cap, "waymask", hex(entry.waymask))
|
||||
elif entry.type == acpiparser.rtct.ACPI_RTCT_V2_TYPE_GT_WayMasks:
|
||||
cap = add_child(cache_node, "parameter", None, id="GT Waymask")
|
||||
for waymask in entry.waymask:
|
||||
add_child(cap, "waymask", hex(waymask))
|
||||
elif entry.type == acpiparser.rtct.ACPI_RTCT_V2_TYPE_SSRAM_WayMask:
|
||||
ssram_node = get_or_create_ssram_node(cache_node)
|
||||
add_child(ssram_node, "waymask", hex(entry.waymask))
|
||||
elif entry.type == acpiparser.rtct.ACPI_RTCT_V2_TYPE_SoftwareSRAM:
|
||||
ssram_node = get_or_create_ssram_node(cache_node)
|
||||
add_child(ssram_node, "start", "0x{:08x}".format(entry.base))
|
||||
add_child(ssram_node, "end", "0x{:08x}".format(entry.base + entry.size - 1))
|
||||
add_child(ssram_node, "size", str(entry.size))
|
||||
elif entry.type == acpiparser.rtct.ACPI_RTCT_V2_TYPE_MemoryHierarchyLatency:
|
||||
for cache_id in entry.cache_id:
|
||||
cache_node = get_node(caches_node, f"cache[@level='{entry.hierarchy}' and @id='{hex(cache_id)}']")
|
||||
if cache_node is None:
|
||||
logging.debug(f"Cannot find the level {entry.hierarchy} cache with cache ID {cache_id}")
|
||||
continue
|
||||
param = add_child(cache_node, "parameter", None, id="Worst Case Access Latency")
|
||||
add_child(param, "native", str(entry.clock_cycles))
|
||||
elif entry.type == acpiparser.rtct.ACPI_RTCT_V2_TYPE_ErrorLogAddress:
|
||||
start = "0x{:016x}".format(entry.address)
|
||||
end = "0x{:016x}".format(entry.address + entry.size - 1)
|
||||
size = str(entry.size)
|
||||
region = add_child(memory_node, "range", None, id="TCC Error Log", start=start, end=end, size=size)
|
||||
|
||||
def extract_tcc_capabilities(board_etree):
|
||||
try:
|
||||
rtct = acpiparser.parse_rtct()
|
||||
if rtct.version == 1:
|
||||
extract_tcc_capabilities_from_rtct_v1(board_etree, rtct)
|
||||
elif rtct.version == 2:
|
||||
extract_tcc_capabilities_from_rtct_v2(board_etree, rtct)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
def extract(args, board_etree):
|
||||
try:
|
||||
tables = parse_apic()
|
||||
tables = acpiparser.parse_apic()
|
||||
except Exception as e:
|
||||
logging.warning(f"Parse ACPI tables failed: {str(e)}")
|
||||
logging.warning(f"Will not extract information from ACPI tables")
|
||||
|
@ -57,3 +154,5 @@ def extract(args, board_etree):
|
|||
|
||||
ioapics_node = get_node(board_etree, "//ioapics")
|
||||
extract_topology(ioapics_node, tables)
|
||||
|
||||
extract_tcc_capabilities(board_etree)
|
||||
|
|
|
@ -656,12 +656,3 @@ def generate_info(board_file):
|
|||
# Generate board info
|
||||
with open(board_file, 'a+') as config:
|
||||
gen_acpi_info(config)
|
||||
|
||||
# get the PTCT/RTCT table from native environment
|
||||
out_dir = os.path.dirname(board_file)
|
||||
if os.path.isfile(SYS_PATH[1] + 'PTCT'):
|
||||
shutil.copy(SYS_PATH[1] + 'PTCT', out_dir if out_dir != "" else "./")
|
||||
logging.info("PTCT table has been saved to {} successfully!".format(os.path.join(out_dir, 'PTCT')))
|
||||
if os.path.isfile(SYS_PATH[1] + 'RTCT'):
|
||||
shutil.copy(SYS_PATH[1] + 'RTCT', out_dir if out_dir != "" else "./")
|
||||
logging.info("RTCT table has been saved to {} successfully!".format(os.path.join(out_dir, 'RTCT')))
|
||||
|
|
|
@ -13,12 +13,10 @@ import common, math, logging
|
|||
|
||||
def import_memory_info(board_etree):
|
||||
ram_range = {}
|
||||
start = board_etree.xpath("/acrn-config/memory/range/@start")
|
||||
size = board_etree.xpath("/acrn-config/memory/range/@size")
|
||||
for i in range(len(start)):
|
||||
start_hex = int(start[i], 16)
|
||||
size_hex = int(size[i], 10)
|
||||
ram_range[start_hex] = size_hex
|
||||
for memory_range in board_etree.xpath("/acrn-config/memory/range[not(@id) or @id = 'RAM']"):
|
||||
start = int(memory_range.get("start"), base=16)
|
||||
size = int(memory_range.get("size"), base=10)
|
||||
ram_range[start] = size
|
||||
|
||||
return ram_range
|
||||
|
||||
|
|
Loading…
Reference in New Issue