diff --git a/hypervisor/arch/x86/configs/pci_dev.c b/hypervisor/arch/x86/configs/pci_dev.c index b9054e5f6..b341c6f03 100644 --- a/hypervisor/arch/x86/configs/pci_dev.c +++ b/hypervisor/arch/x86/configs/pci_dev.c @@ -9,8 +9,6 @@ #include #include -struct acrn_vm_pci_dev_config sos_pci_devs[CONFIG_MAX_PCI_DEV_NUM]; - /* * @pre pdev != NULL; */ diff --git a/hypervisor/include/arch/x86/vm_config.h b/hypervisor/include/arch/x86/vm_config.h index 912f51bb3..720030fe0 100644 --- a/hypervisor/include/arch/x86/vm_config.h +++ b/hypervisor/include/arch/x86/vm_config.h @@ -39,9 +39,7 @@ #define CONFIG_SOS_VM .load_order = SOS_VM, \ .uuid = SOS_VM_UUID, \ - .severity = SEVERITY_SOS, \ - .pci_dev_num = 0U, \ - .pci_devs = sos_pci_devs + .severity = SEVERITY_SOS #define CONFIG_SAFETY_VM(idx) .load_order = PRE_LAUNCHED_VM, \ .uuid = SAFETY_VM_UUID##idx, \ diff --git a/misc/acrn-config/scenario_config/pci_dev_c.py b/misc/acrn-config/scenario_config/pci_dev_c.py index 46a233d6b..852f49e72 100644 --- a/misc/acrn-config/scenario_config/pci_dev_c.py +++ b/misc/acrn-config/scenario_config/pci_dev_c.py @@ -3,12 +3,69 @@ # SPDX-License-Identifier: BSD-3-Clause # +import re +from collections import namedtuple + import common import scenario_cfg_lib import board_cfg_lib PCI_DEV_TYPE = ['PCI_DEV_TYPE_HVEMUL', 'PCI_DEV_TYPE_PTDEV'] + +class BusDevFunc(namedtuple( + "BusDevFunc", [ + "bus", + "dev", + "func"])): + + PATTERN = re.compile(r"(?P[0-9a-f]{2}):(?P[0-9a-f]{2})\.(?P[0-7]{1})") + + @classmethod + def from_str(cls, value): + if not(isinstance(value, str)): + raise ValueError("value must be a str: {}".format(type(value))) + + match = cls.PATTERN.fullmatch(value) + if match: + return BusDevFunc( + bus=int(match.group("bus"), 16), + dev=int(match.group("dev"), 16), + func=int(match.group("func"), 16)) + else: + raise ValueError("not a bdf: {!r}".format(value)) + + def __init__(self, *args, **kwargs): + if not (0x00 <= self.bus <= 0xff): + raise ValueError("Invalid bus number (0x00 ~ 0xff): {:#04x}".format(self.bus)) + if not (0x00 <= self.dev <= 0x1f): + raise ValueError("Invalid device number (0x00 ~ 0x1f): {:#04x}".format(self.dev)) + if not (0x0 <= self.func <= 0x7): + raise ValueError("Invalid function number (0 ~ 7): {:#x}".format(self.func)) + + def __str__(self): + return "{:02x}:{:02x}.{:x}".format(self.bus, self.dev, self.func) + + def __repr__(self): + return "BusDevFunc.from_str({!r})".format(str(self)) + + +def find_unused_bdf(used_bdf, case): + if case == "vuart": + # vuart device cannot detect function difference, find vbdf based on dev increment + for dev in range(0x20): + bdf = BusDevFunc(bus=0x00, dev=dev, func=0x0) + if bdf not in used_bdf: + return bdf + else: + for dev in range(0x20): + for func in range(0x8): + bdf = BusDevFunc(bus=0x00, dev=dev, func=func) + if bdf not in used_bdf: + return bdf + raise ValueError("Cannot find free bdf") + + def add_instance_to_name(i_cnt, bdf, bar_attr): if i_cnt == 0 and bar_attr.name.upper() == "HOST BRIDGE": tmp_sub_name = "_".join(bar_attr.name.split()).upper() @@ -31,6 +88,7 @@ def generate_file(vm_info, config): board_cfg_lib.parse_mem() compared_bdf = [] + sos_used_bdf = [] for cnt_sub_name in board_cfg_lib.SUB_NAME_COUNT.keys(): i_cnt = 0 @@ -44,7 +102,12 @@ def generate_file(vm_info, config): i_cnt += 1 - idx = 0 + for bdf in compared_bdf: + bdf_tuple = BusDevFunc.from_str(bdf) + sos_used_bdf.append(bdf_tuple) + + vuarts = common.get_vuart_info(common.SCENARIO_INFO_FILE) + print("{}".format(scenario_cfg_lib.HEADER_LICENSE), file=config) print("", file=config) print("#include ", file=config) @@ -53,101 +116,114 @@ def generate_file(vm_info, config): print("#include ", file=config) print("#include ", file=config) print("#include ", file=config) + # Insert header for share memory if vm_info.shmem.shmem_enabled == 'y': print("#include ", file=config) - for vm_i, pci_bdf_devs_list in vm_info.cfg_pci.pci_devs.items(): - if not pci_bdf_devs_list: - continue - pci_cnt = 1 - if idx == 0: - print("", file=config) - print("/*", file=config) - print(" * TODO: remove PTDEV macro and add DEV_PRIVINFO macro to initialize pbdf for", file=config) - print(" * passthrough device configuration and shm_name for ivshmem device configuration.", file=config) - print(" */", file=config) - print("#define PTDEV(PCI_DEV)\t\tPCI_DEV, PCI_DEV##_VBAR",file=config) + + # Insert comments and macros for passthrough devices + if any((p for _,p in vm_info.cfg_pci.pci_devs.items())): + print("", file=config) + print("/*", file=config) + print(" * TODO: remove PTDEV macro and add DEV_PRIVINFO macro to initialize pbdf for", file=config) + print(" * passthrough device configuration and shm_name for ivshmem device configuration.", file=config) + print(" */", file=config) + print("#define PTDEV(PCI_DEV)\t\tPCI_DEV, PCI_DEV##_VBAR",file=config) print("", file=config) print("/*", file=config) print(" * TODO: add DEV_PCICOMMON macro to initialize emu_type, vbdf and vdev_ops", file=config) print(" * to simplify the code.", file=config) print(" */", file=config) - print("struct acrn_vm_pci_dev_config " + - "vm{}_pci_devs[VM{}_CONFIG_PCI_DEV_NUM] = {{".format(vm_i, vm_i), file=config) - print("\t{", file=config) - print("\t\t.emu_type = {},".format(PCI_DEV_TYPE[0]), file=config) - print("\t\t.vbdf.bits = {.b = 0x00U, .d = 0x00U, .f = 0x00U},", file=config) - print("\t\t.vdev_ops = &vhostbridge_ops,", file=config) - print("\t},", file=config) - idx += 1 - for pci_bdf_dev in pci_bdf_devs_list: - if not pci_bdf_dev: - continue - bus = int(pci_bdf_dev.split(':')[0], 16) - dev = int(pci_bdf_dev.split(':')[1].split('.')[0], 16) - fun = int(pci_bdf_dev.split('.')[1], 16) - print("\t{", file=config) - print("\t\t.emu_type = {},".format(PCI_DEV_TYPE[1]), file=config) - print("\t\t.vbdf.bits = {{.b = 0x00U, .d = 0x{0:02d}U, .f = 0x00U}},".format(pci_cnt), file=config) - for bdf, bar_attr in board_cfg_lib.PCI_DEV_BAR_DESC.pci_dev_dic.items(): - if bdf == pci_bdf_dev: - print("\t\tPTDEV({}),".format(board_cfg_lib.PCI_DEV_BAR_DESC.pci_dev_dic[bdf].name_w_i_cnt), file=config) - else: - continue - print("\t},", file=config) - pci_cnt += 1 + for vm_i, vm_type in common.VM_TYPES.items(): + vm_used_bdf = [] + # Skip this vm if there is no any pci device and virtual device + if not scenario_cfg_lib.get_pci_dev_num_per_vm()[vm_i] and \ + scenario_cfg_lib.VM_DB[vm_type]['load_type'] != "SOS_VM": + continue + if not scenario_cfg_lib.get_pci_dev_num_per_vm()[vm_i] and \ + scenario_cfg_lib.VM_DB[vm_type]['load_type'] == "SOS_VM": + print("", file=config) + print("struct acrn_vm_pci_dev_config " + + "sos_pci_devs[CONFIG_MAX_PCI_DEV_NUM];", file=config) + continue + pci_cnt = 1 + # Insert device structure and bracket + print("", file=config) + if scenario_cfg_lib.VM_DB[vm_type]['load_type'] == "SOS_VM": + print("struct acrn_vm_pci_dev_config " + + "sos_pci_devs[CONFIG_MAX_PCI_DEV_NUM] = {", file=config) + else: + print("struct acrn_vm_pci_dev_config " + + "vm{}_pci_devs[VM{}_CONFIG_PCI_DEV_NUM] = {{".format(vm_i, vm_i), file=config) + + # Insert passtrough devices data + if vm_i in vm_info.cfg_pci.pci_devs.keys(): + pci_bdf_devs_list = vm_info.cfg_pci.pci_devs[vm_i] + if pci_bdf_devs_list: + # Insert pci hostbridge for passtrough devices: + if pci_cnt == 1: + print("\t{", file=config) + print("\t\t.emu_type = {},".format(PCI_DEV_TYPE[0]), file=config) + print("\t\t.vbdf.bits = {.b = 0x00U, .d = 0x00U, .f = 0x00U},", file=config) + print("\t\t.vdev_ops = &vhostbridge_ops,", file=config) + print("\t},", file=config) + bdf_tuple = BusDevFunc.from_str("00:00.0") + vm_used_bdf.append(bdf_tuple) + + for pci_bdf_dev in pci_bdf_devs_list: + if not pci_bdf_dev: + continue + bus = int(pci_bdf_dev.split(':')[0], 16) + dev = int(pci_bdf_dev.split(':')[1].split('.')[0], 16) + fun = int(pci_bdf_dev.split('.')[1], 16) + print("\t{", file=config) + print("\t\t.emu_type = {},".format(PCI_DEV_TYPE[1]), file=config) + print("\t\t.vbdf.bits = {{.b = 0x00U, .d = 0x{0:02d}U, .f = 0x00U}},".format(pci_cnt), file=config) + for bdf, bar_attr in board_cfg_lib.PCI_DEV_BAR_DESC.pci_dev_dic.items(): + if bdf == pci_bdf_dev: + print("\t\tPTDEV({}),".format(board_cfg_lib.PCI_DEV_BAR_DESC.pci_dev_dic[bdf].name_w_i_cnt), file=config) + else: + continue + print("\t},", file=config) + bdf_tuple = BusDevFunc(0,pci_cnt,0) + vm_used_bdf.append(bdf_tuple) + pci_cnt += 1 + + # Insert ivshmem information if vm_info.shmem.shmem_enabled == 'y' and vm_i in vm_info.shmem.shmem_regions.keys() \ - and len(vm_info.shmem.shmem_regions[vm_i]) > 0: + and len(vm_info.shmem.shmem_regions[vm_i]) > 0: raw_shm_list = vm_info.shmem.shmem_regions[vm_i] for shm in raw_shm_list: shm_splited = shm.split(',') print("\t{", file=config) print("\t\t.emu_type = {},".format(PCI_DEV_TYPE[0]), file=config) - print("\t\t.vbdf.bits = {{.b = 0x00U, .d = 0x{0:02d}U, .f = 0x00U}},".format(pci_cnt), file=config) - print("\t\t.vdev_ops = &vpci_ivshmem_ops,", file=config) + if vm_i in vm_info.cfg_pci.pci_devs.keys(): + print("\t\t.vbdf.bits = {{.b = 0x00U, .d = 0x{0:02d}U, .f = 0x00U}},".format(pci_cnt), file=config) + print("\t\t.vdev_ops = &vpci_ivshmem_ops,", file=config) + bdf_tuple = BusDevFunc(0,pci_cnt,0) + vm_used_bdf.append(bdf_tuple) + elif vm_i not in vm_info.cfg_pci.pci_devs.keys(): + if scenario_cfg_lib.VM_DB[vm_type]['load_type'] == "PRE_LAUNCHED_VM": + print("\t\t.vbdf.bits = {{.b = 0x00U, .d = 0x{0:02d}U, .f = 0x00U}},".format(pci_cnt), file=config) + bdf_tuple = BusDevFunc(0,pci_cnt,0) + vm_used_bdf.append(bdf_tuple) + else: + print("\t\t.vbdf.value = UNASSIGNED_VBDF,", file=config) + print("\t\t.vdev_ops = &vpci_ivshmem_ops,", file=config) for shm_name, bar_attr in board_cfg_lib.PCI_DEV_BAR_DESC.shm_bar_dic.items(): index = shm_name[:shm_name.find('_')] shm_name = shm_name[shm_name.find('_') + 1:] if shm_name == shm_splited[0].strip(): - print("\t\t.shm_region_name = IVSHMEM_SHM_REGION_{},".format(index), file=config) - print("\t\tIVSHMEM_DEVICE_{}_VBAR".format(index), file=config) - # print("\t\t.vbar_size[0] = 0x100,", file=config) - # print("\t\t.vbar_size[2] = {},".format(shm_splited[1].strip()), file=config) - # print('\t\t.shm_name = "{}",'.format(shm_splited[0].strip()), file=config) - print("\t},", file=config) + if scenario_cfg_lib.VM_DB[vm_type]['load_type'] == "PRE_LAUNCHED_VM": + print("\t\t.shm_region_name = IVSHMEM_SHM_REGION_{},".format(index), file=config) + print("\t\tIVSHMEM_DEVICE_{}_VBAR".format(index), file=config) + break + else: + print("\t\t.shm_region_name = IVSHMEM_SHM_REGION_{}".format(index), file=config) + break pci_cnt += 1 + print("\t},", file=config) - print("};", file=config) - - if vm_info.shmem.shmem_enabled == 'y': - for shm_i, raw_shm_list in vm_info.shmem.shmem_regions.items(): - shm_cnt = 0 - if shm_i not in vm_info.cfg_pci.pci_devs.keys() and len(raw_shm_list) > 0: - print("", file=config) - print("struct acrn_vm_pci_dev_config " + - "vm{}_pci_devs[VM{}_CONFIG_PCI_DEV_NUM] = {{".format(shm_i, shm_i), file=config) - for shm in raw_shm_list: - shm_splited = shm.split(',') - print("\t{", file=config) - print("\t\t.emu_type = {},".format(PCI_DEV_TYPE[0]), file=config) - if shm_i in common.VM_TYPES.keys() and common.VM_TYPES[shm_i] in ['PRE_RT_VM', 'PRE_STD_VM', 'SAFETY_VM']: - print("\t\t.vbdf.bits = {{.b = 0x00U, .d = 0x{0:02d}U, .f = 0x00U}},".format(shm_cnt), file=config) - else: - print("\t\t.vbdf.value = UNASSIGNED_VBDF,".format(shm_cnt), file=config) - print("\t\t.vdev_ops = &vpci_ivshmem_ops,", file=config) - for shm_name, bar_attr in board_cfg_lib.PCI_DEV_BAR_DESC.shm_bar_dic.items(): - index = shm_name[:shm_name.find('_')] - shm_name = shm_name[shm_name.find('_')+1:] - if shm_name == shm_splited[0].strip(): - if shm_i in common.VM_TYPES.keys() and common.VM_TYPES[shm_i] in ['PRE_RT_VM', 'PRE_STD_VM', - 'SAFETY_VM']: - print("\t\t.shm_region_name = IVSHMEM_SHM_REGION_{},".format(index), file=config) - print("\t\tIVSHMEM_DEVICE_{}_VBAR".format(index), file=config) - break - else: - print("\t\t.shm_region_name = IVSHMEM_SHM_REGION_{}".format(index), file=config) - break - shm_cnt += 1 - print("\t},", file=config) - print("};", file=config) \ No newline at end of file + # Insert the end bracket of the pci_dev.c file + print("};", file=config) \ No newline at end of file diff --git a/misc/acrn-config/scenario_config/vm_configurations_c.py b/misc/acrn-config/scenario_config/vm_configurations_c.py index e3ce33c66..c58a32ca9 100644 --- a/misc/acrn-config/scenario_config/vm_configurations_c.py +++ b/misc/acrn-config/scenario_config/vm_configurations_c.py @@ -267,6 +267,9 @@ def gen_sos_vm(vm_type, vm_i, scenario_items, config): err_dic = vuart_output(vm_type, vm_i, vm_info, config) if err_dic: return err_dic + sos_dev_num = scenario_cfg_lib.get_pci_dev_num_per_vm()[vm_i] + print("\t\t.pci_dev_num = {}U,".format(sos_dev_num), file=config) + print("\t\t.pci_devs = sos_pci_devs,", file=config) print("\t},", file=config) @@ -321,9 +324,7 @@ def gen_pre_launch_vm(vm_type, vm_i, scenario_items, config): if err_dic: return err_dic - if (vm_i in vm_info.cfg_pci.pci_devs.keys() and vm_info.cfg_pci.pci_devs[vm_i]) or \ - (vm_info.shmem.shmem_enabled == 'y' and vm_i in vm_info.shmem.shmem_regions.keys() \ - and vm_info.shmem.shmem_regions[vm_i]): + if scenario_cfg_lib.get_pci_dev_num_per_vm()[vm_i]: print("\t\t.pci_dev_num = VM{}_CONFIG_PCI_DEV_NUM,".format(vm_i), file=config) print("\t\t.pci_devs = vm{}_pci_devs,".format(vm_i), file=config) @@ -361,8 +362,7 @@ def gen_post_launch_vm(vm_type, vm_i, scenario_items, config): print("\t{{\t/* VM{} */".format(vm_i), file=config) print("\t\t{},".format(post_vm_type), file=config) clos_output(scenario_items, vm_i, config) - if vm_info.shmem.shmem_enabled == 'y' and vm_i in vm_info.shmem.shmem_regions.keys() \ - and vm_info.shmem.shmem_regions[vm_i]: + if scenario_cfg_lib.get_pci_dev_num_per_vm()[vm_i]: print("\t\t/* The PCI device configuration is only for in-hypervisor vPCI devices. */", file=config) print("\t\t.pci_dev_num = VM{}_CONFIG_PCI_DEV_NUM,".format(vm_i), file=config) print("\t\t.pci_devs = vm{}_pci_devs,".format(vm_i), file=config) @@ -375,15 +375,14 @@ def gen_post_launch_vm(vm_type, vm_i, scenario_items, config): print("\t},", file=config) - def declare_pci_devs(vm_info, config): for vm_i,vm_type in common.VM_TYPES.items(): - if scenario_cfg_lib.VM_DB[vm_type]['load_type'] not in ["PRE_LAUNCHED_VM", "POST_LAUNCHED_VM"]: + if vm_type == "SOS_VM": + print("extern struct acrn_vm_pci_dev_config " + + "sos_pci_devs[CONFIG_MAX_PCI_DEV_NUM];", file=config) continue - if (vm_i in vm_info.cfg_pci.pci_devs.keys() and vm_info.cfg_pci.pci_devs[vm_i]) \ - or (vm_info.shmem.shmem_enabled == 'y' and vm_i in vm_info.shmem.shmem_regions.keys() \ - and vm_info.shmem.shmem_regions[vm_i]): + if scenario_cfg_lib.get_pci_dev_num_per_vm()[vm_i]: print("extern struct acrn_vm_pci_dev_config " + "vm{}_pci_devs[VM{}_CONFIG_PCI_DEV_NUM];".format(vm_i, vm_i), file=config) print("", file=config)