From db7be2c6f6a2a4affb900ad8dcc418022466a3c5 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 21 Sep 2022 13:13:17 +0800 Subject: [PATCH] ACRN:DM:PCI: Add the emulation of PCI rom bar register for passthru device The pci_reg 0x30 of PCI config_space is used to check whether the PCI rom bar is supported. When the PCI rom is supported for the device in guest vm, the 0x30 pci_reg is emulated and it can return the addr/enable bit. Tracked-On: #8175 Signed-off-by: Zhao Yakui Acked-by: Yu Wang --- devicemodel/hw/pci/passthrough.c | 39 +++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/devicemodel/hw/pci/passthrough.c b/devicemodel/hw/pci/passthrough.c index 13acf494c..f8067724d 100644 --- a/devicemodel/hw/pci/passthrough.c +++ b/devicemodel/hw/pci/passthrough.c @@ -841,6 +841,13 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts) passthru_gpu_dsm_opregion(ctx, ptdev, &pcidev, device); } + if (ptdev->need_rombar) { + /* When the rombar is enabled, the access to + * pci 0x30 reg will be emulated in DM. + * So this will provide one hint for hypervisor. + */ + pcidev.type = ACRN_PTDEV_QUIRK_ASSIGN; + } pcidev.virt_bdf = PCI_BDF(dev->bus, dev->slot, dev->func); pcidev.phys_bdf = ptdev->phys_bdf; for (idx = 0; idx <= PCI_BARMAX; idx++) { @@ -995,7 +1002,9 @@ passthru_cfgread(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, { struct passthru_dev *ptdev = dev->arg; - if (ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff)) + if (coff == PCIR_BIOS) { + *rv = pci_get_cfgdata32(dev, coff); + } else if (ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff)) *rv = pci_get_cfgdata32(dev, coff); else *rv = read_config(ptdev->phys_dev, coff, bytes); @@ -1008,9 +1017,33 @@ passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, int coff, int bytes, uint32_t val) { struct passthru_dev *ptdev = dev->arg; + uint32_t bios_rom; - if (!(ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff))) - write_config(ptdev->phys_dev, coff, bytes, val); + if (coff == PCIR_BIOS) { + + if ((val & PCIM_BIOS_ADDR_MASK) == PCIM_BIOS_ADDR_MASK) { + /* size is returned by read after writing 0xFFFFF800. + * And format is ~(size - 1). + */ + bios_rom = (uint32_t) dev->bar[PCI_ROMBAR].size; + bios_rom = ~(bios_rom - 1); + pci_set_cfgdata32(dev, PCIR_BIOS, bios_rom); + } else if (val == 0) { + /* restore the zero if ROM_Bar is not supported */ + pci_set_cfgdata32(dev, PCIR_BIOS, val); + } else { + /* restore the original addr into PCI_ROM bar. + * force to update the original addr as remapping is not supported. + */ + bios_rom = (uint32_t) dev->bar[PCI_ROMBAR].addr; + pci_set_cfgdata32(dev, PCIR_BIOS, (bios_rom | PCIR_BIOS)); + pr_dbg("Restore %x into ROM of %d:%d.%d\n", + val, dev->bus, dev->slot, dev->func); + } + } else { + if (!(ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff))) + write_config(ptdev->phys_dev, coff, bytes, val); + } return 0; }