/* data is needed to prevent a pointer cast on 32bit */
unsigned long data;
+ ASSERT(!bridge == !is_hardware_domain(v->domain));
+
if ( vpci_ecam_read(sbdf, ECAM_REG_OFFSET(info->gpa),
1U << info->dabt.size, &data) )
{
struct pci_host_bridge *bridge = p;
pci_sbdf_t sbdf = vpci_sbdf_from_gpa(bridge, info->gpa);
+ ASSERT(!bridge == !is_hardware_domain(v->domain));
+
return vpci_ecam_write(sbdf, ECAM_REG_OFFSET(info->gpa),
1U << info->dabt.size, r);
}
}
#endif /* __XEN__ */
+/*
+ * Find the physical device which is mapped to the virtual device
+ * and translate virtual SBDF to the physical one.
+ */
+static const struct pci_dev *translate_virtual_device(const struct domain *d,
+ pci_sbdf_t *sbdf)
+{
+#ifdef CONFIG_HAS_VPCI_GUEST_SUPPORT
+ const struct pci_dev *pdev;
+
+ ASSERT(!is_hardware_domain(d));
+ ASSERT(rw_is_locked(&d->pci_lock));
+
+ for_each_pdev ( d, pdev )
+ {
+ if ( pdev->vpci && (pdev->vpci->guest_sbdf.sbdf == sbdf->sbdf) )
+ {
+ /* Replace guest SBDF with the physical one. */
+ *sbdf = pdev->sbdf;
+ return pdev;
+ }
+ }
+#else /* !CONFIG_HAS_VPCI_GUEST_SUPPORT */
+ ASSERT_UNREACHABLE();
+#endif /* CONFIG_HAS_VPCI_GUEST_SUPPORT */
+
+ return NULL;
+}
+
static int vpci_register_cmp(const struct vpci_register *r1,
const struct vpci_register *r2)
{
* pci_lock is sufficient.
*/
read_lock(&d->pci_lock);
- pdev = pci_get_pdev(d, sbdf);
- if ( !pdev && is_hardware_domain(d) )
- pdev = pci_get_pdev(dom_xen, sbdf);
+ if ( is_hardware_domain(d) )
+ {
+ pdev = pci_get_pdev(d, sbdf);
+ if ( !pdev )
+ pdev = pci_get_pdev(dom_xen, sbdf);
+ }
+ else
+ pdev = translate_virtual_device(d, &sbdf);
+
if ( !pdev || !pdev->vpci )
{
read_unlock(&d->pci_lock);
* are modifying BARs, so there is a room for improvement.
*/
write_lock(&d->pci_lock);
- pdev = pci_get_pdev(d, sbdf);
- if ( !pdev && is_hardware_domain(d) )
- pdev = pci_get_pdev(dom_xen, sbdf);
+ if ( is_hardware_domain(d) )
+ {
+ pdev = pci_get_pdev(d, sbdf);
+ if ( !pdev )
+ pdev = pci_get_pdev(dom_xen, sbdf);
+ }
+ else
+ pdev = translate_virtual_device(d, &sbdf);
+
if ( !pdev || !pdev->vpci )
{
/* Ignore writes to read-only devices, which have no ->vpci. */