[PATCH 4/6] ACRN:DM:PCI: Add the emulation of PCI rom bar register for passthru device


Zhao, Yakui
 

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.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
devicemodel/hw/pci/passthrough.c | 34 +++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/devicemodel/hw/pci/passthrough.c b/devicemodel/hw/pci/passthrough.c
index bdac31d83..336ba1c72 100644
--- a/devicemodel/hw/pci/passthrough.c
+++ b/devicemodel/hw/pci/passthrough.c
@@ -796,6 +796,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++) {
@@ -965,7 +972,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);
@@ -978,9 +987,28 @@ 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 (coff == PCIR_BIOS) {

- if (!(ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff)))
- write_config(ptdev->phys_dev, coff, bytes, val);
+ 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 {
+ /* 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));
+ }
+ } else {
+ if (!(ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff)))
+ write_config(ptdev->phys_dev, coff, bytes, val);
+ }

return 0;
}
--
2.25.1


Yu Wang
 

On Thu, Sep 15, 2022 at 10:30:51AM +0800, Zhao, Yakui wrote:
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.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
devicemodel/hw/pci/passthrough.c | 34 +++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/devicemodel/hw/pci/passthrough.c b/devicemodel/hw/pci/passthrough.c
index bdac31d83..336ba1c72 100644
--- a/devicemodel/hw/pci/passthrough.c
+++ b/devicemodel/hw/pci/passthrough.c
@@ -796,6 +796,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++) {
@@ -965,7 +972,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);
@@ -978,9 +987,28 @@ 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 (coff == PCIR_BIOS) {

- if (!(ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff)))
- write_config(ptdev->phys_dev, coff, bytes, val);
+ 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 {
+ /* 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));
We have BAR remapping logic in pci_cfgrw. If we don't caching the ROM
bar file and change to access the physical ROMBAR, then we can re-use
the existing logic to support ROMBAR remapping, right?

+ }
+ } else {
+ if (!(ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff)))
+ write_config(ptdev->phys_dev, coff, bytes, val);
+ }

return 0;
}
--
2.25.1






Zhao, Yakui
 

On 2022/9/15 12:05, Yu Wang wrote:
On Thu, Sep 15, 2022 at 10:30:51AM +0800, Zhao, Yakui wrote:
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.

Signed-off-by: Zhao Yakui <yakui.zhao@...>
---
devicemodel/hw/pci/passthrough.c | 34 +++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/devicemodel/hw/pci/passthrough.c b/devicemodel/hw/pci/passthrough.c
index bdac31d83..336ba1c72 100644
--- a/devicemodel/hw/pci/passthrough.c
+++ b/devicemodel/hw/pci/passthrough.c
@@ -796,6 +796,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++) {
@@ -965,7 +972,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);
@@ -978,9 +987,28 @@ 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 (coff == PCIR_BIOS) {
- if (!(ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff)))
- write_config(ptdev->phys_dev, coff, bytes, val);
+ 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 {
+ /* 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));
We have BAR remapping logic in pci_cfgrw. If we don't caching the ROM
bar file and change to access the physical ROMBAR, then we can re-use
the existing logic to support ROMBAR remapping, right?
The current remap logic is mainly used for the emulated PCI devices.
For the passthru device, this is not supported as the GPA bar addr is passed and hypervisor helps to build the mapping between GPA and HPA.

For the PCI rom, the bar is emulated in ACRN-DM. In theory it can be reconfigured. In order to do so, it will have to call the ACRN_IOCTL_UNSET_MEMSEG ioctl and then ACRN_IOCTL_SET_MEMSET for the new addr.
So remapping is not supported for PCI rombar.This will be much simpler.


+ }
+ } else {
+ if (!(ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff)))
+ write_config(ptdev->phys_dev, coff, bytes, val);
+ }
return 0;
}
--
2.25.1