mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
vpci/header: Move emulating cap list logic into new function
No functional changes. Follow-on changes will benifit from this. Signed-off-by: Jiqian Chen <Jiqian.Chen@amd.com> Acked-by: Roger Pau Monné <roger.pau@citrix.com>
This commit is contained in:
1 parent
8e8ffba487
commit
b64f9ee695
1 file changed
+73
-65
+73
-65
@@ -754,6 +754,75 @@ static int bar_add_rangeset(const struct pci_dev *pdev, struct vpci_bar *bar,
|
||||
return !bar->mem ? -ENOMEM : 0;
|
||||
}
|
||||
|
||||
static int vpci_init_capability_list(struct pci_dev *pdev)
|
||||
{
|
||||
int rc;
|
||||
bool mask_cap_list = false;
|
||||
|
||||
if ( !is_hardware_domain(pdev->domain) &&
|
||||
pci_conf_read16(pdev->sbdf, PCI_STATUS) & PCI_STATUS_CAP_LIST )
|
||||
{
|
||||
/* Only expose capabilities to the guest that vPCI can handle. */
|
||||
unsigned int next, ttl = 48;
|
||||
static const unsigned int supported_caps[] = {
|
||||
PCI_CAP_ID_MSI,
|
||||
PCI_CAP_ID_MSIX,
|
||||
};
|
||||
|
||||
next = pci_find_next_cap_ttl(pdev->sbdf, PCI_CAPABILITY_LIST,
|
||||
supported_caps,
|
||||
ARRAY_SIZE(supported_caps), &ttl);
|
||||
|
||||
rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL,
|
||||
PCI_CAPABILITY_LIST, 1,
|
||||
(void *)(uintptr_t)next);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
next &= ~3;
|
||||
|
||||
if ( !next )
|
||||
/*
|
||||
* If we don't have any supported capabilities to expose to the
|
||||
* guest, mask the PCI_STATUS_CAP_LIST bit in the status
|
||||
* register.
|
||||
*/
|
||||
mask_cap_list = true;
|
||||
|
||||
while ( next && ttl )
|
||||
{
|
||||
unsigned int pos = next;
|
||||
|
||||
next = pci_find_next_cap_ttl(pdev->sbdf,
|
||||
pos + PCI_CAP_LIST_NEXT,
|
||||
supported_caps,
|
||||
ARRAY_SIZE(supported_caps), &ttl);
|
||||
|
||||
rc = vpci_add_register(pdev->vpci, vpci_hw_read8, NULL,
|
||||
pos + PCI_CAP_LIST_ID, 1, NULL);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL,
|
||||
pos + PCI_CAP_LIST_NEXT, 1,
|
||||
(void *)(uintptr_t)next);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
next &= ~3;
|
||||
}
|
||||
}
|
||||
|
||||
/* Utilize rsvdp_mask to hide PCI_STATUS_CAP_LIST from the guest. */
|
||||
return vpci_add_register_mask(pdev->vpci, vpci_hw_read16, vpci_hw_write16,
|
||||
PCI_STATUS, 2, NULL,
|
||||
PCI_STATUS_RO_MASK &
|
||||
~(mask_cap_list ? PCI_STATUS_CAP_LIST : 0),
|
||||
PCI_STATUS_RW1C_MASK,
|
||||
mask_cap_list ? PCI_STATUS_CAP_LIST : 0,
|
||||
PCI_STATUS_RSVDZ_MASK);
|
||||
}
|
||||
|
||||
static int cf_check init_header(struct pci_dev *pdev)
|
||||
{
|
||||
uint16_t cmd;
|
||||
@@ -762,7 +831,6 @@ static int cf_check init_header(struct pci_dev *pdev)
|
||||
struct vpci_header *header = &pdev->vpci->header;
|
||||
struct vpci_bar *bars = header->bars;
|
||||
int rc;
|
||||
bool mask_cap_list = false;
|
||||
bool is_hwdom = is_hardware_domain(pdev->domain);
|
||||
|
||||
ASSERT(rw_is_write_locked(&pdev->domain->pci_lock));
|
||||
@@ -803,61 +871,12 @@ static int cf_check init_header(struct pci_dev *pdev)
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
rc = vpci_init_capability_list(pdev);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
if ( !is_hwdom )
|
||||
{
|
||||
if ( pci_conf_read16(pdev->sbdf, PCI_STATUS) & PCI_STATUS_CAP_LIST )
|
||||
{
|
||||
/* Only expose capabilities to the guest that vPCI can handle. */
|
||||
unsigned int next, ttl = 48;
|
||||
static const unsigned int supported_caps[] = {
|
||||
PCI_CAP_ID_MSI,
|
||||
PCI_CAP_ID_MSIX,
|
||||
};
|
||||
|
||||
next = pci_find_next_cap_ttl(pdev->sbdf, PCI_CAPABILITY_LIST,
|
||||
supported_caps,
|
||||
ARRAY_SIZE(supported_caps), &ttl);
|
||||
|
||||
rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL,
|
||||
PCI_CAPABILITY_LIST, 1,
|
||||
(void *)(uintptr_t)next);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
next &= ~3;
|
||||
|
||||
if ( !next )
|
||||
/*
|
||||
* If we don't have any supported capabilities to expose to the
|
||||
* guest, mask the PCI_STATUS_CAP_LIST bit in the status
|
||||
* register.
|
||||
*/
|
||||
mask_cap_list = true;
|
||||
|
||||
while ( next && ttl )
|
||||
{
|
||||
unsigned int pos = next;
|
||||
|
||||
next = pci_find_next_cap_ttl(pdev->sbdf,
|
||||
pos + PCI_CAP_LIST_NEXT,
|
||||
supported_caps,
|
||||
ARRAY_SIZE(supported_caps), &ttl);
|
||||
|
||||
rc = vpci_add_register(pdev->vpci, vpci_hw_read8, NULL,
|
||||
pos + PCI_CAP_LIST_ID, 1, NULL);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL,
|
||||
pos + PCI_CAP_LIST_NEXT, 1,
|
||||
(void *)(uintptr_t)next);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
next &= ~3;
|
||||
}
|
||||
}
|
||||
|
||||
/* Extended capabilities read as zero, write ignore */
|
||||
rc = vpci_add_register(pdev->vpci, vpci_read_val, NULL, 0x100, 4,
|
||||
(void *)0);
|
||||
@@ -865,17 +884,6 @@ static int cf_check init_header(struct pci_dev *pdev)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Utilize rsvdp_mask to hide PCI_STATUS_CAP_LIST from the guest. */
|
||||
rc = vpci_add_register_mask(pdev->vpci, vpci_hw_read16, vpci_hw_write16,
|
||||
PCI_STATUS, 2, NULL,
|
||||
PCI_STATUS_RO_MASK &
|
||||
~(mask_cap_list ? PCI_STATUS_CAP_LIST : 0),
|
||||
PCI_STATUS_RW1C_MASK,
|
||||
mask_cap_list ? PCI_STATUS_CAP_LIST : 0,
|
||||
PCI_STATUS_RSVDZ_MASK);
|
||||
if ( rc )
|
||||
return rc;
|
||||
|
||||
if ( pdev->ignore_bars )
|
||||
return 0;
|
||||
|
||||
|
||||