config_tools: acpi_gen: generate vRTCT instead of copying a physical one

As the last step to simplify the steps to enable software SRAM passthrough
to a pre-launched RT VM, this patch generates a virtual RTCT which only
contains a compatibility entry (to indicate that the format of the RTCT is
v2) and a couple of SSRAM or SSRAM waymask entries to report the software
SRAM blocks that pre-launched VM has access. That follows the practice how
ACRN device model generates virtual RTCT for post-launched VMs today.

In case RTCT v1 is used physically, this patch still generates a v2 RTCT
for the pre-launched VM but does not add an SSRAM waymask entry there
due to lack of information.

Tracked-On: #7947
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Junjie Mao 2022-07-29 23:18:13 +08:00 committed by acrnsi-robot
parent eff353700e
commit 4369896549
4 changed files with 91 additions and 14 deletions

View File

@ -15,7 +15,7 @@ TEMPLATE_ACPI_PATH = os.path.join(VM_CONFIGS_PATH, 'acpi_template', 'template')
ACPI_TABLE_LIST = [('rsdp.asl', 'rsdp.aml'), ('xsdt.asl', 'xsdt.aml'), ('facp.asl', 'facp.aml'),
('mcfg.asl', 'mcfg.aml'), ('apic.asl', 'apic.aml'), ('tpm2.asl', 'tpm2.aml'),
('dsdt.aml', 'dsdt.aml'), ('PTCT', 'ptct.aml'), ('RTCT', 'rtct.aml')]
('dsdt.aml', 'dsdt.aml'), ('ptct.aml', 'ptct.aml'), ('rtct.aml', 'rtct.aml')]
ACPI_BASE = 0x7fe00000
@ -49,5 +49,3 @@ ACPI_MADT_TYPE_LOCAL_APIC_NMI = 4
TSN_DEVICE_LIST = ['8086:4ba0',
'8086:4bb0',
'8086:4b32']
RTCT = ['RTCT', 'PTCT']

View File

@ -12,6 +12,8 @@ import collections
import lxml.etree
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'board_inspector'))
from acpiparser._utils import TableHeader
from acpiparser import rtct
from acpiparser import rdt
from acpiparser.dsdt import parse_tree
from acpiparser.aml import builder
@ -764,6 +766,87 @@ def gen_dsdt(board_etree, scenario_etree, allocation_etree, vm_id, dest_path):
dest.write(binary)
def gen_rtct(board_etree, scenario_etree, allocation_etree, vm_id, dest_path):
def cpu_id_to_lapic_id(cpu_id):
return common.get_node(f"//thread[cpu_id = '{cpu_id}']/apic_id/text()", board_etree)
vm_node = common.get_node(f"//vm[@id='{vm_id}']", scenario_etree)
if vm_node is None:
return False
vcpus = ",".join(map(cpu_id_to_lapic_id, vm_node.xpath("cpu_affinity//pcpu_id/text()")))
rtct_entries = []
# ACPI table header
common_header = create_object(
TableHeader,
signature = b'RTCT',
revision = 1,
oemid = b'ACRN ',
oemtableid = b'ACRNRTCT',
oemrevision = 5,
creatorid = b'INTL',
creatorrevision = 0x100000d
)
rtct_entries.append(common_header)
# Compatibility entry
compat_entry = create_object(
rtct.RTCTSubtableCompatibility,
subtable_size = ctypes.sizeof(rtct.RTCTSubtableCompatibility),
format_or_version = 1,
type = rtct.ACPI_RTCT_TYPE_COMPATIBILITY,
rtct_version_major = 2,
rtct_version_minor = 0,
rtcd_version_major = 0,
rtcd_version_minor = 0
)
rtct_entries.append(compat_entry)
# SSRAM entries
# Look for the cache blocks that are visible to this VM and have software SRAM in it. Those software SRAM will be
# exposed to the VM in RTCT.
for cache in board_etree.xpath(f"//caches/cache[count(processors/processor[contains('{vcpus}', .)]) and capability[@id = 'Software SRAM']]"):
ssram_cap = common.get_node("capability[@id = 'Software SRAM']", cache)
ssram_entry = create_object(
rtct.RTCTSubtableSoftwareSRAM_v2,
subtable_size = ctypes.sizeof(rtct.RTCTSubtableSoftwareSRAM_v2),
format_or_version = 2,
type = rtct.ACPI_RTCT_V2_TYPE_SoftwareSRAM,
level = int(cache.get("level")),
cache_id = int(cache.get("id"), base=16),
base = int(ssram_cap.find("start").text, base=16),
size = int(ssram_cap.find("size").text),
shared = 0
)
rtct_entries.append(ssram_entry)
if ssram_cap.find("waymask") is not None:
ssram_waymask_entry = create_object(
rtct.RTCTSubtableSSRAMWayMask,
subtable_size = ctypes.sizeof(rtct.RTCTSubtableSSRAMWayMask),
format_or_version = 1,
type = rtct.ACPI_RTCT_V2_TYPE_SSRAM_WayMask,
level = int(cache.get("level")),
cache_id = int(cache.get("id"), base=16),
waymask = int(ssram_cap.find("waymask").text, base=16)
)
rtct_entries.append(ssram_waymask_entry)
with open(dest_path, "wb") as dest:
length = sum(map(ctypes.sizeof, rtct_entries))
common_header.length = length
binary = bytearray().join(map(bytearray, rtct_entries))
checksum = (256 - (sum(binary) % 256)) % 256
binary[9] = checksum
dest.write(binary)
def main(args):
err_dic = {}
@ -846,12 +929,8 @@ def main(args):
if not os.path.isdir(dest_vm_acpi_path):
os.makedirs(dest_vm_acpi_path)
if PASSTHROUGH_RTCT is True and vm_id == PRELAUNCHED_RTVM_ID:
for f in RTCT:
if os.path.isfile(os.path.join(VM_CONFIGS_PATH, 'acpi_template', board_type, f)):
passthru_devices.append(f)
shutil.copy(os.path.join(VM_CONFIGS_PATH, 'acpi_template', board_type, f),
dest_vm_acpi_path)
break
passthru_devices.append("RTCT")
gen_rtct(board_etree, scenario_etree, allocation_etree, vm_id, os.path.join(dest_vm_acpi_path, "rtct.aml"))
gen_rsdp(dest_vm_acpi_path)
gen_xsdt(dest_vm_acpi_path, passthru_devices)
gen_fadt(dest_vm_acpi_path, board_root)

View File

@ -70,7 +70,7 @@ def asl_to_aml(dest_vm_acpi_path, dest_vm_acpi_bin_path, scenario_etree, allocat
os.remove(os.path.join(dest_vm_acpi_path, acpi_table[1]))
rmsg = 'failed to compile {}'.format(acpi_table[0])
break
elif acpi_table[0] in ['PTCT', 'RTCT']:
elif acpi_table[0] in ['ptct.aml', 'rtct.aml']:
if acpi_table[0] in os.listdir(dest_vm_acpi_path):
rtct = acpiparser.rtct.RTCT(os.path.join(dest_vm_acpi_path, acpi_table[0]))
outfile = os.path.join(dest_vm_acpi_bin_path, acpi_table[1])
@ -95,7 +95,7 @@ def asl_to_aml(dest_vm_acpi_path, dest_vm_acpi_bin_path, scenario_etree, allocat
os.remove(os.path.join(dest_vm_acpi_path, acpi_table[1]))
rmsg = 'failed to compile {}'.format(acpi_table[0])
break
elif acpi_table[0].endswith(".aml"):
elif acpi_table[0].endswith(".aml") and acpi_table[0] in os.listdir(dest_vm_acpi_path):
shutil.copy(os.path.join(dest_vm_acpi_path, acpi_table[0]),
os.path.join(dest_vm_acpi_bin_path, acpi_table[1]))
@ -171,11 +171,11 @@ def aml_to_bin(dest_vm_acpi_path, dest_vm_acpi_bin_path, acpi_bin_name, board_et
with open(os.path.join(dest_vm_acpi_bin_path, ACPI_TABLE_LIST[6][1]), 'rb') as asl:
acpi_bin.write(asl.read())
if 'PTCT' in os.listdir(dest_vm_acpi_path):
if ACPI_TABLE_LIST[7][1] in os.listdir(dest_vm_acpi_path):
acpi_bin.seek(ACPI_RTCT_ADDR_OFFSET)
with open(os.path.join(dest_vm_acpi_bin_path, ACPI_TABLE_LIST[7][1]), 'rb') as asl:
acpi_bin.write(asl.read())
elif 'RTCT' in os.listdir(dest_vm_acpi_path):
elif ACPI_TABLE_LIST[8][1] in os.listdir(dest_vm_acpi_path):
acpi_bin.seek(ACPI_RTCT_ADDR_OFFSET)
with open(os.path.join(dest_vm_acpi_bin_path, ACPI_TABLE_LIST[8][1]), 'rb') as asl:
acpi_bin.write(asl.read())

View File

@ -30,7 +30,7 @@ SMALL_RESOURCE_ITEM_END_TAG = 0x0F
# 6.4.2.1 IRQ Descriptor
def SmallResourceItemIRQ_factory(_len):
def SmallResourceItemIRQ_factory(_len=2):
class SmallResourceItemIRQ(cdata.Struct):
_pack_ = 1
_fields_ = SmallResourceDataTag._fields_ + [