1# Copyright (C) 2020-2022 Intel Corporation. 2# 3# SPDX-License-Identifier: BSD-3-Clause 4# 5 6import os 7import sys 8import acrn_config_utilities 9import getopt 10import board_cfg_lib 11 12 13ERR_LIST = {} 14N_Y = ['n', 'y'] 15SCHEDULER_TYPE = ['SCHED_NOOP', 'SCHED_IORR', 'SCHED_BVT', 'SCHED_PRIO'] 16 17RANGE_DB = { 18 'LOG_LEVEL':{'min':0,'max':5}, 19 'EMULATED_MMIO_REGIONS':{'min':0,'max':128}, 20 'PT_IRQ_ENTRIES':{'min':0,'max':256}, 21 'IOAPIC_NUM':{'min':1,'max':10}, 22 'IOAPIC_LINES':{'min':1,'max':120}, 23 'PCI_DEV_NUM':{'min':1,'max':1024}, 24 'MSIX_TABLE_NUM':{'min':1,'max':2048}, 25} 26 27 28def empty_check(val, prime_item, item, sub_item=''): 29 if not val or val == None: 30 if sub_item: 31 key = 'hv,{},{},{}'.format(prime_item, item, sub_item) 32 ERR_LIST[key] = "{} should not be empty".format(sub_item) 33 else: 34 key = 'hv,{},{}'.format(prime_item, item) 35 ERR_LIST[key] = "{} should not be empty".format(item) 36 return True 37 38 return False 39 40 41def is_numeric_check(str_value, prime_item, item): 42 43 # to skip for strip 0x/0X 44 if str_value == '0': 45 return True 46 str_hex_0x = str_value.lstrip('0x') 47 str_hex_0X = str_value.lstrip('0X') 48 49 if not str_hex_0x.isnumeric() and not str_hex_0X.isnumeric(): 50 if not isinstance(int(str_hex_0x, 16), int) and not isinstance(int(str_hex_0X, 16), int): 51 key = 'hv,{},{}'.format(prime_item, item) 52 ERR_LIST[key] = "{} should be a numeric".format(item) 53 return False 54 return True 55 56 57def range_check(str_value, prime_item, item, range_val): 58 59 value = acrn_config_utilities.num2int(str_value) 60 if value < range_val['min'] or value > range_val['max']: 61 key = 'hv,{},{}'.format(prime_item, item) 62 ERR_LIST[key] = "{} should be in range[{},{}]".format(item, range_val['min'], range_val['max']) 63 64 65def release_check(sel_str, dbg_opt, rel_str): 66 if empty_check(sel_str, dbg_opt, rel_str): 67 return 68 if sel_str not in N_Y: 69 key = 'hv,{},{}'.format(dbg_opt, rel_str) 70 ERR_LIST[key] = "{} should be in {}".format(rel_str, N_Y) 71 72 73def hv_range_check(str_val, branch_tag, item, range_db, empty_check_enable=True): 74 75 if empty_check_enable: 76 if empty_check(str_val, branch_tag, item): 77 return 78 if not is_numeric_check(str_val, branch_tag, item): 79 return 80 range_check(str_val, branch_tag, item, range_db) 81 82 83def hv_size_check(str_val, branch_tag, item): 84 85 if empty_check(str_val, branch_tag, item): 86 return 87 if not is_numeric_check(str_val, branch_tag, item): 88 return 89 90def hv_ram_start_check(hv_ram_start, prime_item, item): 91 92 err_dic = {} 93 if '0x' not in hv_ram_start and '0X' not in hv_ram_start: 94 key = "hv,{},{}".format(prime_item, item) 95 ERR_LIST[key] = "Address should be Hex format" 96 97 to_mb = (int(hv_ram_start, 16) / (1024 * 1024)) 98 is_aligned = to_mb % 2 99 if to_mb < 2 or is_aligned != 0: 100 key = "hv,{},{}".format(prime_item, item) 101 ERR_LIST[key] = "Address should be larger than or equal to 2MB and 2MB-aligned." 102 103def ir_entries_check(str_num, cap, cap_ir_entries): 104 hv_size_check(str_num, cap, cap_ir_entries) 105 val = acrn_config_utilities.num2int(str_num) 106 if val % 2 != 0: 107 key = 'hv,{},{}'.format(cap, cap_ir_entries) 108 ERR_LIST[key] = "{} should be a value of 2^n".format(cap_ir_entries) 109 110 111def ny_support_check(sel_str, feat, feat_item, feat_sub_leaf=''): 112 if empty_check(sel_str, feat, feat_item, feat_sub_leaf): 113 return 114 if sel_str not in N_Y: 115 key = 'hv,{},{}'.format(feat, feat_item) 116 ERR_LIST[key] = "{} should be in {}".format(feat_item, N_Y) 117 118 119def scheduler_check(sel_str, feat, feat_scheduler): 120 if empty_check(sel_str, feat, feat_scheduler): 121 return 122 if sel_str not in SCHEDULER_TYPE: 123 key = 'hv,{},{}'.format(feat, feat_scheduler) 124 ERR_LIST[key] = "{} should be in {}".format(feat_scheduler, SCHEDULER_TYPE) 125 126 127def get_select_range(branch_tag, range_key): 128 129 range_list = [] 130 if range_key not in RANGE_DB.keys(): 131 key = "hv,{},{}".format(branch_tag, range_key) 132 ERR_LIST[key] = "It is invalid for {}.".format(range_key) 133 return range_list 134 135 for range_i in range(RANGE_DB[range_key]['min'], RANGE_DB[range_key]['max'] + 1): 136 range_list.append(str(range_i)) 137 138 return range_list 139 140 141def is_contiguous_bit_set(value): 142 143 bit_1_cnt = 0 144 tmp_val = value 145 is_contiguous = False 146 147 first_p = 0 148 last_p = 0 149 150 while tmp_val > 0: 151 tmp_val &= (tmp_val - 1) 152 bit_1_cnt += 1 153 154 for shift_i in range(32): 155 mask = (0x1 << shift_i) 156 if value & mask: 157 if first_p == 0 and last_p == 0: 158 first_p = shift_i + 1 159 elif first_p != 0: 160 last_p = shift_i + 1 161 else: 162 if first_p == 0 and last_p == 0: 163 continue 164 break 165 166 167 contiguous_cnt = last_p - first_p + 1 168 if bit_1_cnt == contiguous_cnt or bit_1_cnt in (0, 1): 169 is_contiguous = True 170 171 return is_contiguous 172 173 174def cat_max_mask_check(cat_mask_list, feature, cat_str, max_mask_str): 175 176 (res_info, rdt_res_clos_max, clos_max_mask_list) = board_cfg_lib.clos_info_parser(acrn_config_utilities.BOARD_INFO_FILE) 177 if not board_cfg_lib.is_rdt_enabled() or ("L2" not in res_info and "L3" not in res_info): 178 return 179 180 if board_cfg_lib.is_cdp_enabled(): 181 clos_max_set_entry = 2 * board_cfg_lib.get_common_clos_max() 182 else: 183 clos_max_set_entry = board_cfg_lib.get_common_clos_max() 184 185 cat_max_mask_settings_len = len(cat_mask_list) 186 if clos_max_set_entry != cat_max_mask_settings_len: 187 key = 'hv,{},{},{}'.format(feature, cat_str, max_mask_str) 188 ERR_LIST[key] = "Number of Cache mask entries should be equal to MAX_CACHE_CLOS_NUM_ENTRIES={}".format(clos_max_set_entry) 189 return 190 191 clos_max_mask_str = clos_max_mask_list[0].strip('"').strip("'") 192 clos_max_mask = acrn_config_utilities.num2int(clos_max_mask_str) 193 for val_str in cat_mask_list: 194 if empty_check(val_str, feature, cat_str, max_mask_str): 195 return 196 value = acrn_config_utilities.num2int(val_str) 197 if value < 0 or value > clos_max_mask: 198 key = 'hv,{},{},{}'.format(feature, cat_str, max_mask_str) 199 ERR_LIST[key] = "{} should be in range[0,{}]".format(max_mask_str, clos_max_mask_str) 200 return 201 202 if not is_contiguous_bit_set(value): 203 key = 'hv,{},{},{}'.format(feature, cat_str, max_mask_str) 204 ERR_LIST[key] = "CLOS_MASK {} should be contiguous bit set.".format(max_mask_str, clos_max_mask_str) 205 return 206 207 208def mba_delay_check(mba_delay_list, feature, mba_str, max_mask_str): 209 210 (res_info, rdt_res_clos_max, clos_max_mask_list) = board_cfg_lib.clos_info_parser(acrn_config_utilities.BOARD_INFO_FILE) 211 if not board_cfg_lib.is_rdt_enabled() or "MBA" not in res_info: 212 return 213 214 clos_max = board_cfg_lib.get_common_clos_max() 215 mba_delay_settings_len = len(mba_delay_list) 216 if clos_max != mba_delay_settings_len: 217 key = 'hv,{},{},{}'.format(feature, mba_str, max_mask_str) 218 ERR_LIST[key] = "Number of MBA delay entries should be equal to MAX_MBA_CLOS_NUM_ENTRIES={}".format(clos_max) 219 return 220 221 mba_idx = res_info.index("MBA") 222 mba_delay_str = clos_max_mask_list[mba_idx].strip('"').strip("'") 223 mba_delay = acrn_config_utilities.num2int(mba_delay_str) 224 for val_str in mba_delay_list: 225 if empty_check(val_str, feature, mba_str, max_mask_str): 226 return 227 value = acrn_config_utilities.num2int(val_str) 228 if value > mba_delay: 229 key = 'hv,{},{},{}'.format(feature, mba_str, max_mask_str) 230 ERR_LIST[key] = "{} should be in range[0,{}]".format(max_mask_str, mba_delay_str) 231 return 232 233 234def max_msix_table_num_check(max_msix_table_num, cap_str, max_msi_num_str): 235 native_max_msix_line = board_cfg_lib.get_info(acrn_config_utilities.BOARD_INFO_FILE, "<MAX_MSIX_TABLE_NUM>", "</MAX_MSIX_TABLE_NUM>") 236 if not native_max_msix_line and not max_msix_table_num: 237 empty_check(max_msix_table_num, cap_str, max_msi_num_str) 238 return 239 240 if max_msix_table_num: 241 hv_range_check(max_msix_table_num, cap_str, max_msi_num_str, RANGE_DB['MSIX_TABLE_NUM'], False) 242 if native_max_msix_line: 243 native_max_msix_num = native_max_msix_line[0].strip() 244 range_check(native_max_msix_num, "In board xml", max_msi_num_str, RANGE_DB['MSIX_TABLE_NUM']) 245 246 247def hv_ssram_check(ssram_enabled, cpd_enabled, feature, tag, leaf): 248 key = 'hv,{},{},{}'.format(feature, tag, leaf) 249 if ssram_enabled == 'y' and cpd_enabled == 'y': 250 ERR_LIST[key] = "SSRAM_ENABLED should not be y when CDP_ENABLED is y." 251 return 252