check_cleanup_domid_map(domain, pdev, iommu);
printk(XENLOG_ERR
"%04x:%02x:%02x.%u: unexpected context entry %016lx_%016lx (expected %016lx_%016lx)\n",
- pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+ seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
(uint64_t)(res >> 64), (uint64_t)res,
(uint64_t)(old >> 64), (uint64_t)old);
rc = -EILSEQ;
if ( rc )
{
- if ( !prev_dom )
- ret = domain_context_unmap_one(domain, iommu, bus, devfn,
- DEVICE_DOMID(domain, pdev));
+ if ( !prev_dom ||
+ /*
+ * Unmapping here means DEV_TYPE_PCI devices with RMRRs (if such
+ * exist) would cause problems if such a region was actually
+ * accessed.
+ */
+ (prev_dom == dom_io && !pdev) )
+ ret = domain_context_unmap_one(domain, iommu, bus, devfn);
else if ( prev_dom != domain ) /* Avoid infinite recursion. */
ret = domain_context_mapping_one(prev_dom, iommu, bus, devfn, pdev,
DEVICE_DOMID(prev_dom, pdev),
* Strictly speaking if the device is the only one behind this bridge
* and the only one with this (secbus,0,0) tuple, it could be allowed
* to be re-assigned regardless of RMRR presence. But let's deal with
- * that case only if it is actually found in the wild.
+ * that case only if it is actually found in the wild. Note that
+ * dealing with this just here would still not render the operation
+ * secure.
*/
else if ( prev_present && (mode & MAP_WITH_RMRR) &&
domain != pdev->domain )
int domain_context_unmap_one(
struct domain *domain,
struct vtd_iommu *iommu,
- uint8_t bus, uint8_t devfn, domid_t domid)
+ uint8_t bus, uint8_t devfn)
{
struct context_entry *context, *context_entries;
u64 maddr;
unmap_vtd_domain_page(context_entries);
if ( !iommu->drhd->segment && !rc )
- rc = me_wifi_quirk(domain, bus, devfn, domid, 0, UNMAP_ME_PHANTOM_FUNC);
+ rc = me_wifi_quirk(domain, bus, devfn, DOMID_INVALID, 0,
+ UNMAP_ME_PHANTOM_FUNC);
if ( rc && !is_hardware_domain(domain) && domain != dom_io )
{
printk(VTDPREFIX "d%d:PCIe: unmap %04x:%02x:%02x.%u\n",
domain->domain_id, seg, bus,
PCI_SLOT(devfn), PCI_FUNC(devfn));
- ret = domain_context_unmap_one(domain, iommu, bus, devfn,
- DEVICE_DOMID(domain, pdev));
+ ret = domain_context_unmap_one(domain, iommu, bus, devfn);
if ( !ret && devfn == pdev->devfn && ats_device(pdev, drhd) > 0 )
disable_ats_device(pdev);
if ( iommu_debug )
printk(VTDPREFIX "d%d:PCI: unmap %04x:%02x:%02x.%u\n",
domain->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
- ret = domain_context_unmap_one(domain, iommu, bus, devfn,
- DEVICE_DOMID(domain, pdev));
+ ret = domain_context_unmap_one(domain, iommu, bus, devfn);
if ( ret )
break;
break;
}
- ret = domain_context_unmap_one(domain, iommu, tmp_bus, tmp_devfn,
- DEVICE_DOMID(domain, pdev));
+ ret = domain_context_unmap_one(domain, iommu, tmp_bus, tmp_devfn);
/* PCIe to PCI/PCIx bridge */
if ( !ret && pdev_type(seg, tmp_bus, tmp_devfn) == DEV_TYPE_PCIe2PCI_BRIDGE )
- ret = domain_context_unmap_one(domain, iommu, secbus, 0,
- DEVICE_DOMID(domain, pdev));
+ ret = domain_context_unmap_one(domain, iommu, secbus, 0);
break;