From 270aaf82d84e463ca96029db5241b548db23e5dd Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 21 Sep 2022 13:13:08 +0800 Subject: [PATCH] ACRN:DM:PCI: Add the support of allocating resource for PCI ROM bar Now the device model only supports the 0..5 PCI bar for PCI/PCIE devices. This tries to allocate the PCI_MEM32 resource for PCI ROM bar. V1->V2: Use the PCI_ROMBAR as bar index and PCIBAR_ROM bar type when calling the pci_emul_alloc_bar to allocate the guest physical addr for PCI ROM bar. And it will allocate the resource from PCIBAR_MEM32 region. V2->V3: Add more comments that describes the parameter of pci_emul_alloc_bar. Tracked-On: #8175 Signed-off-by: Zhao Yakui Acked-by: Wang Yu --- devicemodel/hw/pci/core.c | 36 ++++++++++++++++++++++++++++------ devicemodel/include/pci_core.h | 24 +++++++++++++++++++++-- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/devicemodel/hw/pci/core.c b/devicemodel/hw/pci/core.c index 9f6256bc6..a80dc8a1d 100644 --- a/devicemodel/hw/pci/core.c +++ b/devicemodel/hw/pci/core.c @@ -784,6 +784,23 @@ pci_emul_alloc_pbar(struct pci_vdev *pdi, int idx, uint64_t hostbase, size = 16; } + if (idx > PCI_ROMBAR) { + pr_err("%s: invalid bar number %d for PCI bar type\n", __func__, idx); + return -1; + } + if (idx == PCI_ROMBAR) { + /* + * It needs to pass the PCIBAR_ROM for PCI_ROMBAR idx. But as it + * is allocated from PCI_EMUL_MEM32 type, the internal type is + * changed to PCIBAR_MEM32 + */ + if (type != PCIBAR_ROM) { + pr_err("%s: invalid bar type %d for PCI ROM\n", + __func__, type); + return -1; + } + type = PCIBAR_MEM32; + } switch (type) { case PCIBAR_NONE: baseptr = NULL; @@ -853,13 +870,20 @@ pci_emul_alloc_pbar(struct pci_vdev *pdi, int idx, uint64_t hostbase, pdi->bar[idx].addr = addr; pdi->bar[idx].size = size; - /* Initialize the BAR register in config space */ - bar = (addr & mask) | lobits; - pci_set_cfgdata32(pdi, PCIR_BAR(idx), bar); + if (idx == PCI_ROMBAR) { + mask = PCIM_BIOS_ADDR_MASK; + bar = addr & mask; + /* enable flag will be configured later */ + pci_set_cfgdata32(pdi, PCIR_BIOS, bar); + } else { + /* Initialize the BAR register in config space */ + bar = (addr & mask) | lobits; + pci_set_cfgdata32(pdi, PCIR_BAR(idx), bar); - if (type == PCIBAR_MEM64) { - pdi->bar[idx + 1].type = PCIBAR_MEMHI64; - pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32); + if (type == PCIBAR_MEM64) { + pdi->bar[idx + 1].type = PCIBAR_MEMHI64; + pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32); + } } error = register_bar(pdi, idx); diff --git a/devicemodel/include/pci_core.h b/devicemodel/include/pci_core.h index f24bb33bf..df5e5d5b7 100644 --- a/devicemodel/include/pci_core.h +++ b/devicemodel/include/pci_core.h @@ -103,7 +103,9 @@ enum pcibar_type { PCIBAR_IO, PCIBAR_MEM32, PCIBAR_MEM64, - PCIBAR_MEMHI64 + PCIBAR_MEMHI64, + /* the type for ROM bar. It will be allocated from PCI_EMUL_MEM32 region */ + PCIBAR_ROM }; struct pcibar { @@ -135,6 +137,7 @@ enum lintr_stat { PENDING }; +#define PCI_ROMBAR (PCIR_MAX_BAR_0 + 1) /* ROM BAR index in Type 0 Header */ struct pci_vdev { struct pci_vdev_ops *dev_ops; struct vmctx *vmctx; @@ -176,7 +179,8 @@ struct pci_vdev { void *arg; /* devemu-private data */ uint8_t cfgdata[PCI_REGMAX + 1]; - struct pcibar bar[PCI_BARMAX + 1]; + /* 0..5 is used for PCI MMIO/IO bar. 6 is used for PCI ROMbar */ + struct pcibar bar[PCI_BARMAX + 2]; }; struct gsi_dev { @@ -311,6 +315,22 @@ void msicap_cfgwrite(struct pci_vdev *pi, int capoff, int offset, void msixcap_cfgwrite(struct pci_vdev *pi, int capoff, int offset, int bytes, uint32_t val); void pci_callback(void); + +/* + * @brief allocate bar region for virtual PCI device + * + * @param dev Pointer to struct pci_vdev representing virtual PCI device. + * @param idx the bar_idx for the request bar region + * @param type the region type for the request bar region + * @param size the region size for the request bar region + * It can support the allocation of bar_region for bar_idx 0..5 and + * the bar type can be PCIBAR_IO/PCIBAR_MEM32/PCIBAR_MEM64. + * It can support the allocation of ROM bar for PCI_ROMBAR and only allow + * that the bar type is PCIBAR_ROM. + * + * @Return 0 indicates that the allocation is successful. + * error indicates that it fails in the allocation of bar region. + */ int pci_emul_alloc_bar(struct pci_vdev *pdi, int idx, enum pcibar_type type, uint64_t size); int pci_emul_alloc_pbar(struct pci_vdev *pdi, int idx,