[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [v7][RFC][PATCH 13/13] xen/vtd: group assigned device with RMRR
Sometimes different devices may share RMRR range so in this case we shouldn't assign these devices into different VMs since they may have potential leakage even damage between VMs. So we need to group all devices as RMRR range to make sure they are just assigned into the same VM. Here we introduce two field, gid and domid, in struct, acpi_rmrr_unit: gid: indicate which group this device owns. "0" is invalid so just start from "1". domid: indicate which domain this device owns currently. Firstly the hardware domain should own it. Signed-off-by: Tiejun Chen <tiejun.chen@xxxxxxxxx> --- xen/drivers/passthrough/vtd/dmar.c | 29 +++++++++++++++- xen/drivers/passthrough/vtd/dmar.h | 2 ++ xen/drivers/passthrough/vtd/iommu.c | 68 +++++++++++++++++++++++++++++++++---- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c index 141e735..546eca9 100644 --- a/xen/drivers/passthrough/vtd/dmar.c +++ b/xen/drivers/passthrough/vtd/dmar.c @@ -572,10 +572,11 @@ acpi_parse_one_rmrr(struct acpi_dmar_header *header) { struct acpi_dmar_reserved_memory *rmrr = container_of(header, struct acpi_dmar_reserved_memory, header); - struct acpi_rmrr_unit *rmrru; + struct acpi_rmrr_unit *rmrru, *cur_rmrr; void *dev_scope_start, *dev_scope_end; u64 base_addr = rmrr->base_address, end_addr = rmrr->end_address; int ret; + static unsigned int group_id = 0; if ( (ret = acpi_dmar_check_length(header, sizeof(*rmrr))) != 0 ) return ret; @@ -611,6 +612,8 @@ acpi_parse_one_rmrr(struct acpi_dmar_header *header) rmrru->base_address = base_addr; rmrru->end_address = end_addr; rmrru->segment = rmrr->segment; + /* "0" is an invalid group id. */ + rmrru->gid = 0; dev_scope_start = (void *)(rmrr + 1); dev_scope_end = ((void *)rmrr) + header->length; @@ -674,7 +677,31 @@ acpi_parse_one_rmrr(struct acpi_dmar_header *header) " RMRR region: base_addr %"PRIx64 " end_address %"PRIx64"\n", rmrru->base_address, rmrru->end_address); + + list_for_each_entry(cur_rmrr, &acpi_rmrr_units, list) + { + /* + * Any same or overlap range mean they should be + * at same group. + */ + if ( ((base_addr >= cur_rmrr->base_address) && + (end_addr <= cur_rmrr->end_address)) || + ((base_addr <= cur_rmrr->base_address) && + (end_addr >= cur_rmrr->end_address)) ) + { + rmrru->gid = cur_rmrr->gid; + continue; + } + } + acpi_register_rmrr_unit(rmrru); + + /* Allocate group id from gid:1. */ + if ( !rmrru->gid ) + { + group_id++; + rmrru->gid = group_id; + } } } diff --git a/xen/drivers/passthrough/vtd/dmar.h b/xen/drivers/passthrough/vtd/dmar.h index af205f5..3ef7cb7 100644 --- a/xen/drivers/passthrough/vtd/dmar.h +++ b/xen/drivers/passthrough/vtd/dmar.h @@ -76,6 +76,8 @@ struct acpi_rmrr_unit { u64 end_address; u16 segment; u8 allow_all:1; + int gid; + domid_t domid; }; struct acpi_atsr_unit { diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 298d458..00f72cb 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -1882,9 +1882,9 @@ static int rmrr_identity_mapping(struct domain *d, bool_t map, static int intel_iommu_add_device(u8 devfn, struct pci_dev *pdev) { - struct acpi_rmrr_unit *rmrr; - u16 bdf; - int ret, i; + struct acpi_rmrr_unit *rmrr, *g_rmrr; + u16 bdf, g_bdf; + int ret, i, j; ASSERT(spin_is_locked(&pcidevs_lock)); @@ -1905,6 +1905,32 @@ static int intel_iommu_add_device(u8 devfn, struct pci_dev *pdev) PCI_BUS(bdf) == pdev->bus && PCI_DEVFN2(bdf) == devfn ) { + if ( rmrr->domid == hardware_domain->domain_id ) + { + for_each_rmrr_device ( g_rmrr, g_bdf, j ) + { + if ( g_rmrr->gid == rmrr->gid ) + { + if ( g_rmrr->domid == hardware_domain->domain_id ) + g_rmrr->domid = pdev->domain->domain_id; + else if ( g_rmrr->domid != pdev->domain->domain_id ) + { + rmrr->domid = g_rmrr->domid; + continue; + } + } + } + } + + if ( rmrr->domid != pdev->domain->domain_id ) + { + domain_context_unmap(pdev->domain, devfn, pdev); + dprintk(XENLOG_ERR VTDPREFIX, "d%d: this is a group device owned by d%d\n", + pdev->domain->domain_id, rmrr->domid); + rmrr->domid = 0; + return -EINVAL; + } + ret = rmrr_identity_mapping(pdev->domain, 1, rmrr); if ( ret ) dprintk(XENLOG_ERR VTDPREFIX, "d%d: RMRR mapping failed\n", @@ -1946,6 +1972,8 @@ static int intel_iommu_remove_device(u8 devfn, struct pci_dev *pdev) PCI_DEVFN2(bdf) != devfn ) continue; + /* Just release to hardware domain. */ + rmrr->domid = hardware_domain->domain_id; rmrr_identity_mapping(pdev->domain, 0, rmrr); } @@ -2104,6 +2132,8 @@ static void __hwdom_init setup_hwdom_rmrr(struct domain *d) spin_lock(&pcidevs_lock); for_each_rmrr_device ( rmrr, bdf, i ) { + /* hwdom should own all devices at first. */ + rmrr->domid = d->domain_id; ret = rmrr_identity_mapping(d, 1, rmrr); if ( ret ) dprintk(XENLOG_ERR VTDPREFIX, @@ -2271,9 +2301,9 @@ static int reassign_device_ownership( static int intel_iommu_assign_device( struct domain *d, u8 devfn, struct pci_dev *pdev) { - struct acpi_rmrr_unit *rmrr; - int ret = 0, i; - u16 bdf, seg; + struct acpi_rmrr_unit *rmrr, *g_rmrr; + int ret = 0, i, j; + u16 bdf, seg, g_bdf; u8 bus; if ( list_empty(&acpi_drhd_units) ) @@ -2293,6 +2323,32 @@ static int intel_iommu_assign_device( PCI_BUS(bdf) == bus && PCI_DEVFN2(bdf) == devfn ) { + if ( rmrr->domid == hardware_domain->domain_id ) + { + for_each_rmrr_device ( g_rmrr, g_bdf, j ) + { + if ( g_rmrr->gid == rmrr->gid ) + { + if ( g_rmrr->domid == hardware_domain->domain_id ) + g_rmrr->domid = pdev->domain->domain_id; + else if ( g_rmrr->domid != pdev->domain->domain_id ) + { + rmrr->domid = g_rmrr->domid; + continue; + } + } + } + } + + if ( rmrr->domid != pdev->domain->domain_id ) + { + domain_context_unmap(pdev->domain, devfn, pdev); + dprintk(XENLOG_ERR VTDPREFIX, "d%d: this is a group device owned by d%d\n", + pdev->domain->domain_id, rmrr->domid); + rmrr->domid = 0; + return -EINVAL; + } + ret = rmrr_identity_mapping(d, 1, rmrr); if ( ret ) { -- 1.9.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |