diff --git a/misc/acrn-config/library/common.py b/misc/acrn-config/library/common.py index a03da3092..f3c79ecbe 100644 --- a/misc/acrn-config/library/common.py +++ b/misc/acrn-config/library/common.py @@ -36,6 +36,8 @@ LAUNCH_INFO_FILE = "" VM_TYPES = {} MAX_VM_NUM = 8 +MAX_VUART_NUM = 8 + class MultiItem(): def __init__(self): diff --git a/misc/acrn-config/library/scenario_cfg_lib.py b/misc/acrn-config/library/scenario_cfg_lib.py index 07f00b6cc..fbbe2a5f6 100644 --- a/misc/acrn-config/library/scenario_cfg_lib.py +++ b/misc/acrn-config/library/scenario_cfg_lib.py @@ -17,11 +17,15 @@ KERN_TYPE_LIST = ['KERNEL_BZIMAGE', 'KERNEL_ZEPHYR'] KERN_BOOT_ADDR_LIST = ['0x100000'] VUART_TYPE = ['VUART_LEGACY_PIO', 'VUART_PCI'] +INVALID_COM_BASE = 'INVALID_COM_BASE' VUART_BASE = ['SOS_COM1_BASE', 'SOS_COM2_BASE', 'COM1_BASE', - 'COM2_BASE', 'COM3_BASE', 'COM4_BASE', 'INVALID_COM_BASE'] + 'COM2_BASE', 'COM3_BASE', 'COM4_BASE', INVALID_COM_BASE] +INVALID_PCI_BASE = 'INVALID_PCI_BASE' +PCI_VUART = 'PCI_VUART' +PCI_VUART_BASE = [PCI_VUART, INVALID_PCI_BASE] -AVALIBLE_COM1_BASE = ['INVALID_COM_BASE', 'COM1_BASE'] -AVALIBLE_COM2_BASE = ['INVALID_COM_BASE', 'COM2_BASE'] +AVALIBLE_COM1_BASE = [INVALID_COM_BASE, 'COM1_BASE'] +AVALIBLE_COM2_BASE = [INVALID_COM_BASE, 'COM2_BASE'] VUART_IRQ = ['SOS_COM1_IRQ', 'SOS_COM2_IRQ', 'COM1_IRQ', 'COM2_IRQ', 'COM3_IRQ', 'COM4_IRQ', 'CONFIG_COM_IRQ', '3', '4', '6', '7'] @@ -64,6 +68,11 @@ VM_DB = { } LOAD_VM_TYPE = list(VM_DB.keys()) +# field names +F_TARGET_VM_ID = 'target_vm_id' +F_TARGET_UART_ID = 'target_uart_id' + + def get_pci_devs(pci_items): pci_devs = {} @@ -654,14 +663,14 @@ def avl_vuart_ui_select(scenario_info): for vm_i,vm_type in common.VM_TYPES.items(): if "SOS_VM" == VM_DB[vm_type]['load_type']: - key = "vm={},vuart=0,base".format(vm_i) + key = "vm={},legacy_vuart=0,base".format(vm_i) tmp_vuart[key] = ['SOS_COM1_BASE', 'INVALID_COM_BASE'] - key = "vm={},vuart=1,base".format(vm_i) + key = "vm={},legacy_vuart=1,base".format(vm_i) tmp_vuart[key] = ['SOS_COM2_BASE', 'INVALID_COM_BASE'] else: - key = "vm={},vuart=0,base".format(vm_i) + key = "vm={},legacy_vuart=0,base".format(vm_i) tmp_vuart[key] = ['INVALID_COM_BASE', 'COM1_BASE'] - key = "vm={},vuart=1,base".format(vm_i) + key = "vm={},legacy_vuart=1,base".format(vm_i) tmp_vuart[key] = ['INVALID_COM_BASE', 'COM2_BASE'] return tmp_vuart @@ -700,23 +709,23 @@ def check_vuart(v0_vuart, v1_vuart): for vm_i,vuart_dic in v1_vuart.items(): # check target vm id if 'base' not in vuart_dic.keys(): - key = "vm:id={},vuart:id=1,base".format(vm_i) + key = "vm:id={},legacy_vuart:id=1,base".format(vm_i) ERR_LIST[key] = "base should be in xml" return if not vuart_dic['base'] or vuart_dic['base'] not in VUART_BASE: - key = "vm:id={},vuart:id=1,base".format(vm_i) + key = "vm:id={},legacy_vuart:id=1,base".format(vm_i) ERR_LIST[key] = "base should be SOS/COM BASE" if vuart_dic['base'] == "INVALID_COM_BASE": continue if 'target_vm_id' not in vuart_dic.keys(): - key = "vm:id={},vuart:id=1,target_vm_id".format(vm_i) + key = "vm:id={},legacy_vuart:id=1,target_vm_id".format(vm_i) ERR_LIST[key] = "target_vm_id should be in xml" if not vuart_dic['target_vm_id'] or not vuart_dic['target_vm_id'].isnumeric(): - key = "vm:id={},vuart:id=1,target_vm_id".format(vm_i) + key = "vm:id={},legacy_vuart:id=1,target_vm_id".format(vm_i) ERR_LIST[key] = "target_vm_id should be numeric of vm id" vm_target_id_dic[vm_i] = vuart_dic['target_vm_id'] @@ -725,7 +734,7 @@ def check_vuart(v0_vuart, v1_vuart): i = 0 for vm_i,t_vm_id in vm_target_id_dic.items(): if t_vm_id.isnumeric() and int(t_vm_id) not in common.VM_TYPES.keys(): - key = "vm:id={},vuart:id=1,target_vm_id".format(vm_i) + key = "vm:id={},legacy_vuart:id=1,target_vm_id".format(vm_i) ERR_LIST[key] = "target_vm_id which specified does not exist" idx = target_id_keys.index(vm_i) @@ -736,10 +745,311 @@ def check_vuart(v0_vuart, v1_vuart): connect_set = True if not connect_set and len(target_id_keys) >= 2: - key = "vm:id={},vuart:id=1,target_vm_id".format(i) + key = "vm:id={},legacy_vuart:id=1,target_vm_id".format(i) ERR_LIST[key] = "Creating the wrong configuration for target_vm_id." +def get_legacy_vuart1_target_dict(legacy_vuart1): + vuart1_target_dict = {} + vuart1_visited = {} + for vm_i, vuart_dict in legacy_vuart1.items(): + vuart_base = vuart_dict.get('base') + if vuart_base not in VUART_BASE: + continue + if vuart_base == INVALID_COM_BASE: + continue + + try: + key = "vm:id={},legacy_vuart:id=1,target_vm_id".format(vm_i) + target_vm_id = get_target_vm_id(vuart_dict, vm_i) + err_key = "vm:id={},legacy_vuart:id=1,target_uart_id".format(vm_i) + target_uart_id = get_target_uart_id(vuart_dict) + except XmlError as exc: + ERR_LIST[err_key] = str(exc) + return vuart1_target_dict, vuart1_visited + + if vm_i not in vuart1_target_dict: + vuart1_target_dict[vm_i] = (target_vm_id, target_uart_id) + else: + raise ValueError('vm id {} has more than one legacy vuart 1'.format(vm_i)) + + if vm_i not in vuart1_visited: + vuart1_visited[vm_i] = -1 + else: + raise ValueError('vm id {} has more than one legacy vuart 1'.format(vm_i)) + + return vuart1_target_dict, vuart1_visited + + +class InvalidError(Exception): + pass + +class LegacyVuartError(Exception): + pass + +class PciVuartError(Exception): + pass + +class TargetError(Exception): + pass +class XmlError(Exception): + pass + +def check_vuart_id(vuart_id): + if not isinstance(vuart_id, int): + raise ValueError('vuart_id must be int: {}, {!r}'.format(type(vuart_id), vuart_id)) + + +def check_vuart_id_count(vm_pci_vuarts, legacy_vuart0, legacy_vuart1): + vuart_cnt = 0 + for vuart_id in vm_pci_vuarts: + pci_vuart_base = vm_pci_vuarts.get(vuart_id, {}).get('base') + if pci_vuart_base == PCI_VUART: + vuart_cnt += 1 + + legacy_vuart_base0 = legacy_vuart0.get('base') + if legacy_vuart_base0 != INVALID_COM_BASE: + vuart_cnt += 1 + + legacy_vuart_base1 = legacy_vuart1.get('base') + if legacy_vuart_base1 != INVALID_COM_BASE: + vuart_cnt += 1 + + if vuart_cnt > common.MAX_VUART_NUM: + raise XmlError("enables more than {} vuarts, total number: {}".format(common.MAX_VUART_NUM, vuart_cnt)) + + +def check_against_coexistence(vm_pci_vuarts, vm_legacy_vuart, legacy_vuart_idx): + pci_vuart_base = vm_pci_vuarts.get(legacy_vuart_idx, {}).get('base') + legacy_base = vm_legacy_vuart.get('base') + if legacy_base not in VUART_BASE: + raise LegacyVuartError('legacy vuart base should be one of {}'.format(", ".join(VUART_BASE))) + if legacy_base == INVALID_COM_BASE: + return + if pci_vuart_base not in PCI_VUART_BASE: + raise PciVuartError('pci vuart base should be one of {}, last call: {!r}'.format(", ".join(PCI_VUART_BASE), pci_vuart_base)) + if pci_vuart_base == INVALID_PCI_BASE: + return + raise PciVuartError('cannot enable legacy vuart {} and this vuart {} at the same time' \ + .format(legacy_vuart_idx, legacy_vuart_idx)) + + +def check_pci_vuart_base(pci_vuart): + if not isinstance(pci_vuart, dict): + raise TypeError('pci_vuart should be a dict: {}, {!r}'.format(type(pci_vuart), pci_vuart)) + if 'base' not in pci_vuart: + raise ValueError('base should be in vuart: keys_found={}'.format(pci_vuart.keys())) + + pci_vuart_base_str = pci_vuart['base'] + if pci_vuart_base_str not in PCI_VUART_BASE: + raise ValueError("base should be one of {}, last called: {!r}".format(", ".join(PCI_VUART_BASE), pci_vuart_base_str)) + if pci_vuart_base_str == INVALID_PCI_BASE: + raise InvalidError + + +def get_target_vm_id(vuart, vm_id): + if not isinstance(vuart, dict): + raise TypeError('vuart should be a dict: {}, {!r}'.format(type(vuart), vuart)) + if not isinstance(vm_id, int): + raise TypeError('vm_id should be an int: {}, {!r}'.format(type(vm_id), vm_id)) + if F_TARGET_VM_ID not in vuart: + raise ValueError('target_vm_id should be in vuart: keys_found={}'.format(vuart.keys())) + + try: + target_vm_id_str = vuart.get(F_TARGET_VM_ID) + target_vm_id = int(target_vm_id_str) + except (TypeError, ValueError): + raise XmlError( + "target_vm_id should be present and numeric: {!r}".format( + target_vm_id_str)) + + if target_vm_id not in common.VM_TYPES: + raise XmlError( + 'invalid target_vm_id: target_vm_id={!r}, vm_ids={}'.format( + target_vm_id, common.VM_TYPES.keys())) + + if target_vm_id == vm_id: + raise XmlError( + "cannot connect to itself, target_vm_id: {}".format(vm_id)) + return target_vm_id + + +def get_target_uart_id(vuart): + if not isinstance(vuart, dict): + raise TypeError('vuart should be a dict: {}, {!r}'.format(type(vuart), vuart)) + if F_TARGET_UART_ID not in vuart: + raise ValueError('target_uart_id should be in vuart: keys_found={}'.format(vuart.keys())) + + try: + target_uart_id_str = vuart.get(F_TARGET_UART_ID) + target_uart_id = int(target_uart_id_str) + except (TypeError, ValueError): + raise XmlError( + "target_uart_id_str should be present and numeric: {!r}".format( + target_uart_id_str)) + if target_uart_id == 0: + raise XmlError("cannot connect to any type of vuart 0") + return target_uart_id + + +def check_pci_vuart(pci_vuarts, legacy_vuart0, legacy_vuart1): + + vm_target_dict = {} + vm_visited = {} + + for vm_id, vm_pci_vuarts in pci_vuarts.items(): + + try: + vuart_id = 0 + check_against_coexistence(vm_pci_vuarts, legacy_vuart0.get(vm_id), vuart_id) + vuart_id = 1 + check_against_coexistence(vm_pci_vuarts, legacy_vuart1.get(vm_id), vuart_id) + key = "vm:id={}".format(vm_id) + check_vuart_id_count(vm_pci_vuarts, legacy_vuart0.get(vm_id), legacy_vuart1.get(vm_id)) + except XmlError as exc: + ERR_LIST[key] = str(exc) + return + except LegacyVuartError as exc: + key = "vm:id={},legacy_vuart:id={},base".format(vm_id, vuart_id) + ERR_LIST[key] = str(exc) + return + except PciVuartError as exc: + err_key = ( + "vm:id={},console_vuart:id={},base".format(vm_id, vuart_id) + if vuart_id == 0 + else "vm:id={},communication_vuart:id={},base".format(vm_id, vuart_id) + ) + ERR_LIST[err_key] = str(exc) + return + + for vuart_id, pci_vuart in vm_pci_vuarts.items(): + + check_vuart_id(vuart_id) + + err_key = ( + "vm:id={},console_vuart:id={},base".format(vm_id, vuart_id) + if vuart_id == 0 + else "vm:id={},communication_vuart:id={},base".format(vm_id, vuart_id) + ) + key = err_key + + try: + check_pci_vuart_base(pci_vuart) + except ValueError as exc: + ERR_LIST[err_key] = str(exc) + return + except InvalidError: + continue + + if vuart_id == 0: + continue + + try: + err_key = "vm:id={},communication_vuart:id={},target_vm_id".format(vm_id, vuart_id) + target_vm_id = get_target_vm_id(pci_vuart, vm_id) + err_key = "vm:id={},communication_vuart:id={},target_uart_id".format(vm_id, vuart_id) + target_uart_id = get_target_uart_id(pci_vuart) + except XmlError as exc: + ERR_LIST[err_key] = str(exc) + return + + if vm_id not in vm_target_dict: + vm_target_dict[vm_id] = {} + if vuart_id in vm_target_dict[vm_id]: + raise ValueError('Duplicated vm id {} and vuart id {}'.format(vm_id, vuart_id)) + else: + vm_target_dict[vm_id][vuart_id] = (target_vm_id, target_uart_id) + + if vm_id not in vm_visited: + vm_visited[vm_id] = {} + if vuart_id in vm_visited[vm_id]: + raise ValueError('vuart {} of vm {} is duplicated'.format(vuart_id, vm_id)) + else: + vm_visited[vm_id][vuart_id] = -1 + + + legacy_vuart1_target_dict, legacy_vuart1_visited = get_legacy_vuart1_target_dict(legacy_vuart1) + + for vm_id, target in legacy_vuart1_target_dict.items(): + try: + err_key = "vm:id={},legacy_vuart:id=1,target_vm_id".format(vm_id) + target_vm_id = int(target[0]) + is_target_vm_available(target_vm_id, vm_visited, legacy_vuart1_visited) + err_key = "vm:id={},legacy_vuart:id=1,target_uart_id".format(vm_id) + target_uart_id = int(target[1]) + check_target_connection(vm_id, target_vm_id, target_uart_id, vm_visited, legacy_vuart1_visited) + except TargetError as exc: + ERR_LIST[err_key] = str(exc) + continue + + for vm_id, target_list in vm_target_dict.items(): + for vuart_id, target in target_list.items(): + try: + err_key = "vm:id={},communication_vuart:id={},target_vm_id".format(vm_id, vuart_id) + target_vm_id = int(target[0]) + is_target_vm_available(target_vm_id, vm_visited, legacy_vuart1_visited) + err_key = "vm:id={},communication_vuart:id={},target_uart_id".format(vm_id, vuart_id) + target_uart_id = int(target[1]) + check_target_connection(vm_id, target_vm_id, target_uart_id, vm_visited, legacy_vuart1_visited) + except TargetError as exc: + ERR_LIST[err_key] = str(exc) + continue + + +def is_target_vm_available(target_vm_id, vm_visited, legacy_vuart1_visited): + if not isinstance(target_vm_id, int): + raise TypeError('target_vm_id should be an int: {}, {!r}'.format(type(target_vm_id), target_vm_id)) + if not isinstance(vm_visited, dict): + raise TypeError('vm_visited should be a dict: {}, {!r}'.format(type(vm_visited), vm_visited)) + if not isinstance(legacy_vuart1_visited, dict): + raise TypeError('legacy_vuart1_visited should be a dict: {}, {!r}' \ + .format(type(legacy_vuart1_visited), legacy_vuart1_visited)) + + if target_vm_id not in common.VM_TYPES: + raise TargetError("target vm {} is not present".format(target_vm_id)) + if target_vm_id in vm_visited: + pass + elif target_vm_id in legacy_vuart1_visited: + pass + else: + raise TargetError("target vm {} disables legacy vuart 1 and all communication vuarts"\ + .format(target_vm_id)) + + +def check_target_connection(vm_id, target_vm_id, target_uart_id, vm_visited, legacy_vuart1_visited): + if not isinstance(vm_visited, dict): + raise TypeError('vm_visited should be a dict: {}, {!r}'.format(type(vm_visited), vm_visited)) + if not isinstance(legacy_vuart1_visited, dict): + raise TypeError('legacy_vuart1_visited should be a dict: {}, {!r}' \ + .format(type(legacy_vuart1_visited), legacy_vuart1_visited)) + if not isinstance(target_vm_id, int): + raise TypeError('vm_id should be an int: {}, {!r}'.format(type(vm_id), vm_id)) + if not isinstance(target_vm_id, int): + raise TypeError('target_vm_id should be an int: {}, {!r}'.format(type(target_vm_id), target_vm_id)) + if not isinstance(target_uart_id, int): + raise TypeError('target_uart_id should be an int: {}, {!r}'.format(type(target_uart_id), target_uart_id)) + + if target_uart_id == 0: + raise TargetError("cannot connect to any type of vuart 0") + + if vm_visited.get(target_vm_id) and target_uart_id in vm_visited[target_vm_id]: + connected_vm = vm_visited[target_vm_id][target_uart_id] + if connected_vm > -1: + raise TargetError("target vm{} : vuart{} is connected to vm {}" \ + .format(target_vm_id, target_uart_id, connected_vm)) + else: + vm_visited[target_vm_id][target_uart_id] = vm_id + elif target_uart_id == 1 and target_vm_id in legacy_vuart1_visited: + connected_vm = legacy_vuart1_visited[target_vm_id] + if connected_vm > -1: + raise TargetError("target vm{} : vuart{} is connected to vm {}" \ + .format(target_vm_id, target_uart_id, connected_vm)) + else: + legacy_vuart1_visited[target_vm_id] = vm_id + else: + raise TargetError("target vm{}'s vuart{} is not present".format(target_vm_id ,target_uart_id)) + + def vcpu_clos_check(cpus_per_vm, clos_per_vm, prime_item, item): if not board_cfg_lib.is_rdt_enabled(): diff --git a/misc/acrn-config/scenario_config/scenario_item.py b/misc/acrn-config/scenario_config/scenario_item.py index a0846c4ec..7b16da185 100644 --- a/misc/acrn-config/scenario_config/scenario_item.py +++ b/misc/acrn-config/scenario_config/scenario_item.py @@ -117,6 +117,7 @@ class VuartInfo: """ This is Abstract of class of vm vuart setting """ v0_vuart = {} v1_vuart = {} + pci_vuarts = {} def __init__(self, scenario_file): self.scenario_info = scenario_file @@ -132,6 +133,7 @@ class VuartInfo: """ self.v0_vuart = common.get_vuart_info_id(self.scenario_info, 0) self.v1_vuart = common.get_vuart_info_id(self.scenario_info, 1) + self.pci_vuarts = common.get_vuart_info(self.scenario_info) def check_item(self): """ @@ -140,6 +142,7 @@ class VuartInfo: """ scenario_cfg_lib.check_board_private_info() scenario_cfg_lib.check_vuart(self.v0_vuart, self.v1_vuart) + scenario_cfg_lib.check_pci_vuart(self.pci_vuarts, self.v0_vuart, self.v1_vuart) class MemInfo: """ This is Abstract of class of memory setting information """