mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-05-10 09:25:36 +00:00
1. "make clean && make BOARD=nuc11tnbi5 SCENARIO=shared" will generate the acrn debian package. 2. "make clean && make board_inspector" will generate the acrn board_inspector debian package Tracked-On: #6688 Signed-off-by: Hu Fenglin <fenglin.hu@intel.com>
168 lines
5.0 KiB
Python
168 lines
5.0 KiB
Python
# Copyright (C) 2021 Intel Corporation. All rights reserved.
|
|
#
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
#
|
|
|
|
import ctypes
|
|
import copy
|
|
import inspectorlib.cdata as cdata
|
|
|
|
class Capability:
|
|
# Capability names from PCI Local Bus Specification and PCI Express Base Specification
|
|
_cap_names_ = {
|
|
0x01: "Power Management",
|
|
0x02: "AGP",
|
|
0x03: "VPD",
|
|
0x04: "Slot Identification",
|
|
0x05: "MSI",
|
|
0x06: "CompactPCI Hot Swap",
|
|
0x07: "PCI-X",
|
|
0x08: "Hyper Transport",
|
|
0x09: "Vendor-Specific",
|
|
0x0a: "Debug port",
|
|
0x0b: "CompactPCI Central Resource Control",
|
|
0x0c: "Hot Plug",
|
|
0x0d: "Subsystem ID and Subsystem Vendor ID",
|
|
0x0e: "AGP 8x",
|
|
0x0f: "Secure Device",
|
|
0x10: "PCI Express",
|
|
0x11: "MSI-X",
|
|
0x13: "Conventional PCI Advanced Features",
|
|
0x14: "Enhanced Allocation",
|
|
0x15: "FPB",
|
|
}
|
|
|
|
@property
|
|
def name(self):
|
|
if self.id in self._cap_names_.keys():
|
|
return self._cap_names_[self.id]
|
|
else:
|
|
return f"Reserved ({hex(self.id)})"
|
|
|
|
class CapabilityListRegister(cdata.Struct, Capability):
|
|
_pack_ = 1
|
|
_fields_ = [
|
|
('id', ctypes.c_uint8),
|
|
('next_cap_ptr', ctypes.c_uint8),
|
|
]
|
|
|
|
# Power Management (0x01)
|
|
|
|
class PowerManagement(cdata.Struct, Capability):
|
|
_pack_ = 1
|
|
_fields_ = copy.copy(CapabilityListRegister._fields_) + [
|
|
('version', ctypes.c_uint16, 3),
|
|
('pme_clock', ctypes.c_uint16, 1),
|
|
('immediate_readiness_on_return_to_d0', ctypes.c_uint16, 1),
|
|
('device_specific_initialization', ctypes.c_uint16, 1),
|
|
('aux_current', ctypes.c_uint16, 3),
|
|
('d1_support', ctypes.c_uint16, 1),
|
|
('d2_support', ctypes.c_uint16, 1),
|
|
('pme_support', ctypes.c_uint16, 5),
|
|
('power_state', ctypes.c_uint16, 2),
|
|
('reserved1', ctypes.c_uint16, 1),
|
|
('no_soft_reset', ctypes.c_uint16, 1),
|
|
('reserved2', ctypes.c_uint16, 4),
|
|
('pme_en', ctypes.c_uint16, 1),
|
|
('data_select', ctypes.c_uint16, 4),
|
|
('data_scale', ctypes.c_uint16, 2),
|
|
('pme_status', ctypes.c_uint16, 1),
|
|
('reserved3', ctypes.c_uint8, 6),
|
|
('undefined', ctypes.c_uint8, 2),
|
|
('data', ctypes.c_uint8),
|
|
]
|
|
|
|
def parse_power_management(buf, cap_ptr):
|
|
return PowerManagement.from_buffer_copy(buf, cap_ptr)
|
|
|
|
# MSI (0x05)
|
|
|
|
def MSI_factory(field_list):
|
|
class MSI(cdata.Struct, Capability):
|
|
_pack_ = 1
|
|
_fields_ = copy.copy(CapabilityListRegister._fields_) + [
|
|
('msi_enable', ctypes.c_uint16, 1),
|
|
('multiple_message_capable', ctypes.c_uint16, 3),
|
|
('multiple_message_enable', ctypes.c_uint16, 3),
|
|
('address_64bit', ctypes.c_uint16, 1),
|
|
('per_vector_masking_capable', ctypes.c_uint16, 1),
|
|
('reserved', ctypes.c_uint16, 7),
|
|
] + field_list
|
|
|
|
return MSI
|
|
|
|
def msi_field_list(addr):
|
|
field_list = list()
|
|
msgctrl = MSI_factory([]).from_address(addr)
|
|
|
|
if msgctrl.address_64bit == 1:
|
|
field_list.append(('message_address', ctypes.c_uint64))
|
|
else:
|
|
field_list.append(('message_address', ctypes.c_uint32))
|
|
|
|
field_list.append(('message_data', ctypes.c_uint16))
|
|
|
|
if msgctrl.per_vector_masking_capable:
|
|
field_list.append(('reserved', ctypes.c_uint16))
|
|
field_list.append(('mask_bits', ctypes.c_uint32))
|
|
field_list.append(('pending_bits', ctypes.c_uint32))
|
|
|
|
return field_list
|
|
|
|
def parse_msi(buf, cap_ptr):
|
|
addr = ctypes.addressof(buf) + cap_ptr
|
|
field_list = msi_field_list(addr)
|
|
return MSI_factory(field_list).from_buffer_copy(buf, cap_ptr)
|
|
|
|
# MSI-X (0x11)
|
|
|
|
class MSIX(cdata.Struct, Capability):
|
|
_pack_ = 1
|
|
_fields_ = copy.copy(CapabilityListRegister._fields_) + [
|
|
('table_size_z', ctypes.c_uint16, 10),
|
|
('reserved', ctypes.c_uint16, 3),
|
|
('function_mask', ctypes.c_uint16, 1),
|
|
('msix_enable', ctypes.c_uint16, 1),
|
|
('table_bir', ctypes.c_uint32, 3),
|
|
('table_offset_z', ctypes.c_uint32, 29),
|
|
('pba_bir', ctypes.c_uint32, 3),
|
|
('pba_offset_z', ctypes.c_uint32, 29),
|
|
]
|
|
|
|
@property
|
|
def table_size(self):
|
|
return self.table_size_z + 1
|
|
|
|
@property
|
|
def table_offset(self):
|
|
return self.table_offset_z << 3
|
|
|
|
@property
|
|
def pba_offset(self):
|
|
return self.pba_offset_z << 3
|
|
|
|
def parse_msix(buf, cap_ptr):
|
|
return MSIX.from_buffer_copy(buf, cap_ptr)
|
|
|
|
# Module API
|
|
|
|
capability_parsers = {
|
|
0x1: parse_power_management,
|
|
0x5: parse_msi,
|
|
0x11: parse_msix,
|
|
}
|
|
|
|
def capabilities(data, cap_ptr):
|
|
buf = ctypes.create_string_buffer(data, len(data))
|
|
|
|
acc = list()
|
|
while cap_ptr != 0:
|
|
caplist = CapabilityListRegister.from_buffer_copy(buf, cap_ptr)
|
|
if caplist.id in capability_parsers.keys():
|
|
acc.append(capability_parsers[caplist.id](buf, cap_ptr))
|
|
else:
|
|
acc.append(caplist)
|
|
cap_ptr = caplist.next_cap_ptr
|
|
|
|
return acc
|