config_tools: add PnP uart and rtc for pre-launched VM

In commit of 7cc9c8fe06
the pre-launched VM was set to ACPI HW Reduced platform, then the IRQ
would be allocated from 0 for PCI MSI devices. The Intel igb/igc driver
might get IRQ 8 when do request irq which would conflict with the irq
of RTC device:
    [ 14.264954] genirq: Flags mismatch irq 8. 00000000 (enp0s8-TxRx-3) vs.
                 00000000 (rtc0)
    [ 14.265411] ------------[ cut here ]------------
    [ 14.265508] kernel BUG at drivers/pci/msi.c:376!
    [ 14.265610] invalid opcode: 0000 [#1] PREEMPT SMP
    [ 14.265710] CPU: 0 PID: 296 Comm: connmand Not tainted 5.10.52-acrn-sos
                 -dirty #72
    [ 14.265863] RIP: 0010:free_msi_irqs+0x182/0x1b0

This patch will specify some legacy PnP device like UART and RTC in ACPI
DSDT table of pre-launched VM, so that IRQs from IOAPIC pin 4/3/8 could be
preserved before MSI device requesting IRQs.

Tracked-On: #6704

Signed-off-by: Victor Sun <victor.sun@intel.com>
This commit is contained in:
Victor Sun 2021-10-22 13:10:30 +08:00 committed by wenlingz
parent 4ca2b3a860
commit b80b1dde25

View File

@ -455,6 +455,108 @@ def gen_root_pci_bus(path, prt_packages):
return tree
def pnp_uart(path, uid, ddn, port, irq):
resources = []
cls = rdt.SmallResourceItemIOPort
length = ctypes.sizeof(cls)
data = bytearray(length)
res = cls.from_buffer(data)
res.type = 0
res.name = rdt.SMALL_RESOURCE_ITEM_IO_PORT
res.length = 7
res._DEC = 1
res._MIN = port
res._MAX = port
res._ALN = 1
res._LEN = 8
resources.append(data)
cls = rdt.SmallResourceItemIRQ_factory(2)
length = ctypes.sizeof(cls)
data = bytearray(length)
res = cls.from_buffer(data)
res.type = 0
res.name = rdt.SMALL_RESOURCE_ITEM_IRQ_FORMAT
res.length = 2
res._INT = 1 << irq
resources.append(data)
resources.append(bytes([0x79, 0]))
resource_buf = bytearray().join(resources)
checksum = (256 - (sum(resource_buf) % 256)) % 256
resource_buf[-1] = checksum
uart = builder.DefDevice(
builder.PkgLength(),
path,
builder.TermList(
builder.DefName(
"_HID",
builder.DWordConst(encode_eisa_id("PNP0501"))),
builder.DefName(
"_UID",
builder.build_value(uid)),
builder.DefName(
"_DDN",
builder.String(ddn)),
builder.DefName(
"_CRS",
builder.DefBuffer(
builder.PkgLength(),
builder.WordConst(len(resource_buf)),
builder.ByteList(resource_buf)))))
return uart
def pnp_rtc(path):
resources = []
cls = rdt.SmallResourceItemIOPort
length = ctypes.sizeof(cls)
data = bytearray(length)
res = cls.from_buffer(data)
res.type = 0
res.name = rdt.SMALL_RESOURCE_ITEM_IO_PORT
res.length = 7
res._DEC = 1
res._MIN = 0x70
res._MAX = 0x70
res._ALN = 1
res._LEN = 8
resources.append(data)
cls = rdt.SmallResourceItemIRQ_factory(2)
length = ctypes.sizeof(cls)
data = bytearray(length)
res = cls.from_buffer(data)
res.type = 0
res.name = rdt.SMALL_RESOURCE_ITEM_IRQ_FORMAT
res.length = 2
res._INT = 1 << 8
resources.append(data)
resources.append(bytes([0x79, 0]))
resource_buf = bytearray().join(resources)
checksum = (256 - (sum(resource_buf) % 256)) % 256
resource_buf[-1] = checksum
rtc = builder.DefDevice(
builder.PkgLength(),
path,
builder.TermList(
builder.DefName(
"_HID",
builder.DWordConst(encode_eisa_id("PNP0B00"))),
builder.DefName(
"_CRS",
builder.DefBuffer(
builder.PkgLength(),
builder.WordConst(len(resource_buf)),
builder.ByteList(resource_buf)))))
return rtc
def collect_dependent_devices(board_etree, device_node):
types_in_scope = ["uses", "is used by", "consumes resources from"]
result = set()
@ -635,6 +737,19 @@ def gen_dsdt(board_etree, scenario_etree, allocation_etree, vm_id, dest_path):
builder.build_value(0))))
objects.add_object("\\", s5_object)
rtvm = False
for guest_flag in scenario_etree.xpath(f"//vm[@id='{vm_id}']/guest_flags/guest_flag/text()"):
if guest_flag == 'GUEST_FLAG_LAPIC_PASSTHROUGH':
rtvm = True
break
# RTVM cannot set IRQ because no INTR is sent with LAPIC PT
if rtvm is False:
objects.add_object("\\_SB_", pnp_uart("UAR0", 0, "COM1", 0x3f8, 4))
objects.add_object("\\_SB_", pnp_uart("UAR1", 1, "COM2", 0x2f8, 3))
objects.add_object("\\_SB_", pnp_rtc("RTC0"))
amlcode = builder.AMLCode(header, *objects.get_term_list())
with open(dest_path, "wb") as dest:
visitor = GenerateBinaryVisitor()