From mboxrd@z Thu Jan 1 00:00:00 1970 From: Tiejun Chen Subject: [v3][PATCH 04/16] xen/passthrough: extend hypercall to support rdm reservation policy Date: Thu, 11 Jun 2015 09:15:13 +0800 Message-ID: <1433985325-16676-5-git-send-email-tiejun.chen@intel.com> References: <1433985325-16676-1-git-send-email-tiejun.chen@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1433985325-16676-1-git-send-email-tiejun.chen@intel.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: jbeulich@suse.com, tim@xen.org, andrew.cooper3@citrix.com, kevin.tian@intel.com, yang.z.zhang@intel.com, wei.liu2@citrix.com, ian.campbell@citrix.com, Ian.Jackson@eu.citrix.com, stefano.stabellini@citrix.com Cc: xen-devel@lists.xen.org List-Id: xen-devel@lists.xenproject.org This patch extends the existing hypercall to support rdm reservation policy. We return error or just throw out a warning message depending on whether the policy is "strict" or "relaxed" when reserving RDM regions in pfn space. Note in some special cases, e.g. add a device to hwdomain, and remove a device from user domain, 'relaxed' is fine enough since this is always safe to hwdomain. Signed-off-by: Tiejun Chen --- xen/arch/x86/mm/p2m.c | 8 +++++++- xen/drivers/passthrough/amd/pci_amd_iommu.c | 3 ++- xen/drivers/passthrough/arm/smmu.c | 2 +- xen/drivers/passthrough/device_tree.c | 11 ++++++++++- xen/drivers/passthrough/pci.c | 10 ++++++---- xen/drivers/passthrough/vtd/iommu.c | 20 ++++++++++++-------- xen/include/asm-x86/p2m.h | 2 +- xen/include/public/domctl.h | 5 +++++ xen/include/xen/iommu.h | 2 +- 9 files changed, 45 insertions(+), 18 deletions(-) diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index c7198a5..3fcdcac 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -899,7 +899,7 @@ int set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, } int set_identity_p2m_entry(struct domain *d, unsigned long gfn, - p2m_access_t p2ma) + p2m_access_t p2ma, u32 flag) { p2m_type_t p2mt; p2m_access_t a; @@ -924,6 +924,12 @@ int set_identity_p2m_entry(struct domain *d, unsigned long gfn, printk(XENLOG_G_WARNING "Cannot identity map d%d:%lx, already mapped to %lx.\n", d->domain_id, gfn, mfn_x(mfn)); + + if ( flag == XEN_DOMCTL_DEV_RDM_RELAXED ) + { + ret = 0; + printk(XENLOG_G_WARNING "Some devices may work failed.\n"); + } } gfn_unlock(p2m, gfn, 0); diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index e83bb35..920b35a 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -394,7 +394,8 @@ static int reassign_device(struct domain *source, struct domain *target, } static int amd_iommu_assign_device(struct domain *d, u8 devfn, - struct pci_dev *pdev) + struct pci_dev *pdev, + u32 flag) { struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(pdev->seg); int bdf = PCI_BDF2(pdev->bus, devfn); diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c index 6cc4394..9a667e9 100644 --- a/xen/drivers/passthrough/arm/smmu.c +++ b/xen/drivers/passthrough/arm/smmu.c @@ -2605,7 +2605,7 @@ static void arm_smmu_destroy_iommu_domain(struct iommu_domain *domain) } static int arm_smmu_assign_dev(struct domain *d, u8 devfn, - struct device *dev) + struct device *dev, u32 flag) { struct iommu_domain *domain; struct arm_smmu_xen_domain *xen_domain; diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c index 5d3842a..ea85645 100644 --- a/xen/drivers/passthrough/device_tree.c +++ b/xen/drivers/passthrough/device_tree.c @@ -52,7 +52,8 @@ int iommu_assign_dt_device(struct domain *d, struct dt_device_node *dev) goto fail; } - rc = hd->platform_ops->assign_device(d, 0, dt_to_dev(dev)); + rc = hd->platform_ops->assign_device(d, 0, dt_to_dev(dev), + XEN_DOMCTL_DEV_NO_RDM); if ( rc ) goto fail; @@ -148,6 +149,14 @@ int iommu_do_dt_domctl(struct xen_domctl *domctl, struct domain *d, if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_DT ) break; + if ( domctl->u.assign_device.flag == XEN_DOMCTL_DEV_NO_RDM ) + { + printk(XENLOG_G_ERR "XEN_DOMCTL_assign_device: assign \"%s\"" + " to dom%u failed (%d) since we don't support RDM.\n", + dt_node_full_name(dev), d->domain_id, ret); + break; + } + if ( unlikely(d->is_dying) ) { ret = -EINVAL; diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c index e30be43..557c87e 100644 --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -1335,7 +1335,7 @@ static int device_assigned(u16 seg, u8 bus, u8 devfn) return pdev ? 0 : -EBUSY; } -static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn) +static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn, u32 flag) { struct hvm_iommu *hd = domain_hvm_iommu(d); struct pci_dev *pdev; @@ -1371,7 +1371,7 @@ static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn) pdev->fault.count = 0; - if ( (rc = hd->platform_ops->assign_device(d, devfn, pci_to_dev(pdev))) ) + if ( (rc = hd->platform_ops->assign_device(d, devfn, pci_to_dev(pdev), flag)) ) goto done; for ( ; pdev->phantom_stride; rc = 0 ) @@ -1379,7 +1379,7 @@ static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn) devfn += pdev->phantom_stride; if ( PCI_SLOT(devfn) != PCI_SLOT(pdev->devfn) ) break; - rc = hd->platform_ops->assign_device(d, devfn, pci_to_dev(pdev)); + rc = hd->platform_ops->assign_device(d, devfn, pci_to_dev(pdev), flag); if ( rc ) printk(XENLOG_G_WARNING "d%d: assign %04x:%02x:%02x.%u failed (%d)\n", d->domain_id, seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), @@ -1496,6 +1496,7 @@ int iommu_do_pci_domctl( { u16 seg; u8 bus, devfn; + u32 flag; int ret = 0; uint32_t machine_sbdf; @@ -1577,9 +1578,10 @@ int iommu_do_pci_domctl( seg = machine_sbdf >> 16; bus = PCI_BUS(machine_sbdf); devfn = PCI_DEVFN2(machine_sbdf); + flag = domctl->u.assign_device.flag; ret = device_assigned(seg, bus, devfn) ?: - assign_device(d, seg, bus, devfn); + assign_device(d, seg, bus, devfn, flag); if ( ret == -ERESTART ) ret = hypercall_create_continuation(__HYPERVISOR_domctl, "h", u_domctl); diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 31ce1af..d7c9e1c 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -1808,7 +1808,8 @@ static void iommu_set_pgd(struct domain *d) } static int rmrr_identity_mapping(struct domain *d, bool_t map, - const struct acpi_rmrr_unit *rmrr) + const struct acpi_rmrr_unit *rmrr, + u32 flag) { unsigned long base_pfn = rmrr->base_address >> PAGE_SHIFT_4K; unsigned long end_pfn = PAGE_ALIGN_4K(rmrr->end_address) >> PAGE_SHIFT_4K; @@ -1856,7 +1857,7 @@ static int rmrr_identity_mapping(struct domain *d, bool_t map, while ( base_pfn < end_pfn ) { - int err = set_identity_p2m_entry(d, base_pfn, p2m_access_rw); + int err = set_identity_p2m_entry(d, base_pfn, p2m_access_rw, flag); if ( err ) return err; @@ -1899,7 +1900,8 @@ static int intel_iommu_add_device(u8 devfn, struct pci_dev *pdev) PCI_BUS(bdf) == pdev->bus && PCI_DEVFN2(bdf) == devfn ) { - ret = rmrr_identity_mapping(pdev->domain, 1, rmrr); + ret = rmrr_identity_mapping(pdev->domain, 1, rmrr, + XEN_DOMCTL_DEV_RDM_RELAXED); if ( ret ) dprintk(XENLOG_ERR VTDPREFIX, "d%d: RMRR mapping failed\n", pdev->domain->domain_id); @@ -1940,7 +1942,8 @@ static int intel_iommu_remove_device(u8 devfn, struct pci_dev *pdev) PCI_DEVFN2(bdf) != devfn ) continue; - rmrr_identity_mapping(pdev->domain, 0, rmrr); + rmrr_identity_mapping(pdev->domain, 0, rmrr, + XEN_DOMCTL_DEV_RDM_RELAXED); } return domain_context_unmap(pdev->domain, devfn, pdev); @@ -2098,7 +2101,7 @@ static void __hwdom_init setup_hwdom_rmrr(struct domain *d) spin_lock(&pcidevs_lock); for_each_rmrr_device ( rmrr, bdf, i ) { - ret = rmrr_identity_mapping(d, 1, rmrr); + ret = rmrr_identity_mapping(d, 1, rmrr, XEN_DOMCTL_DEV_RDM_RELAXED); if ( ret ) dprintk(XENLOG_ERR VTDPREFIX, "IOMMU: mapping reserved region failed\n"); @@ -2241,7 +2244,8 @@ static int reassign_device_ownership( PCI_BUS(bdf) == pdev->bus && PCI_DEVFN2(bdf) == devfn ) { - ret = rmrr_identity_mapping(source, 0, rmrr); + ret = rmrr_identity_mapping(source, 0, rmrr, + XEN_DOMCTL_DEV_RDM_RELAXED); if ( ret != -ENOENT ) return ret; } @@ -2265,7 +2269,7 @@ static int reassign_device_ownership( } static int intel_iommu_assign_device( - struct domain *d, u8 devfn, struct pci_dev *pdev) + struct domain *d, u8 devfn, struct pci_dev *pdev, u32 flag) { struct acpi_rmrr_unit *rmrr; int ret = 0, i; @@ -2294,7 +2298,7 @@ static int intel_iommu_assign_device( PCI_BUS(bdf) == bus && PCI_DEVFN2(bdf) == devfn ) { - ret = rmrr_identity_mapping(d, 1, rmrr); + ret = rmrr_identity_mapping(d, 1, rmrr, flag); if ( ret ) { reassign_device_ownership(d, hardware_domain, devfn, pdev); diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h index 95b6266..a80b4f8 100644 --- a/xen/include/asm-x86/p2m.h +++ b/xen/include/asm-x86/p2m.h @@ -545,7 +545,7 @@ int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn); /* Set identity addresses in the p2m table (for pass-through) */ int set_identity_p2m_entry(struct domain *d, unsigned long gfn, - p2m_access_t p2ma); + p2m_access_t p2ma, u32 flag); /* Add foreign mapping to the guest's p2m table. */ int p2m_add_foreign(struct domain *tdom, unsigned long fgfn, diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index bc45ea5..2f9e40e 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -478,6 +478,11 @@ struct xen_domctl_assign_device { XEN_GUEST_HANDLE_64(char) path; /* path to the device tree node */ } dt; } u; + /* IN */ +#define XEN_DOMCTL_DEV_NO_RDM 0 +#define XEN_DOMCTL_DEV_RDM_RELAXED 1 +#define XEN_DOMCTL_DEV_RDM_STRICT 2 + uint32_t flag; /* flag of assigned device */ }; typedef struct xen_domctl_assign_device xen_domctl_assign_device_t; DEFINE_XEN_GUEST_HANDLE(xen_domctl_assign_device_t); diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h index e2f584d..02b2b02 100644 --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -140,7 +140,7 @@ struct iommu_ops { int (*add_device)(u8 devfn, device_t *dev); int (*enable_device)(device_t *dev); int (*remove_device)(u8 devfn, device_t *dev); - int (*assign_device)(struct domain *, u8 devfn, device_t *dev); + int (*assign_device)(struct domain *, u8 devfn, device_t *dev, u32 flag); int (*reassign_device)(struct domain *s, struct domain *t, u8 devfn, device_t *dev); #ifdef HAS_PCI -- 1.9.1