vpci/rebar: Implement cleanup function for Rebar

When Rebar initialization fails, vPCI hides the capability, but
removing handlers and datas won't be performed until the device is
deassigned. So, implement Rebar cleanup hook that will be called to
cleanup Rebar related handlers and free it's associated data when
initialization fails.

Signed-off-by: Jiqian Chen <Jiqian.Chen@amd.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
This commit is contained in:
Jiqian Chen authored and Roger Pau Monne committed 2026-02-02 13:05:27 +01:00
1 parent d0f94a0d40
commit ee459aeac0
1 file changed
+54 -9
+54 -9
View File
@@ -49,6 +49,58 @@ static void cf_check rebar_ctrl_write(const struct pci_dev *pdev,
bar->guest_addr = bar->addr;
}
static int cf_check cleanup_rebar(const struct pci_dev *pdev, bool hide)
{
int rc;
uint32_t ctrl;
unsigned int nbars;
unsigned int rebar_offset = pci_find_ext_capability(pdev,
PCI_EXT_CAP_ID_REBAR);
if ( !hide )
return 0;
ctrl = pci_conf_read32(pdev->sbdf, rebar_offset + PCI_REBAR_CTRL(0));
nbars = MASK_EXTR(ctrl, PCI_REBAR_CTRL_NBAR_MASK);
rc = vpci_remove_registers(pdev->vpci, rebar_offset + PCI_REBAR_CAP(0),
PCI_REBAR_CTRL(nbars - 1));
if ( rc )
{
printk(XENLOG_ERR "%pd %pp: fail to remove Rebar handlers rc=%d\n",
pdev->domain, &pdev->sbdf, rc);
ASSERT_UNREACHABLE();
return rc;
}
/*
* Unprivileged domains have a deny by default register access policy, no
* need to add any further handlers for them.
*/
if ( !is_hardware_domain(pdev->domain) )
return 0;
/*
* The driver may not traverse the capability list and think device
* supports Rebar by default. So here let the control register of Rebar
* be Read-Only is to ensure Rebar disabled.
*/
for ( unsigned int i = 0; i < nbars; i++ )
{
rc = vpci_add_register(pdev->vpci, vpci_hw_read32, NULL,
rebar_offset + PCI_REBAR_CTRL(i), 4, NULL);
if ( rc )
{
printk(XENLOG_ERR
"%pd %pp: fail to add Rebar ctrl handler rc=%d\n",
pdev->domain, &pdev->sbdf, rc);
return rc;
}
}
return 0;
}
static int cf_check init_rebar(struct pci_dev *pdev)
{
uint32_t ctrl;
@@ -97,14 +149,7 @@ static int cf_check init_rebar(struct pci_dev *pdev)
{
printk(XENLOG_ERR "%pd %pp: BAR%u fail to add reg of REBAR_CTRL rc=%d\n",
pdev->domain, &pdev->sbdf, index, rc);
/*
* Ideally we would hide the ReBar capability on error, but code
* for doing so still needs to be written. Use continue instead
* to keep any already setup register hooks, as returning an
* error will cause the hardware domain to get unmediated access
* to all device registers.
*/
continue;
return rc;
}
bar->resizable_sizes =
@@ -118,7 +163,7 @@ static int cf_check init_rebar(struct pci_dev *pdev)
return 0;
}
REGISTER_VPCI_EXTCAP(REBAR, init_rebar, NULL);
REGISTER_VPCI_EXTCAP(REBAR, init_rebar, cleanup_rebar);
/*
* Local variables:
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.