[PATCH v3 1/5] ACRN:DM:PCI: Add the support of allocating resource for PCI ROM bar


Zhao, Yakui
 

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.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
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,
--
2.25.1


Yu Wang
 

Acked-by: Wang, Yu1 <yu1.wang@...>

On Tue, Sep 20, 2022 at 09:56:48AM +0800, Zhao Yakui wrote:
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.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
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,
--
2.25.1