acrn-hypervisor/misc/config_tools/board_inspector/acpiparser/rtct.py
Junjie Mao 99f15a27c2 board_inspector/acpiparser: enable parsing RTCT v2
This patch adds support to parse RTCT v2 using the refined board XML
schema. The major changes include:

 - Add the RTCT v2 parser in the acpiparser module. The version of an RTCT
   is detected automatically to choose the right parser.
 - Extract software SRAM capabilities of caches into the board XML.
 - Move the logic that determines the software SRAM base address for the
   pre-launched VM to the static allocator of GPAs.
 - Generate software SRAM related macros into misc_cfg.h when necessary.

Tracked-On: #6020
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
2021-05-19 08:53:38 +08:00

293 lines
9.9 KiB
Python

# Copyright (C) 2021 Intel Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
import ctypes
import copy
import lib.cdata as cdata
from acpiparser._utils import TableHeader
# Common structures
class RTCTSubtable(cdata.Struct):
_pack_ = 1
_fields_ = [
('subtable_size', ctypes.c_uint16),
('format', ctypes.c_uint16),
('type', ctypes.c_uint32),
]
ACPI_RTCT_TYPE_COMPATIBILITY = 0
class RTCTSubtableCompatibility(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('rtct_version_major', ctypes.c_uint32),
('rtct_version_minor', ctypes.c_uint32),
('rtcd_version_major', ctypes.c_uint32),
('rtcd_version_minor', ctypes.c_uint32),
]
def RTCTSubtableUnknown_factory(data_len):
class RTCTSubtableUnknown(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('data', ctypes.c_uint8 * data_len),
]
return RTCTSubtableUnknown
# RTCT v1
ACPI_RTCT_V1_TYPE_RTCM_BINARY = 2
ACPI_RTCT_V1_TYPE_WRC_L3Waymasks = 3
ACPI_RTCT_V1_TYPE_GT_L3Waymasks = 4
ACPI_RTCT_V1_TYPE_SoftwareSRAM = 5
ACPI_RTCT_V1_TYPE_Memory_Hierarchy_Latency = 9
class RTCTSubtableRTCMBinary(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('address', ctypes.c_uint64),
('size', ctypes.c_uint32),
]
def RTCTSubtableWRCL3Waymasks_factory(data_len):
class RTCTSubtableWRCL3Waymasks(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('waymask', ctypes.c_uint32 * (data_len // 4)),
]
return RTCTSubtableWRCL3Waymasks
def RTCTSubtableGTL3Waymasks_factory(data_len):
class RTCTSubtableGTL3Waymasks(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('waymask', ctypes.c_uint32 * (data_len // 4)),
]
return RTCTSubtableGTL3Waymasks
def RTCTSubtableSoftwareSRAM_v1_factory(data_len):
class RTCTSubtableSoftwareSRAM_v1(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('cache_level', ctypes.c_uint32),
('base', ctypes.c_uint64),
('ways', ctypes.c_uint32),
('size', ctypes.c_uint32),
('apic_id_tbl', ctypes.c_uint32 * ((data_len - 20) // 4)),
]
return RTCTSubtableSoftwareSRAM_v1
def RTCTSubtableMemoryHierarchyLatency_v1_factory(data_len):
class RTCTSubtableMemoryHierarchyLatency_v1(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('hierarchy', ctypes.c_uint32),
('clock_cycles', ctypes.c_uint32),
('apic_id_tbl', ctypes.c_uint32 * ((data_len - 8) // 4)),
]
return RTCTSubtableMemoryHierarchyLatency_v1
# RTCT v2
ACPI_RTCT_V2_TYPE_RTCD_Limits = 1
ACPI_RTCT_V2_TYPE_CRL_Binary = 2
ACPI_RTCT_V2_TYPE_IA_WayMasks = 3
ACPI_RTCT_V2_TYPE_WRC_WayMasks = 4
ACPI_RTCT_V2_TYPE_GT_WayMasks = 5
ACPI_RTCT_V2_TYPE_SSRAM_WayMask = 6
ACPI_RTCT_V2_TYPE_SoftwareSRAM = 7
ACPI_RTCT_V2_TYPE_MemoryHierarchyLatency = 8
ACPI_RTCT_V2_TYPE_ErrorLogAddress = 9
class RTCTSubtableRTCDLimits(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('total_ia_l2_clos', ctypes.c_uint32),
('total_ia_l3_clos', ctypes.c_uint32),
('total_l2_instances', ctypes.c_uint32),
('total_l3_instances', ctypes.c_uint32),
('total_gt_clos', ctypes.c_uint32),
('total_wrc_clos', ctypes.c_uint32),
('max_tcc_streams', ctypes.c_uint32),
('max_tcc_registers', ctypes.c_uint32),
]
def RTCTSubtableIAWayMasks_factory(data_len):
class RTCTSubtableIAWayMasks(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('level', ctypes.c_uint32),
('cache_id', ctypes.c_uint32),
('waymask', ctypes.c_uint32 * ((data_len - 8) // 4)),
]
return RTCTSubtableIAWayMasks
class RTCTSubtableWRCWayMasks(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('level', ctypes.c_uint32),
('cache_id', ctypes.c_uint32),
('waymask', ctypes.c_uint32),
]
def RTCTSubtableGTWayMasks_factory(data_len):
class RTCTSubtableGTWayMasks(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('level', ctypes.c_uint32),
('cache_id', ctypes.c_uint32),
('waymask', ctypes.c_uint32 * ((data_len - 8) // 4)),
]
return RTCTSubtableGTWayMasks
class RTCTSubtableSSRAMWayMask(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('level', ctypes.c_uint32),
('cache_id', ctypes.c_uint32),
('waymask', ctypes.c_uint32),
]
def RTCTSubtableSoftwareSRAM_v2_factory(data_len):
class RTCTSubtableSoftwareSRAM_v2(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('level', ctypes.c_uint32),
('cache_id', ctypes.c_uint32),
('base', ctypes.c_uint64),
('size', ctypes.c_uint32),
('shared', ctypes.c_uint32),
]
return RTCTSubtableSoftwareSRAM_v2
def RTCTSubtableMemoryHierarchyLatency_v2_factory(data_len):
class RTCTSubtableMemoryHierarchyLatency_v2(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('hierarchy', ctypes.c_uint32),
('clock_cycles', ctypes.c_uint32),
('cache_id', ctypes.c_uint32 * ((data_len - 8) // 4)),
]
return RTCTSubtableMemoryHierarchyLatency_v2
class RTCTSubtableErrorLogAddress(cdata.Struct):
_pack_ = 1
_fields_ = copy.copy(RTCTSubtable._fields_) + [
('address', ctypes.c_uint64),
('size', ctypes.c_uint32),
]
# Parsers
def rtct_version(addr, length):
end = addr + length
while addr < end:
subtable = RTCTSubtable.from_address(addr)
if subtable.type == ACPI_RTCT_TYPE_COMPATIBILITY:
subtable = RTCTSubtableCompatibility.from_address(addr)
return subtable.rtct_version_major
addr += subtable.subtable_size
# RTCT v1 does not have a compatibility entry
return 1
def rtct_v1_subtable_list(addr, length):
end = addr + length
field_list = list()
subtable_num = 0
while addr < end:
subtable_num += 1
subtable = RTCTSubtable.from_address(addr)
data_len = subtable.subtable_size - ctypes.sizeof(RTCTSubtable)
if subtable.type == ACPI_RTCT_V1_TYPE_RTCM_BINARY:
cls = RTCTSubtableRTCMBinary
elif subtable.type == ACPI_RTCT_V1_TYPE_WRC_L3Waymasks:
cls = RTCTSubtableWRCL3Waymasks_factory(data_len)
elif subtable.type == ACPI_RTCT_V1_TYPE_GT_L3Waymasks:
cls = RTCTSubtableGTL3Waymasks_factory(data_len)
elif subtable.type == ACPI_RTCT_V1_TYPE_SoftwareSRAM:
cls = RTCTSubtableSoftwareSRAM_v1_factory(data_len)
elif subtable.type == ACPI_RTCT_V1_TYPE_Memory_Hierarchy_Latency:
cls = RTCTSubtableMemoryHierarchyLatency_v1_factory(data_len)
else:
cls = RTCTSubtableUnknown_factory(data_len)
addr += subtable.subtable_size
field_list.append( ('subtable{}'.format(subtable_num), cls) )
return field_list
def rtct_v2_subtable_list(addr, length):
end = addr + length
field_list = list()
subtable_num = 0
while addr < end:
subtable_num += 1
subtable = RTCTSubtable.from_address(addr)
data_len = subtable.subtable_size - ctypes.sizeof(RTCTSubtable)
if subtable.type == ACPI_RTCT_V2_TYPE_RTCD_Limits:
cls = RTCTSubtableRTCDLimits
elif subtable.type == ACPI_RTCT_V2_TYPE_CRL_Binary:
cls = RTCTSubtableRTCMBinary
elif subtable.type == ACPI_RTCT_V2_TYPE_IA_WayMasks:
cls = RTCTSubtableIAWayMasks_factory(data_len)
elif subtable.type == ACPI_RTCT_V2_TYPE_WRC_WayMasks:
cls = RTCTSubtableWRCWayMasks
elif subtable.type == ACPI_RTCT_V2_TYPE_GT_WayMasks:
cls = RTCTSubtableGTWayMasks_factory(data_len)
elif subtable.type == ACPI_RTCT_V2_TYPE_SSRAM_WayMask:
cls = RTCTSubtableSSRAMWayMask
elif subtable.type == ACPI_RTCT_V2_TYPE_SoftwareSRAM:
cls = RTCTSubtableSoftwareSRAM_v2_factory(data_len)
elif subtable.type == ACPI_RTCT_V2_TYPE_MemoryHierarchyLatency:
cls = RTCTSubtableMemoryHierarchyLatency_v2_factory(data_len)
elif subtable.type == ACPI_RTCT_V2_TYPE_ErrorLogAddress:
cls = RTCTSubtableErrorLogAddress
else:
cls = RTCTSubtableUnknown_factory(data_len)
addr += subtable.subtable_size
field_list.append( ('subtable{}'.format(subtable_num), cls) )
return field_list
def rtct_version_and_subtable_list(addr, length):
version = rtct_version(addr, length)
if version == 1:
return (version, rtct_v1_subtable_list(addr, length))
else:
return (version, rtct_v2_subtable_list(addr, length))
def rtct_factory(field_list, version):
class subtables(cdata.Struct):
_pack_ = 1
_fields_ = field_list
def __iter__(self):
for f in self._fields_:
yield getattr(self, f[0])
class RTCT(cdata.Struct):
_pack_ = 1
_fields_ = [
('header', TableHeader),
('entries', subtables),
]
@property
def version(self):
return version
return RTCT
def RTCT(val):
"""Create class based on decode of an RTCT table from filename."""
base_length = ctypes.sizeof(rtct_factory(list(), 0))
data = open(val, mode='rb').read()
buf = ctypes.create_string_buffer(data, len(data))
addr = ctypes.addressof(buf)
hdr = TableHeader.from_address(addr)
version, field_list = rtct_version_and_subtable_list(addr + base_length, hdr.length - base_length)
return rtct_factory(field_list, version).from_buffer_copy(data)