mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2026-06-08 10:04:42 +00:00
Devices that support SR-IOV can expose their capabilities in lspci -vv command as below. The offline tool, instead of picking up the bios exposed memory region(bc000000) for the devices ends picking up the SR-IOV memory region(00000000c0000000) and generates VBAR address (in pci_devices.h). This is incorrect. This patch fixes the offline tool to take the right memory region as the VBAR address. Sample lspic -vv log: 67:00.0 Ethernet controller: Intel Corporation Ethernet Connection X722 for 10GbE backplane (rev 09) Subsystem: Intel Corporation Device 0000 Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- Latency: 0 Interrupt: pin A routed to IRQ 61 Region 0: Memory at bc000000 (64-bit, prefetchable) [size=16M] Region 3: Memory at c1000000 (64-bit, prefetchable) [size=32K] Capabilities: [160 v1] Single Root I/O Virtualization (SR-IOV) IOVCap: Migration-, Interrupt Message Number: 000 IOVCtl: Enable- Migration- Interrupt- MSE- ARIHierarchy+ IOVSta: Migration- Initial VFs: 32, Total VFs: 32, Number of VFs: 0, Function Dependency Link: 00 VF offset: 16, stride: 1, Device ID: 37cd Supported Page Size: 00000553, System Page Size: 00000001 Region 0: Memory at 00000000c0000000 (64-bit, prefetchable) Region 3: Memory at 00000000c1020000 (64-bit, prefetchable) VF Migration: offset: 00000000, BIR: 0 Tracked-On: #4443 Signed-off-by: Vijay Dhanraj <vijay.dhanraj@intel.com> Acked-by: Victor Sun <victor.sun@intel.com>
177 lines
5.4 KiB
Python
177 lines
5.4 KiB
Python
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
|
#
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
#
|
|
|
|
import collections
|
|
import board_cfg_lib
|
|
|
|
PCI_HEADER = r"""
|
|
#ifndef PCI_DEVICES_H_
|
|
#define PCI_DEVICES_H_
|
|
"""
|
|
PCI_END_HEADER = r"""
|
|
#endif /* PCI_DEVICES_H_ */"""
|
|
|
|
|
|
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 parser_pci():
|
|
""" Parse PCI lines """
|
|
cur_bdf = 0
|
|
prev_bdf = 0
|
|
tmp_bar_dic = {}
|
|
pci_dev_dic = {}
|
|
pci_bar_dic = {}
|
|
above_4G_mmio = False
|
|
bar_addr = bar_num = '0'
|
|
|
|
pci_lines = board_cfg_lib.get_info(
|
|
board_cfg_lib.BOARD_INFO_FILE, "<PCI_DEVICE>", "</PCI_DEVICE>")
|
|
for line in pci_lines:
|
|
# get pci bar information into pci_bar_dic
|
|
if "Region" in line and "Memory at" in line:
|
|
#ignore memory region from SR-IOV capabilities
|
|
if "size=" not in line:
|
|
continue
|
|
bar_num = line.split()[1].strip(':')
|
|
bar_addr = get_value_after_str(line, "at")
|
|
if int(bar_addr, 16) > 0xffffffff:
|
|
above_4G_mmio = True
|
|
tmp_bar_dic[int(bar_num)] = hex(int(bar_addr, 16))
|
|
else:
|
|
prev_bdf = cur_bdf
|
|
pci_bdf = line.split()[0]
|
|
pci_sub_name = " ".join(line.split(':')[1].split()[1:])
|
|
|
|
# remove '[*]' in pci subname
|
|
if '[' in pci_sub_name:
|
|
pci_sub_name = pci_sub_name.rsplit('[', 1)[0]
|
|
|
|
pci_dev_dic[pci_bdf] = pci_sub_name
|
|
cur_bdf = pci_bdf
|
|
|
|
if not prev_bdf:
|
|
prev_bdf = cur_bdf
|
|
|
|
if tmp_bar_dic and cur_bdf != prev_bdf:
|
|
pci_bar_dic[prev_bdf] = tmp_bar_dic
|
|
|
|
# clear the tmp_bar_dic before store the next dic
|
|
tmp_bar_dic = {}
|
|
|
|
if above_4G_mmio:
|
|
board_cfg_lib.print_yel("Currently ACRN does not support BAR size above 4G, please double check below possible items in BIOS:\n\
|
|
1. GPU Aperture size is less than 1GB;\n\
|
|
2. the device MMIO mapping region is below 4GB", warn=True)
|
|
|
|
# output all the pci device list to pci_device.h
|
|
sub_name_count = collections.Counter(pci_dev_dic.values())
|
|
|
|
if tmp_bar_dic:
|
|
pci_bar_dic[cur_bdf] = tmp_bar_dic
|
|
|
|
return (pci_dev_dic, pci_bar_dic, sub_name_count)
|
|
|
|
|
|
def write_pbdf(i_cnt, bdf, subname, config):
|
|
"""
|
|
Parser and generate pbdf
|
|
:param i_cnt: the number of pci devices have the same PCI subname
|
|
:param bdf: it is a string what contains BDF
|
|
:param subname: it is a string belong to PIC subname
|
|
: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 subname.upper() == "HOST BRIDGE":
|
|
tmp_sub_name = "_".join(subname.split()).upper()
|
|
else:
|
|
if '-' in subname:
|
|
tmp_sub_name = board_cfg_lib.undline_name(subname) + "_" + str(i_cnt)
|
|
else:
|
|
tmp_sub_name = "_".join(subname.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)
|
|
|
|
|
|
def write_vbar(bdf, pci_bar_dic, config):
|
|
"""
|
|
Parser and generate vbar
|
|
:param bdf: it is a string what contains BDF
|
|
:param pci_bar_dic: it is a dictionary of pci vbar for those BDF
|
|
:param config: it is a file pointer of pci information for writing to
|
|
"""
|
|
tail = 0
|
|
align = ' ' * 48
|
|
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 tail == 0:
|
|
print(", \\", file=config)
|
|
tail += 1
|
|
bar_num += 1
|
|
bar_val = pci_bar_dic[bdf][bar_i]
|
|
|
|
if bar_num == bar_len:
|
|
print("{}.vbar_base[{}] = {}UL".format(align, bar_i, bar_val), file=config)
|
|
else:
|
|
print("{}.vbar_base[{}] = {}UL, \\".format(
|
|
align, bar_i, bar_val), file=config)
|
|
|
|
# print("", 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)
|
|
|
|
(pci_dev_dic, pci_bar_dic, sub_name_count) = parser_pci()
|
|
|
|
|
|
compared_bdf = []
|
|
for cnt_sub_name in sub_name_count.keys():
|
|
i_cnt = 0
|
|
for bdf, subname in pci_dev_dic.items():
|
|
if cnt_sub_name == subname and bdf not in compared_bdf:
|
|
compared_bdf.append(bdf)
|
|
else:
|
|
continue
|
|
|
|
write_pbdf(i_cnt, bdf, subname, config)
|
|
write_vbar(bdf, pci_bar_dic, config)
|
|
|
|
i_cnt += 1
|
|
|
|
# write the end to the pci devices
|
|
print("{0}".format(PCI_END_HEADER), file=config)
|