diff --git a/misc/acrn-config/board_config/pci_devices_h.py b/misc/acrn-config/board_config/pci_devices_h.py index a6628df01..86372a916 100644 --- a/misc/acrn-config/board_config/pci_devices_h.py +++ b/misc/acrn-config/board_config/pci_devices_h.py @@ -62,5 +62,16 @@ def generate_file(config): i_cnt += 1 + ivshmem_enabled = common.get_hv_item_tag(common.SCENARIO_INFO_FILE, "FEATURES", "IVSHMEM", "IVSHMEM_ENABLED") + raw_shmem_regions = common.get_hv_item_tag(common.SCENARIO_INFO_FILE, "FEATURES", "IVSHMEM", "IVSHMEM_REGION") + if ivshmem_enabled == 'y': + shmem_cnt = 0 + for raw_shmem_region in raw_shmem_regions: + if raw_shmem_region and raw_shmem_region.strip != '': + name = raw_shmem_region.split(',')[0].strip() + print("", file=config) + print("#define IVSHMEM_SHM_REGION_%-21d"%shmem_cnt, end="", file=config) + print('"{}"'.format(name), file=config) + shmem_cnt += 1 # write the end to the pci devices print("{0}".format(PCI_END_HEADER), file=config) diff --git a/misc/acrn-config/board_config/vbar_base_h.py b/misc/acrn-config/board_config/vbar_base_h.py index 2dd646d26..360525a09 100644 --- a/misc/acrn-config/board_config/vbar_base_h.py +++ b/misc/acrn-config/board_config/vbar_base_h.py @@ -78,4 +78,26 @@ def generate_file(config): i_cnt += 1 + ivshmem_enabled = common.get_hv_item_tag(common.SCENARIO_INFO_FILE, "FEATURES", "IVSHMEM", "IVSHMEM_ENABLED") + if ivshmem_enabled == 'y': + board_cfg_lib.parse_mem() + for shm_name, bar_attr_dic in board_cfg_lib.PCI_DEV_BAR_DESC.shm_bar_dic.items(): + index = shm_name[:shm_name.find('_')] + i_cnt = 0 + for bar_i, bar_attr in bar_attr_dic.items(): + i_cnt += 1 + if bar_i == 0: + if len(bar_attr_dic.keys()) == 1: + print("#define IVSHMEM_DEVICE_%-23s" % (str(index) + "_VBAR"), + " .vbar_base[{}] = {}UL".format(bar_i, bar_attr.addr), file=config) + else: + print("#define IVSHMEM_DEVICE_%-23s" % (str(index) + "_VBAR"), + " .vbar_base[{}] = {}UL, \\".format(bar_i, bar_attr.addr), file=config) + elif i_cnt == len(bar_attr_dic.keys()): + print("{}.vbar_base[{}] = {}UL".format(' ' * 54, bar_i, bar_attr.addr), file=config) + else: + print("{}.vbar_base[{}] = {}UL, \\".format(' ' * 54, bar_i, bar_attr.addr), file=config) + + print("", file=config) + print(VBAR_INFO_ENDIF, file=config) diff --git a/misc/acrn-config/hv_config/board_defconfig.py b/misc/acrn-config/hv_config/board_defconfig.py index 7a17ab06d..3d51ce4bd 100644 --- a/misc/acrn-config/hv_config/board_defconfig.py +++ b/misc/acrn-config/hv_config/board_defconfig.py @@ -33,52 +33,6 @@ VM_NUM_MAP_TOTAL_HV_RAM_SIZE = { MEM_ALIGN = 2 * common.SIZE_M -def find_avl_memory(ram_range, hpa_size, hv_start_offset): - """ - This is get hv address from System RAM as host physical size - :param ram_range: System RAM mapping - :param hpa_size: fixed host physical size - :param hv_start_offset: base address of HV RAM start - :return: start host physical address - """ - ret_start_addr = 0 - tmp_order_key = 0 - - tmp_order_key = sorted(ram_range) - for start_addr in tmp_order_key: - mem_range = ram_range[start_addr] - if start_addr < hv_start_offset < start_addr + ram_range[start_addr]: - # 256M address located in this start ram range - if start_addr + mem_range - hv_start_offset > int(hpa_size, 10): - ret_start_addr = hv_start_offset - break - elif start_addr > hv_start_offset: - # above 256M address, than return the start address of this ram range - ret_start_addr = start_addr - break - - return hex(ret_start_addr) - - -def get_ram_range(): - """ Get System RAM range mapping """ - # read system ram from board_info.xml - ram_range = {} - - io_mem_lines = board_cfg_lib.get_info( - common.BOARD_INFO_FILE, "", "") - - for line in io_mem_lines: - if 'System RAM' not in line: - continue - start_addr = int(line.split('-')[0], 16) - end_addr = int(line.split('-')[1].split(':')[0], 16) - mem_range = end_addr - start_addr - ram_range[start_addr] = mem_range - - return ram_range - - def get_serial_type(): """ Get serial console type specified by user """ ttys_type = '' @@ -123,17 +77,20 @@ def get_memory(hv_info, config): err_dic["board config: total vm number error"] = "VM num should not be greater than 8" return err_dic - ram_range = get_ram_range() - # reseve 16M memory for hv sbuf, ramoops, etc. reserved_ram = 0x1000000 # We recommend to put hv ram start address high than 0x10000000 to # reduce memory conflict with GRUB/SOS Kernel. hv_start_offset = 0x10000000 total_size = reserved_ram + hv_ram_size - avl_start_addr = find_avl_memory(ram_range, str(total_size), hv_start_offset) + for start_addr in list(board_cfg_lib.USED_RAM_RANGE): + if hv_start_offset <= start_addr < 0x80000000: + del board_cfg_lib.USED_RAM_RANGE[start_addr] + ram_range = board_cfg_lib.get_ram_range() + avl_start_addr = board_cfg_lib.find_avl_memory(ram_range, str(total_size), hv_start_offset) hv_start_addr = int(avl_start_addr, 16) + int(hex(reserved_ram), 16) hv_start_addr = common.round_up(hv_start_addr, MEM_ALIGN) + board_cfg_lib.USED_RAM_RANGE[hv_start_addr] = total_size if not hv_info.mem.hv_ram_start: print("CONFIG_HV_RAM_START={}".format(hex(hv_start_addr)), file=config) @@ -149,6 +106,7 @@ def get_memory(hv_info, config): print("CONFIG_SOS_RAM_SIZE={}".format(hv_info.mem.sos_ram_size), file=config) print("CONFIG_UOS_RAM_SIZE={}".format(hv_info.mem.uos_ram_size), file=config) print("CONFIG_STACK_SIZE={}".format(hv_info.mem.stack_size), file=config) + print("CONFIG_IVSHMEM_ENABLED={}".format(hv_info.mem.ivshmem_enable), file=config) def get_serial_console(config): diff --git a/misc/acrn-config/hv_config/hv_item.py b/misc/acrn-config/hv_config/hv_item.py index 720337a8f..acedae8f7 100644 --- a/misc/acrn-config/hv_config/hv_item.py +++ b/misc/acrn-config/hv_config/hv_item.py @@ -153,6 +153,8 @@ class Memory: self.platform_ram_size = 0 self.sos_ram_size = 0 self.uos_ram_size = 0 + self.ivshmem_enable = 'n' + self.ivshmem_region = [] def get_info(self): self.stack_size = common.get_hv_item_tag(self.hv_file, "MEMORY", "STACK_SIZE") @@ -162,6 +164,8 @@ class Memory: self.platform_ram_size = common.get_hv_item_tag(self.hv_file, "MEMORY", "PLATFORM_RAM_SIZE") self.sos_ram_size = common.get_hv_item_tag(self.hv_file, "MEMORY", "SOS_RAM_SIZE") self.uos_ram_size = common.get_hv_item_tag(self.hv_file, "MEMORY", "UOS_RAM_SIZE") + self.ivshmem_enable = common.get_hv_item_tag(self.hv_file, "FEATURES", "IVSHMEM", "IVSHMEM_ENABLED") + self.ivshmem_region = common.get_hv_item_tag(self.hv_file, "FEATURES", "IVSHMEM", "IVSHMEM_REGION") def check_item(self): hv_cfg_lib.hv_size_check(self.stack_size, "MEMORY", "STACK_SIZE") @@ -169,6 +173,7 @@ class Memory: hv_cfg_lib.hv_size_check(self.platform_ram_size, "MEMORY", "PLATFORM_RAM_SIZE") hv_cfg_lib.hv_size_check(self.sos_ram_size, "MEMORY", "SOS_RAM_SIZE") hv_cfg_lib.hv_size_check(self.uos_ram_size, "MEMORY", "UOS_RAM_SIZE") + hv_cfg_lib.ny_support_check(self.ivshmem_enable, "FEATURES", "IVSHMEM", "IVSHMEM_ENABLED") class HvInfo: diff --git a/misc/acrn-config/library/board_cfg_lib.py b/misc/acrn-config/library/board_cfg_lib.py index 3b891b9de..921a0fe0b 100644 --- a/misc/acrn-config/library/board_cfg_lib.py +++ b/misc/acrn-config/library/board_cfg_lib.py @@ -21,6 +21,7 @@ LEGACY_TTYS = { VALID_LEGACY_IRQ = [] ERR_LIST = {} +USED_RAM_RANGE = {} HEADER_LICENSE = common.open_license() + "\n" @@ -363,6 +364,7 @@ class Pci_Dev_Bar_Desc: def __init__(self): self.pci_dev_dic = {} self.pci_bar_dic = {} + self.shm_bar_dic = {} PCI_DEV_BAR_DESC = Pci_Dev_Bar_Desc() SUB_NAME_COUNT = {} @@ -472,6 +474,47 @@ def parser_pci(): PCI_DEV_BAR_DESC.pci_bar_dic[cur_bdf] = tmp_bar_dic +def parse_mem(): + raw_shmem_regions = common.get_hv_item_tag(common.SCENARIO_INFO_FILE, "FEATURES", "IVSHMEM", "IVSHMEM_REGION") + + global USED_RAM_RANGE + for shm_name, shm_bar_dic in PCI_DEV_BAR_DESC.shm_bar_dic.items(): + if 0 in shm_bar_dic.keys() and int(shm_bar_dic[0].addr, 16) in USED_RAM_RANGE.keys(): + del USED_RAM_RANGE[int(shm_bar_dic[0].addr, 16)] + if 2 in shm_bar_dic.keys() and int(shm_bar_dic[2].addr, 16)-0xC in USED_RAM_RANGE.keys(): + del USED_RAM_RANGE[int(shm_bar_dic[2].addr, 16)-0xC] + + idx = 0 + for shm in raw_shmem_regions: + if shm is None or shm.strip() == '': + continue + shm_splited = shm.split(',') + name = shm_splited[0].strip() + size = shm_splited[1].strip() + + if size.isdecimal(): + int_size = int(size) + else: + int_size = int(size, 16) + ram_range = get_ram_range() + tmp_bar_dict = {} + hv_start_offset = 0x80000000 + ret_start_addr = find_avl_memory(ram_range, str(0x200100), hv_start_offset) + bar_mem_0 = Bar_Mem() + bar_mem_0.addr = hex(common.round_up(int(ret_start_addr, 16), 0x200000)) + USED_RAM_RANGE[int(bar_mem_0.addr, 16)] = 0x100 + tmp_bar_dict[0] = bar_mem_0 + ram_range = get_ram_range() + hv_start_offset2 = 0x100000000 + ret_start_addr2 = find_avl_memory(ram_range, str(int_size + 0x200000), hv_start_offset2) + bar_mem_2 = Bar_Mem() + bar_mem_2.addr = hex(common.round_up(int(ret_start_addr2, 16), 0x200000) + 0xC) + USED_RAM_RANGE[common.round_up(int(ret_start_addr2, 16), 0x20000)] = int_size + tmp_bar_dict[2] = bar_mem_2 + PCI_DEV_BAR_DESC.shm_bar_dic[str(idx)+'_'+name] = tmp_bar_dict + idx += 1 + + def is_rdt_supported(): """ Returns True if platform supports RDT else False @@ -569,3 +612,71 @@ def is_tpm_passthru(): tpm_passthru = True return tpm_passthru + + +def find_avl_memory(ram_range, hpa_size, hv_start_offset): + """ + This is get hv address from System RAM as host physical size + :param ram_range: System RAM mapping + :param hpa_size: fixed host physical size + :param hv_start_offset: base address of HV RAM start + :return: start host physical address + """ + ret_start_addr = 0 + tmp_order_key = 0 + int_hpa_size = int(hpa_size, 10) + + tmp_order_key = sorted(ram_range) + for start_addr in tmp_order_key: + mem_range = ram_range[start_addr] + if start_addr <= hv_start_offset and hv_start_offset + int_hpa_size <= start_addr + mem_range: + ret_start_addr = hv_start_offset + break + elif start_addr >= hv_start_offset and mem_range >= int_hpa_size: + ret_start_addr = start_addr + break + + return hex(ret_start_addr) + + +def get_ram_range(): + """ Get System RAM range mapping """ + # read system ram from board_info.xml + ram_range = {} + + io_mem_lines = get_info( + common.BOARD_INFO_FILE, "", "") + + for line in io_mem_lines: + if 'System RAM' not in line: + continue + start_addr = int(line.split('-')[0], 16) + end_addr = int(line.split('-')[1].split(':')[0], 16) + mem_range = end_addr - start_addr + ram_range[start_addr] = mem_range + + global USED_RAM_RANGE + tmp_order_key_used = sorted(USED_RAM_RANGE) + for start_addr_used in tmp_order_key_used: + mem_range_used = USED_RAM_RANGE[start_addr_used] + tmp_order_key = sorted(ram_range) + for start_addr in tmp_order_key: + mem_range = ram_range[start_addr] + if start_addr < start_addr_used and start_addr_used + mem_range_used < start_addr + mem_range: + ram_range[start_addr] = start_addr_used - start_addr + ram_range[start_addr_used+mem_range_used] = start_addr + mem_range - start_addr_used - mem_range_used + break + elif start_addr == start_addr_used and start_addr_used + mem_range_used < start_addr + mem_range: + del ram_range[start_addr] + ram_range[start_addr_used + mem_range_used] = start_addr + mem_range - start_addr_used - mem_range_used + break + elif start_addr < start_addr_used and start_addr_used + mem_range_used == start_addr + mem_range: + ram_range[start_addr] = start_addr_used - start_addr + break + elif start_addr == start_addr_used and start_addr_used + mem_range_used == start_addr + mem_range: + del ram_range[start_addr] + break + else: + continue + + return ram_range diff --git a/misc/acrn-config/library/common.py b/misc/acrn-config/library/common.py index 9a9fb7943..70f4d526f 100644 --- a/misc/acrn-config/library/common.py +++ b/misc/acrn-config/library/common.py @@ -19,7 +19,7 @@ PY_CACHES = ["__pycache__", "../board_config/__pycache__", "../scenario_config/_ GUEST_FLAG = ["0UL", "GUEST_FLAG_SECURE_WORLD_ENABLED", "GUEST_FLAG_LAPIC_PASSTHROUGH", "GUEST_FLAG_IO_COMPLETION_POLLING", "GUEST_FLAG_HIDE_MTRR", "GUEST_FLAG_RT"] -MULTI_ITEM = ["guest_flag", "pcpu_id", "vcpu_clos", "input", "block", "network", "pci_dev"] +MULTI_ITEM = ["guest_flag", "pcpu_id", "vcpu_clos", "input", "block", "network", "pci_dev", "shmem_region"] SIZE_K = 1024 SIZE_M = SIZE_K * 1024 @@ -45,6 +45,7 @@ class MultiItem(): self.vir_console = [] self.vir_network = [] self.pci_dev = [] + self.shmem_region = [] class TmpItem(): @@ -282,6 +283,10 @@ def get_leaf_value(tmp, tag_str, leaf): if leaf.tag == "pci_dev" and tag_str == "pci_dev": tmp.multi.pci_dev.append(leaf.text) + # get shmem_region for vm + if leaf.tag == "shmem_region" and tag_str == "shmem_region": + tmp.multi.shmem_region.append(leaf.text) + def get_sub_value(tmp, tag_str, vm_id): @@ -313,6 +318,10 @@ def get_sub_value(tmp, tag_str, vm_id): if tmp.multi.pci_dev and tag_str == "pci_dev": tmp.tag[vm_id] = tmp.multi.pci_dev + # append shmem_region for vm + if tmp.multi.shmem_region and tag_str == "shmem_region": + tmp.tag[vm_id] = tmp.multi.shmem_region + def get_leaf_tag_map(config_file, branch_tag, tag_str=''): """ @@ -409,6 +418,7 @@ def get_hv_item_tag(config_file, branch_tag, tag_str='', leaf_str=''): tmp = '' root = get_config_root(config_file) + for item in root: # for each 2th level item for sub in item: @@ -421,26 +431,35 @@ def get_hv_item_tag(config_file, branch_tag, tag_str='', leaf_str=''): continue # for each 3rd level item + tmp_list = [] for leaf in sub: if leaf.tag == tag_str: if not leaf_str: if leaf.tag == tag_str and leaf.text and leaf.text != None: - tmp = leaf.text + if tag_str == "IVSHMEM_REGION": + tmp_list.append(leaf.text) + else: + tmp = leaf.text + else: # for each 4rd level item tmp_list = [] for leaf_s in leaf: if leaf_s.tag == leaf_str and leaf_s.text and leaf_s.text != None: - if leaf_str == "CLOS_MASK" or leaf_str == "MBA_DELAY": + if leaf_str == "CLOS_MASK" or leaf_str == "MBA_DELAY" or leaf_str == "IVSHMEM_REGION": tmp_list.append(leaf_s.text) else: tmp = leaf_s.text continue - if leaf_str == "CLOS_MASK" or leaf_str == "MBA_DELAY": + if leaf_str == "CLOS_MASK" or leaf_str == "MBA_DELAY" or leaf_str == "IVSHMEM_REGION": tmp = tmp_list break + if tag_str == "IVSHMEM_REGION": + tmp = tmp_list + break + return tmp diff --git a/misc/acrn-config/library/scenario_cfg_lib.py b/misc/acrn-config/library/scenario_cfg_lib.py index 45e4b50a1..f91e79bdb 100644 --- a/misc/acrn-config/library/scenario_cfg_lib.py +++ b/misc/acrn-config/library/scenario_cfg_lib.py @@ -3,6 +3,7 @@ # SPDX-License-Identifier: BSD-3-Clause # +import math import common import board_cfg_lib @@ -92,6 +93,41 @@ def get_pci_num(pci_devs): return pci_devs_num +def get_shmem_regions(raw_shmem_regions): + shmem_regions = {'err': []} + for raw_shmem_region in raw_shmem_regions: + if raw_shmem_region and raw_shmem_region.strip(): + shm_splited = raw_shmem_region.split(',') + if len(shm_splited) == 3 and (shm_splited[0].strip() != '' and shm_splited[1].strip() != '' + and len(shm_splited[2].split(':')) >= 2): + name = shm_splited[0].strip() + size = shm_splited[1].strip() + vmid_list = shm_splited[2].split(':') + for i in range(len(vmid_list)): + try: + int_vm_id = int(vmid_list[i]) + except: + shmem_regions['err'].append(raw_shmem_region) + break + if int_vm_id not in shmem_regions.keys(): + shmem_regions[int_vm_id] = [','.join([name, size, ':'.join(vmid_list[0:i]+vmid_list[i+1:])])] + else: + shmem_regions[int_vm_id].append(','.join([name, size, ':'.join(vmid_list[0:i]+vmid_list[i+1:])])) + elif raw_shmem_region.strip() != '': + shmem_regions['err'].append(raw_shmem_region) + + return shmem_regions + + +def get_shmem_num(shmem_regions): + + shmem_num = {} + for shm_i, shm_list in shmem_regions.items(): + shmem_num[shm_i] = len(shm_list) + + return shmem_num + + def check_board_private_info(): if 'SOS_VM' not in common.VM_TYPES.values(): @@ -648,3 +684,111 @@ def vcpu_clos_check(cpus_per_vm, clos_per_vm, prime_item, item): key = "vm:id={},{},{}".format(vm_i, prime_item, item) ERR_LIST[key] = "CDP_ENABLED=y, the clos value should not be greater than {} for VM{}".format(common_clos_max - 1, vm_i) return + + +def share_mem_check(shmem_regions, raw_shmem_regions, vm_type_info, prime_item, item, sub_item): + + shmem_names = {} + for shm_i, shm_list in shmem_regions.items(): + for shm_str in shm_list: + index = -1 + if shm_i == 'err': + for i in range(len(raw_shmem_regions)): + if raw_shmem_regions[i] == shm_str: + index = i + break + if index == -1: + try: + for i in range(len(raw_shmem_regions)): + if raw_shmem_regions[i].split(',')[0].strip() == shm_str.split(',')[0].strip(): + index = i + break + except: + index = 0 + key = "hv,{},{},{}".format(prime_item, item, sub_item, index) + + shm_str_splited = shm_str.split(',') + if len(shm_str_splited) < 3: + ERR_LIST[key] = "The name, size, communication VM IDs of the share memory should be separated " \ + "by comma and not be empty." + return + try: + curr_vm_id = int(shm_i) + except: + ERR_LIST[key] = "share memory region should be configure with format like this: VM0_VM2,0x20000,0:2" + return + name = shm_str_splited[0].strip() + size = shm_str_splited[1].strip() + vmid_list = shm_str_splited[2].split(':') + int_vmid_list = [] + for vmid in vmid_list: + try: + int_vmid = int(vmid) + int_vmid_list.append(int_vmid) + except: + ERR_LIST[key] = "The communication VM IDs of the share memory should be decimal and separated by comma." + return + if not int_vmid_list: + ERR_LIST[key] = "The communication VM IDs of the share memory should be decimal and separated by comma." + return + if curr_vm_id in int_vmid_list or len(set(int_vmid_list)) != len(int_vmid_list): + ERR_LIST[key] = "The communication VM IDs of the share memory should not be duplicated." + return + for target_vm_id in int_vmid_list: + if curr_vm_id not in vm_type_info.keys() or target_vm_id not in vm_type_info.keys() \ + or vm_type_info[curr_vm_id] in ['SOS_VM'] or vm_type_info[target_vm_id] in ['SOS_VM']: + ERR_LIST[key] = "Shared Memory can be only configured for existed Pre-launched VMs and Post-launched VMs." + return + + if name =='' or size == '': + ERR_LIST[key] = "The name, size of the share memory should not be empty." + return + name_len = len(name) + if name_len > 32 or name_len == 0: + ERR_LIST[key] = "The size of share Memory name should be in range [1,32] bytes." + return + + int_size = 0 + try: + if size.isdecimal(): + int_size = int(size) + else: + int_size = int(size, 16) + except: + ERR_LIST[key] = "The size of share Memory region should be decimal or hexadecimal." + return + if int_size < 0x200000 or int_size > 0x40000000: + ERR_LIST[key] = "The size of share Memory region should be in [2M, 1G]." + return + if not math.log(int_size, 2).is_integer(): + ERR_LIST[key] = "The size of share Memory region should be a power of 2." + return + + if name in shmem_names.keys(): + shmem_names[name] += 1 + else: + shmem_names[name] = 1 + if shmem_names[name] > len(vmid_list)+1: + ERR_LIST[key] = "The names of share memory regions should not be duplicated: {}".format(name) + return + + board_cfg_lib.parse_mem() + for shm_i, shm_list in shmem_regions.items(): + for shm_str in shm_list: + shm_str_splited = shm_str.split(',') + name = shm_str_splited[0].strip() + index = 0 + try: + for i in range(len(raw_shmem_regions)): + if raw_shmem_regions[i].split(',')[0].strip() == shm_str.split(',')[0].strip(): + index = i + break + except: + index = 0 + key = "hv,{},{},{}".format(prime_item, item, sub_item, index) + if 'IVSHMEM_'+name in board_cfg_lib.PCI_DEV_BAR_DESC.shm_bar_dic.keys(): + bar_attr_dic = board_cfg_lib.PCI_DEV_BAR_DESC.shm_bar_dic['IVSHMEM_'+name] + if (0 in bar_attr_dic.keys() and int(bar_attr_dic[0].addr, 16) < 0x80000000) \ + or (2 in bar_attr_dic.keys() and int(bar_attr_dic[2].addr, 16) < 0x100000000): + ERR_LIST[key] = "Failed to get the start address of the shared memory, please check the size of it." + return diff --git a/misc/acrn-config/scenario_config/ivshmem_cfg_h.py b/misc/acrn-config/scenario_config/ivshmem_cfg_h.py new file mode 100644 index 000000000..950f50006 --- /dev/null +++ b/misc/acrn-config/scenario_config/ivshmem_cfg_h.py @@ -0,0 +1,96 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import common +import scenario_cfg_lib +import board_cfg_lib + +IVSHMEM_HEADER_DEFINE = scenario_cfg_lib.HEADER_LICENSE + r""" +#ifndef IVSHMEM_CFG_H +#define IVSHMEM_CFG_H +""" +IVSHMEM_END_DEFINE = r"""#endif /* IVSHMEM_CFG_H */""" + + +def gen_common_header(config): + """ + This is common header for ivshmem_cfg.h + :param config: it is the pointer which file write to + :return: None + """ + print("{0}".format(IVSHMEM_HEADER_DEFINE), file=config) + + +def write_shmem_regions(config): + raw_shmem_regions = common.get_hv_item_tag(common.SCENARIO_INFO_FILE, "FEATURES", "IVSHMEM", "IVSHMEM_REGION") + shmem_regions = [] + shmem_dev_num = 0 + for raw_shm in raw_shmem_regions: + if raw_shm is None or raw_shm.strip() == '': + continue + raw_shm_splited = raw_shm.split(',') + if len(raw_shm_splited) == 3 and raw_shm_splited[0].strip() != '' \ + and raw_shm_splited[1].strip() != '' and len(raw_shm_splited[2].strip().split(':')) >= 1: + shmem_regions.append((raw_shm_splited[0].strip(), raw_shm_splited[1].strip(), raw_shm_splited[2].strip().split(':'))) + shmem_dev_num += len(raw_shm_splited[2].strip().split(':')) + + print("", file=config) + print("/*", file=config) + print(" * The IVSHMEM_SHM_SIZE is the sum of all memory regions.", file=config) + print(" * The size range of each memory region is [2M, 1G) and is a power of 2.", file=config) + print(" */", file=config) + total_shm_size = 0 + if len(shmem_regions) > 0: + for shmem_region in shmem_regions: + int_size = 0 + size = shmem_region[1] + try: + if size.isdecimal(): + int_size = int(size) + else: + int_size = int(size, 16) + except Exception as e: + print('the format of shm size error: ', str(e)) + total_shm_size += int_size + + print("#define IVSHMEM_SHM_SIZE\t{}UL".format(hex(total_shm_size)), file=config) + print("#define IVSHMEM_DEV_NUM\t\t{}UL".format(shmem_dev_num), file=config) + print("", file=config) + print("/* All user defined memory regions */", file=config) + print("\nstruct ivshmem_shm_region mem_regions[] = {", file=config) + shmem_cnt = 0 + for shmem in shmem_regions: + print("\t{", file=config) + print('\t\t.name = IVSHMEM_SHM_REGION_{},'.format(shmem_cnt), file=config) + try: + if shmem[1].isdecimal(): + int_m_size = int(int(shmem[1])/0x100000) + else: + int_m_size = int(int(shmem[1], 16)/0x100000) + except: + int_m_size = 0 + print('\t\t.size = {}UL,\t\t/* {}M */'.format(shmem[1], int_m_size), file=config) + print("\t},", file=config) + shmem_cnt += 1 + print("};", file=config) + print("", file=config) + + +def generate_file(scenario_items, config): + """ + Start to generate ivshmem_cfg.h + :param scenario_items: it is the class which contain all user setting information + :param config: it is a file pointer of scenario information for writing to + """ + vm_info = scenario_items['vm'] + gen_common_header(config) + + if vm_info.shmem.shmem_enabled == 'y': + print("#include ", file=config) + print("#include ", file=config) + print("#include ", file=config) + write_shmem_regions(config) + + print("{0}".format(IVSHMEM_END_DEFINE), file=config) diff --git a/misc/acrn-config/scenario_config/pci_dev_c.py b/misc/acrn-config/scenario_config/pci_dev_c.py index 0d7f6d0c5..b6da82b0a 100644 --- a/misc/acrn-config/scenario_config/pci_dev_c.py +++ b/misc/acrn-config/scenario_config/pci_dev_c.py @@ -27,6 +27,7 @@ def generate_file(vm_info, config): :return: None """ board_cfg_lib.parser_pci() + board_cfg_lib.parse_mem() compared_bdf = [] @@ -51,14 +52,24 @@ def generate_file(vm_info, config): print("#include ", file=config) print("#include ", file=config) print("#include ", file=config) + 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) 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) @@ -76,7 +87,7 @@ def generate_file(vm_info, config): 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 = 0x0{}U, .f = 0x00U}},".format(pci_cnt), 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) @@ -85,4 +96,57 @@ def generate_file(vm_info, config): print("\t},", file=config) pci_cnt += 1 + 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: + 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) + 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) + pci_cnt += 1 + 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 diff --git a/misc/acrn-config/scenario_config/scenario_cfg_gen.py b/misc/acrn-config/scenario_config/scenario_cfg_gen.py index de9e4fa38..b924d05f2 100755 --- a/misc/acrn-config/scenario_config/scenario_cfg_gen.py +++ b/misc/acrn-config/scenario_config/scenario_cfg_gen.py @@ -14,6 +14,7 @@ import scenario_cfg_lib import vm_configurations_c import vm_configurations_h import pci_dev_c +import ivshmem_cfg_h import common import hv_cfg_lib import board_defconfig @@ -21,7 +22,7 @@ from hv_item import HvInfo ACRN_PATH = common.SOURCE_ROOT_DIR ACRN_CONFIG_DEF = ACRN_PATH + 'misc/vm_configs/scenarios/' -GEN_FILE = ["vm_configurations.h", "vm_configurations.c", "pci_dev.c", ".config"] +GEN_FILE = ["vm_configurations.h", "vm_configurations.c", "pci_dev.c", ".config", "ivshmem_cfg.h"] def get_scenario_item_values(board_info, scenario_info): @@ -73,6 +74,7 @@ def get_scenario_item_values(board_info, scenario_info): scenario_item_values["hv,FEATURES,L1D_VMENTRY_ENABLED"] = hv_cfg_lib.N_Y scenario_item_values["hv,FEATURES,MCE_ON_PSC_DISABLED"] = hv_cfg_lib.N_Y scenario_item_values["hv,FEATURES,IOMMU_ENFORCE_SNP"] = hv_cfg_lib.N_Y + scenario_item_values["hv,FEATURES,IVSHMEM,IVSHMEM_ENABLED"] = hv_cfg_lib.N_Y scenario_cfg_lib.ERR_LIST.update(hv_cfg_lib.ERR_LIST) return scenario_item_values @@ -90,15 +92,16 @@ def validate_scenario_setting(board_info, scenario_info): common.BOARD_INFO_FILE = board_info common.SCENARIO_INFO_FILE = scenario_info - scenario_info_items = {} - vm_info = VmInfo(board_info, scenario_info) - vm_info.get_info() - vm_info.check_item() - hv_info = HvInfo(scenario_info) hv_info.get_info() hv_info.check_item() + scenario_info_items = {} + vm_info = VmInfo(board_info, scenario_info) + vm_info.get_info() + vm_info.set_ivshmem(hv_info.mem.ivshmem_region) + vm_info.check_item() + scenario_info_items['vm'] = vm_info scenario_info_items['hv'] = hv_info @@ -151,7 +154,7 @@ def main(args): else: scen_output = ACRN_PATH + params['--out'] + "/scenarios/" + scenario + "/" else: - scen_output = ACRN_CONFIG_DEF + "/scenarios/" + scenario + "/" + scen_output = ACRN_CONFIG_DEF + "/" + scenario + "/" scen_board = scen_output + board_name + "/" common.mkdir(scen_board) @@ -161,6 +164,7 @@ def main(args): vm_config_c = scen_output + GEN_FILE[1] pci_config_c = scen_board + GEN_FILE[2] config_hv = scen_board + board_name + GEN_FILE[3] + ivshmem_config_h = scen_board + GEN_FILE[4] # parse the scenario.xml get_scenario_item_values(params['--board'], params['--scenario']) @@ -185,6 +189,11 @@ def main(args): if err_dic: return err_dic + # generate ivshmem_cfg.h + print(ivshmem_config_h) + with open(ivshmem_config_h, 'w') as config: + ivshmem_cfg_h.generate_file(scenario_items, config) + # generate pci_dev.c with open(pci_config_c, 'w') as config: pci_dev_c.generate_file(scenario_items['vm'], config) diff --git a/misc/acrn-config/scenario_config/scenario_item.py b/misc/acrn-config/scenario_config/scenario_item.py index 2b3f9415c..174989ad1 100644 --- a/misc/acrn-config/scenario_config/scenario_item.py +++ b/misc/acrn-config/scenario_config/scenario_item.py @@ -228,6 +228,38 @@ class EpcSection: self.size = common.get_leaf_tag_map(self.scenario_info, "epc_section", "size") +class ShareMem: + """ This is the class to get Share Memory regions for VMs """ + shmem_enabled = 'n' + raw_shmem_regions = [] + shmem_regions = {} + shmem_num = {} + + def __init__(self, scenario_info): + self.scenario_info = scenario_info + + def set_ivshmem(self, ivshmem_regions): + """ + set ivshmem regions for VMs. + :param ivshmem_regions: + :return: + """ + self.raw_shmem_regions = ivshmem_regions + self.shmem_enabled = common.get_hv_item_tag(self.scenario_info, "FEATURES", "IVSHMEM", "IVSHMEM_ENABLED") + self.shmem_regions = scenario_cfg_lib.get_shmem_regions(ivshmem_regions) + self.shmem_num = scenario_cfg_lib.get_shmem_num(self.shmem_regions) + + def check_items(self): + ''' + check the configurations for share memories. + :return: + ''' + if self.shmem_enabled == 'y': + vm_type_info = common.get_leaf_tag_map(self.scenario_info, "vm_type") + scenario_cfg_lib.share_mem_check(self.shmem_regions, self.raw_shmem_regions, vm_type_info, + "FEATURES", "IVSHMEM", "IVSHMEM_REGION") + + class LoadOrderNum: """ This is Abstract of VM number for different load order """ def __init__(self): @@ -259,6 +291,7 @@ class VmInfo: self.vuart = VuartInfo(self.scenario_info) self.cfg_pci = CfgPci(self.scenario_info) self.load_order_cnt = LoadOrderNum() + self.shmem = ShareMem(self.scenario_info) def get_info(self): """ @@ -281,6 +314,14 @@ class VmInfo: self.cfg_pci.get_info() self.load_order_cnt.get_info(self.load_vm) + def set_ivshmem(self, ivshmem_regions): + """ + set ivshmem regions for VMs + :param ivshmem_regions: + :return: + """ + self.shmem.set_ivshmem(ivshmem_regions) + def get_cpu_bitmap(self, index): """ :param index: index list in GUESF_FLAGS @@ -310,4 +351,5 @@ class VmInfo: self.os_cfg.check_item() self.cfg_pci.check_item() self.vuart.check_item() + self.shmem.check_items() scenario_cfg_lib.ERR_LIST.update(err_dic) diff --git a/misc/acrn-config/scenario_config/vm_configurations_c.py b/misc/acrn-config/scenario_config/vm_configurations_c.py index 323dd4fb7..19c5ec5a8 100644 --- a/misc/acrn-config/scenario_config/vm_configurations_c.py +++ b/misc/acrn-config/scenario_config/vm_configurations_c.py @@ -340,7 +340,9 @@ def gen_pre_launch_vm(vm_type, vm_i, scenario_items, config): if err_dic: return err_dic - if vm_info.cfg_pci.pci_devs[vm_i] and vm_info.cfg_pci.pci_devs[vm_i] != None: + 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]): 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) @@ -363,6 +365,11 @@ 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]: + 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) cpu_affinity_output(vm_info, vm_i, config) is_need_epc(vm_info.epc_section, vm_i, config) # VUART @@ -376,10 +383,13 @@ def gen_post_launch_vm(vm_type, vm_i, scenario_items, config): def pre_launch_definiation(vm_info, config): for vm_i,vm_type in common.VM_TYPES.items(): - if "PRE_LAUNCHED_VM" != scenario_cfg_lib.VM_DB[vm_type]['load_type']: + if scenario_cfg_lib.VM_DB[vm_type]['load_type'] not in ["PRE_LAUNCHED_VM", "POST_LAUNCHED_VM"]: continue - print("extern struct acrn_vm_pci_dev_config " + - "vm{}_pci_devs[VM{}_CONFIG_PCI_DEV_NUM];".format(vm_i, vm_i), file=config) + 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]): + 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) def generate_file(scenario_items, config): diff --git a/misc/acrn-config/scenario_config/vm_configurations_h.py b/misc/acrn-config/scenario_config/vm_configurations_h.py index b5de6c328..719c2072c 100644 --- a/misc/acrn-config/scenario_config/vm_configurations_h.py +++ b/misc/acrn-config/scenario_config/vm_configurations_h.py @@ -91,7 +91,12 @@ def gen_pre_launch_vm(scenario_items, config): print("#define VM{0}_CONFIG_MEM_SIZE_HPA2 {1}UL".format( vm_i, vm_info.mem_info.mem_size_hpa2[vm_i]), file=config) - print("#define VM{}_CONFIG_PCI_DEV_NUM {}U".format(vm_i, vm_info.cfg_pci.pci_dev_num[vm_i]), file=config) + shmem_num_i = 0 + if vm_info.shmem.shmem_enabled == 'y' and vm_i in vm_info.shmem.shmem_num.keys(): + shmem_num_i = vm_info.shmem.shmem_num[vm_i] + + print("#define VM{}_CONFIG_PCI_DEV_NUM {}U".format(vm_i, + vm_info.cfg_pci.pci_dev_num[vm_i] + shmem_num_i), file=config) print("", file=config) vm_i += 1 @@ -108,6 +113,10 @@ def gen_post_launch_header(scenario_items, config): is_post_vm_available = True cpu_affinity_output(vm_info, vm_i, config) clos_config_output(scenario_items, vm_i, config) + + if vm_info.shmem.shmem_enabled == 'y' and vm_i in vm_info.shmem.shmem_num.keys(): + print("#define VM{}_CONFIG_PCI_DEV_NUM {}U".format(vm_i, + vm_info.shmem.shmem_num[vm_i]), file=config) vm_i += 1 if is_post_vm_available: