acrn-hypervisor/misc/config_tools/board_inspector/legacy/dmar.py
Geoffroy Van Cutsem 8b16be9185 Remove "All rights reserved" string headers
Many of the license and Intel copyright headers include the "All rights
reserved" string. It is not relevant in the context of the BSD-3-Clause
license that the code is released under. This patch removes those strings
throughout the code (hypervisor, devicemodel and misc).

Tracked-On: #7254
Signed-off-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com>
2022-04-06 13:21:02 +08:00

402 lines
14 KiB
Python

# Copyright (C) 2019 Intel Corporation.
#
# SPDX-License-Identifier: BSD-3-Clause
#
import sys
import ctypes
import parser_lib
ACPI_DMAR_TYPE = {
'ACPI_DMAR_TYPE_HARDWARE_UNIT':0,
'ACPI_DMAR_TYPE_RESERVED_MEMORY':1,
'ACPI_DMAR_TYPE_ROOT_ATS':2,
'ACPI_DMAR_TYPE_HARDWARE_AFFINITY':3,
'ACPI_DMAR_TYPE_NAMESPACE':4,
'ACPI_DMAR_TYPE_RESERVED':5,
}
ACPI_DEV_SCOPE_TYPE = {
'ACPI_DMAR_SCOPE_TYPE_NOT_USED':0,
'ACPI_DMAR_SCOPE_TYPE_ENDPOINT':1,
'ACPI_DMAR_SCOPE_TYPE_BRIDGE':2,
'ACPI_DMAR_SCOPE_TYPE_IOAPIC':3,
'ACPI_DMAR_SCOPE_TYPE_HPET':4,
'ACPI_DMAR_SCOPE_TYPE_NAMESPACE':5,
'ACPI_DMAR_SCOPE_TYPE_RESERVED':6,
}
class DmarHeader(ctypes.Structure):
"""DMAR Header"""
_pack_ = 1
_fields_ = [
('signature', ctypes.c_char*4),
('length', ctypes.c_uint32),
('revision', ctypes.c_ubyte),
('checksum', ctypes.c_ubyte),
('oem_id', ctypes.c_char*6),
('oem_table_id', ctypes.c_char*8),
('oem_revision', ctypes.c_uint32),
('asl_compiler_id', ctypes.c_char*4),
('asl_compiler_revision', ctypes.c_uint32),
('host_addr_width', ctypes.c_ubyte),
('flags', ctypes.c_ubyte),
('reserved', ctypes.c_ubyte*10),
]
def style_check_1(self):
"""Style check if have public method"""
self._pack_ = 0
def style_check_2(self):
"""Style check if have public method"""
self._pack_ = 0
class DmarDevScope(ctypes.Structure):
"""DMAR Device Scope"""
_pack_ = 1
_fields_ = [
('entry_type', ctypes.c_uint8),
('scope_length', ctypes.c_uint8),
('reserved', ctypes.c_uint16),
('enumeration_id', ctypes.c_uint8),
('bus', ctypes.c_uint8),
]
def style_check_1(self):
"""Style check if have public method"""
self._pack_ = 0
def style_check_2(self):
"""Style check if have public method"""
self._pack_ = 0
class DmarHwUnit(ctypes.Structure):
"""DMAR Hardware Unit"""
_pack_ = 1
_fields_ = [
('type', ctypes.c_uint16),
('length', ctypes.c_uint16),
('flags', ctypes.c_uint8),
('reserved', ctypes.c_uint8),
('segment', ctypes.c_uint16),
('address', ctypes.c_uint64),
]
def style_check_1(self):
"""Style check if have public method"""
self._pack_ = 0
def style_check_2(self):
"""Style check if have public method"""
self._pack_ = 0
class DevScopePath(ctypes.Structure):
"""DEVICE Scope Path"""
_pack_ = 1
_fields_ = [
("device", ctypes.c_uint8),
("function", ctypes.c_uint8),
]
def style_check_1(self):
"""Style check if have public method"""
self._pack_ = 0
def style_check_2(self):
"""Style check if have public method"""
self._pack_ = 0
class DmarHwList:
"""DMAR HW List"""
def __init__(self):
self.hw_segment_list = []
self.hw_flags_list = []
self.hw_address_list = []
self.hw_ignore = {}
def style_check_1(self):
"""Style check if have public method"""
self.hw_ignore = {}
def style_check_2(self):
"""Style check if have public method"""
self.hw_ignore = {}
class DmarDevList:
"""DMAR DEV List"""
def __init__(self):
self.dev_scope_cnt_list = []
self.dev_bus_list = []
self.dev_path_list = []
self.dev_scope_id_list = []
self.dev_scope_type_list = []
def style_check_1(self):
"""Style check if have public method"""
self.dev_bus_list = []
def style_check_2(self):
"""Style check if have public method"""
self.dev_bus_list = []
class DmarTbl:
"""DMAR TBL"""
def __init__(self):
self.drhd_offset = 0
self.dmar_drhd = 0
self.dmar_dev_scope = 0
self.dev_scope_offset = 0
self.dev_scope_cnt = 0
self.path_offset = 0
def style_check_1(self):
"""Style check if have public method"""
self.path_offset = 0
def style_check_2(self):
"""Style check if have public method"""
self.path_offset = 0
# TODO: Get board information is independent part of acrn-config tools, it does not get the GPU_SBDF default
# config from the other part of tools, so hard code the GPU_SBDF to gernerate DRHDx_IGNORE macro
CONFIG_IGD_SBDF = 0x10
PCI_BRIDGE_HEADER = 1
class PathDevFun:
"""Path Device Function meta data"""
def __init__(self):
self.path = 0
self.device = 0
self.function = 0
def style_check_1(self):
"""Style check if have public method"""
self.path = 0
def style_check_2(self):
"""Style check if have public method"""
self.path = 0
def get_secondary_bus(dmar_tbl, tmp_dev, tmp_fun):
cmd = "lspci -xxx"
secondary_bus_str = ''
found_pci_bdf = False
pci_bridge_header_type = False
res = parser_lib.cmd_execute(cmd)
while True:
line = res.stdout.readline().decode("ascii")
if not line:
break
if ':' not in line or len(line.strip().split(":")) < 1:
continue
if not found_pci_bdf:
if '.' not in line.strip():
continue
bus = int(line.strip().split(":")[0], 16)
dev = int(line.strip().split()[0].split(":")[1].split(".")[0], 16)
fun = int(line.strip().split()[0].split(":")[1].split(".")[1].strip(), 16)
if bus == dmar_tbl.dmar_dev_scope.bus and dev == tmp_dev and fun == tmp_fun:
found_pci_bdf = True
continue
else:
if "00:" == line.strip().split()[0]:
# PCI Header type stores in 0xE
if len(line.split()) >= 16 and int(line.strip().split()[15], 16) & 0x7 == PCI_BRIDGE_HEADER:
pci_bridge_header_type = True
continue
if not pci_bridge_header_type:
continue
# found the pci device, parse the secondary bus
if "10:" == line.strip().split()[0]:
# Secondary PCI BUS number stores in 0x18
secondary_bus_str = line.split()[9]
found_pci_bdf = False
pci_bridge_header_type = False
break
# the pci device has secondary bus
if secondary_bus_str:
dmar_tbl.dmar_dev_scope.bus = int(secondary_bus_str, 16)
def walk_pci_bus(tmp_pdf, dmar_tbl, dmar_hw_list, drhd_cnt):
"""Walk Pci bus
:param tmp_pdf: it is a class what contains path,device,function in dmar device scope region
:param dmar_tbl: it is a class to describe dmar which contains Device Scope and DRHD
:param dmar_hw_list: it is a class to describe hardware scope in DMAR table
:param drhd_cnt: it is a counter to calculate the DRHD in DMAR table
"""
# path offset is in end of device spcope
dmar_tbl.path_offset = dmar_tbl.dev_scope_offset + ctypes.sizeof(DmarDevScope)
n_cnt = (dmar_tbl.dmar_dev_scope.scope_length - ctypes.sizeof(DmarDevScope)) // 2
while n_cnt:
scope_path = DevScopePath.from_address(dmar_tbl.path_offset)
tmp_pdf.device = scope_path.device
tmp_pdf.function = scope_path.function
tmp_pdf.path = (((tmp_pdf.device & 0x1F) << 3) | ((tmp_pdf.function & 0x7)))
# walk the secondary pci bus
get_secondary_bus(dmar_tbl, tmp_pdf.device, tmp_pdf.function)
if ((dmar_tbl.dmar_drhd.segment << 16) | (
dmar_tbl.dmar_dev_scope.bus << 8) | tmp_pdf.path) == CONFIG_IGD_SBDF:
dmar_hw_list.hw_ignore[drhd_cnt] = 'true'
dmar_tbl.path_offset += ctypes.sizeof(DevScopePath)
n_cnt -= 1
def walk_dev_scope(dmar_tbl, dmar_dev_list, dmar_hw_list, drhd_cnt):
"""Walk device scope
:param dmar_tbl: it is a class to describe dmar which contains Device Scope and DRHD
:param dmar_dev_list: it is a class to describe device scope in DMAR table
:param dmar_hw_list: it is a class to describe DRHD in DMAR table
:param drhd_cnt: it is a counter to calculate the DRHD in DMAR table
"""
dmar_tbl.dev_scope_offset = dmar_tbl.drhd_offset + ctypes.sizeof(DmarHwUnit)
scope_end = dmar_tbl.dev_scope_offset + dmar_tbl.dmar_drhd.length
dmar_tbl.dev_scope_cnt = 0
while dmar_tbl.dev_scope_offset < scope_end:
dmar_tbl.dmar_dev_scope = DmarDevScope.from_address(dmar_tbl.dev_scope_offset)
if dmar_tbl.dmar_dev_scope.scope_length <= 0:
break
if dmar_tbl.dmar_dev_scope.entry_type != \
ACPI_DEV_SCOPE_TYPE['ACPI_DMAR_SCOPE_TYPE_NOT_USED'] and \
dmar_tbl.dmar_dev_scope.entry_type < \
ACPI_DEV_SCOPE_TYPE['ACPI_DMAR_SCOPE_TYPE_RESERVED']:
dmar_tbl.dev_scope_cnt += 1
# get type and id from device scope
dmar_dev_list.dev_scope_type_list.append(dmar_tbl.dmar_dev_scope.entry_type)
dmar_dev_list.dev_scope_id_list.append(dmar_tbl.dmar_dev_scope.enumeration_id)
# walk the pci bus with path deep, and find the {Device,Function}
tmp_pdf = PathDevFun()
walk_pci_bus(tmp_pdf, dmar_tbl, dmar_hw_list, drhd_cnt)
dmar_dev_list.dev_bus_list.append(dmar_tbl.dmar_dev_scope.bus)
dmar_dev_list.dev_path_list.append(tmp_pdf.path)
dmar_tbl.dev_scope_offset += dmar_tbl.dmar_dev_scope.scope_length
def walk_dmar_table(dmar_tbl, dmar_hw_list, dmar_dev_list, sysnode):
"""Walk dmar table and get information
:param dmar_tbl: it is a class to describe dmar which contains Device Scope and DRHD
:param dmar_hw_list: it is a class to describe hardware scope in DMAR table
:param dmar_dev_list: it is a class to describe device scope in DMAR table
:param sysnode: the system device node of acpi table, such as: /sys/firmware/acpi/tables/DMAR
"""
data = open(sysnode, 'rb').read()
buf = ctypes.create_string_buffer(data, len(data))
addr = ctypes.addressof(buf)
# contain the dmar tbl_header
dmar_tbl_header = DmarHeader.from_address(addr)
# cytpes.c_int16.from_address(addr) reade int16 from ad1
# in end of tbl header is remapping structure(DRHD/sub tbl)
dmar_tbl.drhd_offset = addr + ctypes.sizeof(DmarHeader)
drhd_cnt = 0
while True:
# get one DRHD type in sub table
dmar_tbl.dmar_drhd = DmarHwUnit.from_address(dmar_tbl.drhd_offset)
dmar_type = dmar_tbl.dmar_drhd.type
dmar_len = dmar_tbl.dmar_drhd.length
if dmar_tbl.drhd_offset - addr >= dmar_tbl_header.length:
break
if dmar_type != ACPI_DMAR_TYPE['ACPI_DMAR_TYPE_HARDWARE_UNIT']:
dmar_tbl.drhd_offset += dmar_len
continue
# initialize DRHDx_IGNORE to false
dmar_hw_list.hw_ignore[drhd_cnt] = 'false'
dmar_hw_list.hw_segment_list.append(dmar_tbl.dmar_drhd.segment)
dmar_hw_list.hw_flags_list.append(dmar_tbl.dmar_drhd.flags)
dmar_hw_list.hw_address_list.append(dmar_tbl.dmar_drhd.address)
# in end of DRHD/sub tbl header is dev scope, then enumerate the device scope
walk_dev_scope(dmar_tbl, dmar_dev_list, dmar_hw_list, drhd_cnt)
dmar_dev_list.dev_scope_cnt_list.append(dmar_tbl.dev_scope_cnt)
drhd_cnt += 1
dmar_tbl.drhd_offset += dmar_len
return (dmar_tbl, dmar_hw_list, dmar_dev_list, drhd_cnt)
def write_dmar_data(sysnode, config):
"""Write the DMAR data to board info
:param sysnode: the system device node of acpi table, such as: /sys/firmware/acpi/tables/DMAR
:param config: file pointer that opened for writing board information
"""
dmar_hw_list = DmarHwList()
dmar_dev_list = DmarDevList()
dmar_tbl = DmarTbl()
(dmar_tbl, dmar_hw_list, dmar_dev_list, drhd_cnt) = walk_dmar_table(
dmar_tbl, dmar_hw_list, dmar_dev_list, sysnode)
print("\t#define DRHD_COUNT {0}U".format(drhd_cnt), file=config)
print("", file=config)
prev_dev_scope_num = 0
for drhd_hw_i in range(drhd_cnt):
dev_scope_num = dmar_dev_list.dev_scope_cnt_list[drhd_hw_i]
print("\t#define DRHD"+str(drhd_hw_i)+"_DEV_CNT {0}U".format(
hex(dmar_dev_list.dev_scope_cnt_list[drhd_hw_i])), file=config)
print("\t#define DRHD"+str(drhd_hw_i)+"_SEGMENT {0}U".format(
hex(dmar_hw_list.hw_segment_list[drhd_hw_i])), file=config)
print("\t#define DRHD"+str(drhd_hw_i)+"_FLAGS {0}U".format(
hex(dmar_hw_list.hw_flags_list[drhd_hw_i])), file=config)
print("\t#define DRHD"+str(drhd_hw_i)+"_REG_BASE 0x{:0>2X}UL".format(
dmar_hw_list.hw_address_list[drhd_hw_i]), file=config)
if drhd_hw_i in dmar_hw_list.hw_ignore.keys():
print("\t#define DRHD"+str(drhd_hw_i)+"_IGNORE {0}".format(
dmar_hw_list.hw_ignore[drhd_hw_i]), file=config)
for dev_scope_i in range(dev_scope_num):
print("\t#define DRHD"+str(drhd_hw_i)+"_DEVSCOPE"+str(dev_scope_i),
file=config, end="")
print("_TYPE {0}U".format(
hex(dmar_dev_list.dev_scope_type_list[prev_dev_scope_num + dev_scope_i])),
file=config)
print("\t#define DRHD"+str(drhd_hw_i)+"_DEVSCOPE"+str(dev_scope_i),
file=config, end="")
print("_ID {0}U".format(
hex(dmar_dev_list.dev_scope_id_list[prev_dev_scope_num + dev_scope_i])),
file=config)
print("\t#define DRHD"+str(drhd_hw_i)+"_DEVSCOPE"+str(dev_scope_i),
file=config, end="")
print("_BUS {0}U".format(hex(
dmar_dev_list.dev_bus_list[prev_dev_scope_num + dev_scope_i])),
file=config)
print("\t#define DRHD"+str(drhd_hw_i)+"_DEVSCOPE"+str(dev_scope_i),
file=config, end="")
print("_PATH {0}U".format(hex(
dmar_dev_list.dev_path_list[prev_dev_scope_num + dev_scope_i])),
file=config)
print("", file=config)
prev_dev_scope_num += dev_scope_num