acrn-hypervisor/misc/acrn-config/board_config/pci_devices_h.py
Wei Liu ed8ac484ad acrn-config: remove the same parameters and functions from board_cfg_lib
Board config should relay on library/common.py and board_cfg_lib, then
remove the duplicate parameters and functions.

Tracked-On: #3854
Signed-off-by: Wei Liu <weix.w.liu@intel.com>
Acked-by: Victor Sun <victor.sun@intel.com>
Acked-by: Terry Zou <terry.zou@intel.com>
2020-04-08 10:19:17 +08:00

251 lines
7.6 KiB
Python

# Copyright (C) 2019 Intel Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
import collections
import board_cfg_lib
import common
PCI_HEADER = r"""
#ifndef PCI_DEVICES_H_
#define PCI_DEVICES_H_
"""
PCI_END_HEADER = r"""
#endif /* PCI_DEVICES_H_ */"""
HI_MMIO_OFFSET = 0
class Bar_Mem:
def __init__(self):
self.addr = 0
self.remapped = False
class Bar_Attr:
def __init__(self):
self.name = 0
self.remappable = True
class Pci_Dev_Bar_Desc:
def __init__(self):
self.pci_dev_dic = {}
self.pci_bar_dic = {}
PCI_DEV_BAR_DESC = Pci_Dev_Bar_Desc()
def get_value_after_str(line, key):
""" Get the value after cstate string """
idx = 0
line_in_list = line.split()
for idx_key, val in enumerate(line_in_list):
if val == key:
idx = idx_key
break
return line_in_list[idx + 1]
def check_bar_remappable(line):
#TODO: check device BAR remappable per ACPI table
return True
def get_size(line):
# get size string from format, Region n: Memory at x ... [size=NK]
size_str = line.split()[-1].strip(']').split('=')[1]
if 'G' in size_str:
size = int(size_str.strip('G')) * common.SIZE_G
elif 'M' in size_str:
size = int(size_str.strip('M')) * common.SIZE_M
elif 'K' in size_str:
size = int(size_str.strip('K')) * common.SIZE_K
else:
size = int(size_str)
return size
# round up the running bar_addr to the size of the incoming bar "line"
def remap_bar_addr_to_high(bar_addr, line):
"""Generate vbar address"""
global HI_MMIO_OFFSET
size = get_size(line)
cur_addr = common.round_up(bar_addr, size)
HI_MMIO_OFFSET = cur_addr + size
return cur_addr
def parser_pci():
""" Parse PCI lines """
cur_bdf = 0
prev_bdf = 0
tmp_bar_dic = {}
bar_addr = bar_num = '0'
cal_sub_pci_name = []
pci_lines = board_cfg_lib.get_info(
common.BOARD_INFO_FILE, "<PCI_DEVICE>", "</PCI_DEVICE>")
for line in pci_lines:
tmp_bar_mem = Bar_Mem()
# get pci bar information into PCI_DEV_BAR_DESC
if "Region" in line and "Memory at" in line:
#ignore memory region from SR-IOV capabilities
if "size=" not in line:
continue
bar_addr = int(get_value_after_str(line, "at"), 16)
bar_num = line.split()[1].strip(':')
if bar_addr >= common.SIZE_4G or bar_addr < common.SIZE_2G:
if not tmp_bar_attr.remappable:
continue
bar_addr = remap_bar_addr_to_high(HI_MMIO_OFFSET, line)
tmp_bar_mem.remapped = True
tmp_bar_mem.addr = hex(bar_addr)
tmp_bar_dic[int(bar_num)] = tmp_bar_mem
else:
tmp_bar_attr = Bar_Attr()
prev_bdf = cur_bdf
pci_bdf = line.split()[0]
tmp_bar_attr.name = " ".join(line.split(':')[1].split()[1:])
# remove '[*]' in pci subname
if '[' in tmp_bar_attr.name:
tmp_bar_attr.name = tmp_bar_attr.name.rsplit('[', 1)[0]
cal_sub_pci_name.append(tmp_bar_attr.name)
tmp_bar_attr.remappable = check_bar_remappable(line)
PCI_DEV_BAR_DESC.pci_dev_dic[pci_bdf] = tmp_bar_attr
cur_bdf = pci_bdf
if not prev_bdf:
prev_bdf = cur_bdf
if tmp_bar_dic and cur_bdf != prev_bdf:
PCI_DEV_BAR_DESC.pci_bar_dic[prev_bdf] = tmp_bar_dic
# clear the tmp_bar_dic before store the next dic
tmp_bar_dic = {}
# output all the pci device list to pci_device.h
sub_name_count = collections.Counter(cal_sub_pci_name)
if tmp_bar_dic:
PCI_DEV_BAR_DESC.pci_bar_dic[cur_bdf] = tmp_bar_dic
return sub_name_count
def write_pbdf(i_cnt, bdf, bar_attr, config):
"""
Parser and generate pbdf
:param i_cnt: the number of pci devices have the same PCI sub class name
:param bdf: it is a string what contains BDF
:param bar_attr: it is a class, contains PIC bar attribute
:param config: it is a file pointer of pci information for writing to
"""
# if there is only one host bridge, then will discard the index of suffix
if i_cnt == 0 and bar_attr.name.upper() == "HOST BRIDGE":
tmp_sub_name = "_".join(bar_attr.name.split()).upper()
else:
if '-' in bar_attr.name:
tmp_sub_name = common.undline_name(bar_attr.name) + "_" + str(i_cnt)
else:
tmp_sub_name = "_".join(bar_attr.name.split()).upper() + "_" + str(i_cnt)
bus = int(bdf.split(':')[0], 16)
dev = int(bdf.split(':')[1].split('.')[0], 16)
fun = int(bdf.split('.')[1], 16)
print("#define %-32s" % tmp_sub_name, end="", file=config)
print(" .pbdf.bits = {{.b = 0x{:02X}U, .d = 0x{:02X}U, .f = 0x{:02X}U}}".format(
bus, dev, fun), end="", file=config)
if not bar_attr.remappable:
align = ' ' * 48
print("\n{}/* TODO: add {} 64bit BAR support */".format(align, tmp_sub_name), file=config)
return
def write_vbar(i_cnt, bdf, pci_bar_dic, bar_attr, config):
"""
Parser and generate vbar
:param i_cnt: the number of pci devices have the same PCI sub class name
:param bdf: it is a string what contains BDF
:param pci_bar_dic: it is a dictionary of pci vbar for those BDF
:param bar_attr: it is a class, contains PIC bar attribute
:param config: it is a file pointer of pci information for writing to
"""
tail = 0
align = ' ' * 48
ptdev_mmio_str = ''
tmp_sub_name = common.undline_name(bar_attr.name) + "_" + str(i_cnt)
if bdf in pci_bar_dic.keys():
bar_list = list(pci_bar_dic[bdf].keys())
bar_len = len(bar_list)
bar_num = 0
for bar_i in bar_list:
if not bar_attr.remappable:
return
if tail == 0:
print(", \\", file=config)
tail += 1
bar_num += 1
bar_val = pci_bar_dic[bdf][bar_i].addr
if pci_bar_dic[bdf][bar_i].remapped:
ptdev_mmio_str = 'PTDEV_HI_MMIO_START + '
if bar_num == bar_len:
print("{}.vbar_base[{}] = {}{}UL".format(align, bar_i, ptdev_mmio_str, bar_val), file=config)
else:
print("{}.vbar_base[{}] = {}{}UL, \\".format(
align, bar_i, ptdev_mmio_str, bar_val), file=config)
else:
print("", file=config)
def generate_file(config):
"""
Get PCI device and generate pci_devices.h
:param config: it is a file pointer of pci information for writing to
"""
# write the license into pci
print("{0}".format(board_cfg_lib.HEADER_LICENSE), file=config)
# add bios and base board info
board_cfg_lib.handle_bios_info(config)
# write the header into pci
print("{0}".format(PCI_HEADER), file=config)
sub_name_count = parser_pci()
print("#define %-32s" % "PTDEV_HI_MMIO_SIZE", " {}UL".format(hex(HI_MMIO_OFFSET)), file=config)
compared_bdf = []
for cnt_sub_name in sub_name_count.keys():
i_cnt = 0
for bdf, bar_attr in PCI_DEV_BAR_DESC.pci_dev_dic.items():
if cnt_sub_name == bar_attr.name and bdf not in compared_bdf:
compared_bdf.append(bdf)
else:
continue
print("",file=config)
write_pbdf(i_cnt, bdf, bar_attr, config)
write_vbar(i_cnt, bdf, PCI_DEV_BAR_DESC.pci_bar_dic, bar_attr, config)
i_cnt += 1
# write the end to the pci devices
print("{0}".format(PCI_END_HEADER), file=config)