mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-26 15:31:35 +00:00
acrn-config: add static allocators to rewrite scenario XMLs
In order to split the allocation logic from tranformation in the configuration tool, this patch introduces the `static_allocators` directory under `misc/acrn-config` to host scripts that statically allocate resources (currently the physical memory) and fill the scenario XML with the results. The logic is extracted from the existing configuration tool which allocates resources when transforming XML files, while XPath is used to read and manipulate the XML when possible. The aim is to make transformation from XML files to C configuration sources to be more trivial and easier to express in descriptive languages like XSLT. v2: * Instead of rewriting the scenario XML, the new version generates allocation results to a new XML named `allocation.xml` so that the form of the results are not restricted by the XML schema. Tracked-On: #5644 Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
parent
9cff2bbdc0
commit
7a145253f3
@ -10,6 +10,7 @@ import shutil
|
||||
import subprocess
|
||||
import xml.etree.ElementTree as ET
|
||||
import re
|
||||
import lxml
|
||||
|
||||
|
||||
ACRN_CONFIG_TARGET = ''
|
||||
@ -183,6 +184,39 @@ def get_xml_attrib(config_file, attrib):
|
||||
|
||||
return (err_dic, value)
|
||||
|
||||
def count_nodes(xpath, etree):
|
||||
return int(etree.xpath(f"count({xpath})"))
|
||||
|
||||
def get_text(xpath, etree):
|
||||
result = etree.xpath(f"{xpath}/text()")
|
||||
assert len(result) == 1, "Internal error: cannot get texts from multiple nodes at a time"
|
||||
return result[0]
|
||||
|
||||
def update_text(xpath, value, etree, overwrite=False):
|
||||
result = etree.xpath(f"{xpath}")
|
||||
assert len(result) == 1, "Internal error: cannot set text to multiple nodes at a time"
|
||||
if overwrite or not result[0].text:
|
||||
result[0].text = str(value)
|
||||
|
||||
def append_node(xpath, value, etree):
|
||||
# Look for an existing ancestor node
|
||||
parts = xpath.split("/")
|
||||
ancestor_level = 1
|
||||
ancestor = None
|
||||
while ancestor_level < len(parts):
|
||||
result = etree.xpath("/".join(parts[:-ancestor_level]))
|
||||
assert len(result) <= 1, "Internal error: cannot append element nodes to multiple ancestors"
|
||||
if len(result) == 1:
|
||||
ancestor = result[0]
|
||||
break
|
||||
ancestor_level += 1
|
||||
|
||||
assert ancestor is not None, f"Internal error: cannot find an existing ancestor for {xpath}"
|
||||
for tag in parts[-ancestor_level:]:
|
||||
child = lxml.etree.Element(tag)
|
||||
ancestor.append(child)
|
||||
ancestor = child
|
||||
child.text = str(value)
|
||||
|
||||
def get_board_name():
|
||||
"""
|
||||
|
75
misc/acrn-config/static_allocators/hv_ram.py
Normal file
75
misc/acrn-config/static_allocators/hv_ram.py
Normal file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import sys, os
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library'))
|
||||
import common, board_cfg_lib
|
||||
|
||||
VM_NUM_MAP_TOTAL_HV_RAM_SIZE = {
|
||||
# 120M
|
||||
2:0x7800000,
|
||||
# 150M
|
||||
3:0x9600000,
|
||||
# 190M
|
||||
4:0xBE00000,
|
||||
# 210M
|
||||
5:0xD200000,
|
||||
# 250M
|
||||
6:0xFA00000,
|
||||
# 300M
|
||||
7:0x12C00000,
|
||||
# 328M
|
||||
8:0x14800000,
|
||||
}
|
||||
|
||||
HV_RAM_SIZE_MAX = 0x40000000
|
||||
|
||||
MEM_ALIGN = 2 * common.SIZE_M
|
||||
|
||||
def fn(board_etree, scenario_etree, allocation_etree):
|
||||
# this dictonary mapped with 'address start':'mem range'
|
||||
ram_range = {}
|
||||
|
||||
vm_count = common.count_nodes("//*[local-name() = 'vm']", scenario_etree)
|
||||
hv_ram_size = VM_NUM_MAP_TOTAL_HV_RAM_SIZE[vm_count]
|
||||
|
||||
ivshmem_enabled = common.get_text("//IVSHMEM_ENABLED", scenario_etree)
|
||||
total_shm_size = 0
|
||||
if ivshmem_enabled == 'y':
|
||||
raw_shmem_regions = scenario_etree.xpath("//IVSHMEM_REGION/text()")
|
||||
for raw_shm in raw_shmem_regions:
|
||||
if 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:
|
||||
try:
|
||||
size = raw_shm_splited[1].strip()
|
||||
int_size = int(size) * 0x100000
|
||||
total_shm_size += int_size
|
||||
except Exception as e:
|
||||
print(e)
|
||||
hv_ram_size += total_shm_size
|
||||
assert(hv_ram_size <= HV_RAM_SIZE_MAX)
|
||||
|
||||
# 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
|
||||
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
|
||||
|
||||
common.append_node("/acrn-config/hv/MEMORY/HV_RAM_START", hex(hv_start_addr), allocation_etree)
|
||||
common.append_node("/acrn-config/hv/MEMORY/HV_RAM_SIZE", hex(hv_ram_size), allocation_etree)
|
41
misc/acrn-config/static_allocators/main.py
Executable file
41
misc/acrn-config/static_allocators/main.py
Executable file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2021 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
import sys, os
|
||||
import lxml.etree
|
||||
import argparse
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library'))
|
||||
import common
|
||||
from importlib import import_module
|
||||
|
||||
def main(args):
|
||||
# Initialize configuration libraries for backward compatibility
|
||||
common.BOARD_INFO_FILE = args.board
|
||||
common.SCENARIO_INFO_FILE = args.scenario
|
||||
common.get_vm_num(args.scenario)
|
||||
common.get_vm_types()
|
||||
|
||||
scripts_path = os.path.dirname(os.path.realpath(__file__))
|
||||
current = os.path.basename(__file__)
|
||||
|
||||
board_etree = lxml.etree.parse(args.board)
|
||||
scenario_etree = lxml.etree.parse(args.scenario)
|
||||
allocation_etree = lxml.etree.ElementTree(element=lxml.etree.fromstring("<acrn-config></acrn-config>"))
|
||||
for script in [f for f in os.listdir(scripts_path) if f.endswith(".py") and f != current]:
|
||||
module_name = os.path.splitext(script)[0]
|
||||
module = import_module(f"{module_name}")
|
||||
module.fn(board_etree, scenario_etree, allocation_etree)
|
||||
allocation_etree.write(args.output, pretty_print=True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--board", help="the XML file summarizing characteristics of the target board")
|
||||
parser.add_argument("--scenario", help="the XML file specifying the scenario to be set up")
|
||||
parser.add_argument("--output", help="location of the output XML")
|
||||
args = parser.parse_args()
|
||||
|
||||
main(args)
|
Loading…
Reference in New Issue
Block a user