From patchwork Sun Feb 23 22:16:27 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 25146 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yh0-f71.google.com (mail-yh0-f71.google.com [209.85.213.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 575FF20972 for ; Sun, 23 Feb 2014 22:18:07 +0000 (UTC) Received: by mail-yh0-f71.google.com with SMTP id z6sf8447946yhz.10 for ; Sun, 23 Feb 2014 14:18:07 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:cc:subject:precedence:list-id:list-unsubscribe:list-post :list-help:list-subscribe:mime-version:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list :list-archive:content-type:content-transfer-encoding; bh=gzNzTQh+a+MJd2jrphLG/a+gzJ/3AC10BjlCMHNBJ2M=; b=PM7Ix3caAhOpyDLqeWYAK7ujAfKWWpIs19+cYKjq6rQl1CdeFdS5G/3EfeHRPMvGqB GtnxNp6RPUq4TwvWfnrpoHbf7KrOm/sI4EZxofTBr6SlH0Hc/5jL8Mzwt+YT0nQg9zGz YXleyzdWog73ZxdrGUt1jaExVuyURvyI+jomn1jF/8YGs85OZimis6SHMEJ0sygnJ8Kw SmPfGjWMQMoBZmBXqQfcbA6xSXNelVOVsrv0p2U4q0UY/KAUKGQ5YRYmsVtkLApCu8x5 +CtlmR+s/7WqxPb0RuiFg2GclQJbajF2WCdyyJ5bYOteyyKBBNOBKRbw3rm+SySdYslw krzA== X-Gm-Message-State: ALoCoQlCbriMsZjNj3ORWUEo+xQUTuV9NtLsyexu410QIMEVrwgTBbPlbLbM6uHWmDXxlfFCouhK X-Received: by 10.236.89.15 with SMTP id b15mr8434425yhf.13.1393193887105; Sun, 23 Feb 2014 14:18:07 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.36.200 with SMTP id p66ls1671541qgp.74.gmail; Sun, 23 Feb 2014 14:18:07 -0800 (PST) X-Received: by 10.220.175.198 with SMTP id bb6mr10703167vcb.31.1393193886985; Sun, 23 Feb 2014 14:18:06 -0800 (PST) Received: from mail-ve0-f175.google.com (mail-ve0-f175.google.com [209.85.128.175]) by mx.google.com with ESMTPS id f7si5297117vcz.132.2014.02.23.14.18.06 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 23 Feb 2014 14:18:06 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.175 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.175; Received: by mail-ve0-f175.google.com with SMTP id oy12so730132veb.20 for ; Sun, 23 Feb 2014 14:18:06 -0800 (PST) X-Received: by 10.52.107.35 with SMTP id gz3mr8887880vdb.8.1393193886891; Sun, 23 Feb 2014 14:18:06 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.174.196 with SMTP id u4csp20469vcz; Sun, 23 Feb 2014 14:18:06 -0800 (PST) X-Received: by 10.52.184.161 with SMTP id ev1mr8964646vdc.84.1393193886145; Sun, 23 Feb 2014 14:18:06 -0800 (PST) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id io9si5306555vcb.62.2014.02.23.14.18.05 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Sun, 23 Feb 2014 14:18:06 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of xen-devel-bounces@lists.xen.org designates 50.57.142.19 as permitted sender) client-ip=50.57.142.19; Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1WHhM1-0006zW-Gp; Sun, 23 Feb 2014 22:16:57 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1WHhLy-0006uL-V3 for xen-devel@lists.xenproject.org; Sun, 23 Feb 2014 22:16:55 +0000 Received: from [85.158.137.68:23447] by server-13.bemta-3.messagelabs.com id 64/53-26923-6537A035; Sun, 23 Feb 2014 22:16:54 +0000 X-Env-Sender: julien.grall@linaro.org X-Msg-Ref: server-12.tower-31.messagelabs.com!1393193813!872290!1 X-Originating-IP: [74.125.83.44] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 6.9.16; banners=-,-,- X-VirusChecked: Checked Received: (qmail 13848 invoked from network); 23 Feb 2014 22:16:53 -0000 Received: from mail-ee0-f44.google.com (HELO mail-ee0-f44.google.com) (74.125.83.44) by server-12.tower-31.messagelabs.com with RC4-SHA encrypted SMTP; 23 Feb 2014 22:16:53 -0000 Received: by mail-ee0-f44.google.com with SMTP id d49so379558eek.31 for ; Sun, 23 Feb 2014 14:16:52 -0800 (PST) X-Received: by 10.14.176.66 with SMTP id a42mr20730293eem.101.1393193812806; Sun, 23 Feb 2014 14:16:52 -0800 (PST) Received: from belegaer.uk.xensource.com. ([185.25.64.249]) by mx.google.com with ESMTPSA id g1sm55994749eet.6.2014.02.23.14.16.50 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 23 Feb 2014 14:16:51 -0800 (PST) From: Julien Grall To: xen-devel@lists.xenproject.org Date: Sun, 23 Feb 2014 22:16:27 +0000 Message-Id: <1393193792-20008-11-git-send-email-julien.grall@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1393193792-20008-1-git-send-email-julien.grall@linaro.org> References: <1393193792-20008-1-git-send-email-julien.grall@linaro.org> Cc: stefano.stabellini@citrix.com, Julien Grall , tim@xen.org, ian.campbell@citrix.com Subject: [Xen-devel] [PATCH v2 10/15] xen/passthrough: iommu: Basic support of device tree assignment X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: List-Unsubscribe: , List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: julien.grall@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.175 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Archive: Add IOMMU helpers to support device tree assignment/deassignment. This patch introduces 2 new fields in the dt_device_node: - is_protected: Does the device is protected by an IOMMU - next_assigned: Pointer to the next device assigned to the same domain Signed-off-by: Julien Grall --- Changes in v2: - Patch added --- xen/common/device_tree.c | 4 ++ xen/drivers/passthrough/Makefile | 1 + xen/drivers/passthrough/device_tree.c | 106 +++++++++++++++++++++++++++++++++ xen/drivers/passthrough/iommu.c | 10 ++++ xen/include/xen/device_tree.h | 14 +++++ xen/include/xen/hvm/iommu.h | 6 ++ xen/include/xen/iommu.h | 16 +++++ 7 files changed, 157 insertions(+) create mode 100644 xen/drivers/passthrough/device_tree.c diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c index 564f2bb..7c6b683 100644 --- a/xen/common/device_tree.c +++ b/xen/common/device_tree.c @@ -1695,6 +1695,10 @@ static unsigned long __init unflatten_dt_node(const void *fdt, np->full_name = ((char *)np) + sizeof(struct dt_device_node); /* By default dom0 owns the device */ np->used_by = 0; + /* By default the device is not protected */ + np->is_protected = false; + INIT_LIST_HEAD(&np->next_assigned); + if ( new_format ) { char *fn = np->full_name; diff --git a/xen/drivers/passthrough/Makefile b/xen/drivers/passthrough/Makefile index 6e08f89..5a0a35e 100644 --- a/xen/drivers/passthrough/Makefile +++ b/xen/drivers/passthrough/Makefile @@ -5,3 +5,4 @@ subdir-$(x86_64) += x86 obj-y += iommu.o obj-$(x86) += io.o obj-$(HAS_PCI) += pci.o +obj-$(HAS_DEVICE_TREE) += device_tree.o diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c new file mode 100644 index 0000000..7384e73 --- /dev/null +++ b/xen/drivers/passthrough/device_tree.c @@ -0,0 +1,106 @@ +/* + * xen/drivers/passthrough/arm/device_tree.c + * + * Code to passthrough device tree node to a guest + * + * Julien Grall + * Copyright (c) 2014 Linaro Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +static spinlock_t dtdevs_lock = SPIN_LOCK_UNLOCKED; + +int iommu_assign_dt_device(struct domain *d, struct dt_device_node *dev) +{ + int rc = -EBUSY; + struct hvm_iommu *hd = domain_hvm_iommu(d); + + if ( !iommu_enabled || !hd->platform_ops ) + return -EINVAL; + + if ( !dt_device_is_protected(dev) ) + return -EINVAL; + + spin_lock(&dtdevs_lock); + + if ( !list_empty(&dev->next_assigned) ) + goto fail; + + rc = hd->platform_ops->assign_dt_device(d, dev); + + if ( rc ) + goto fail; + + list_add(&dev->next_assigned, &hd->dt_devices); + dt_device_set_used_by(dev, d->domain_id); + +fail: + spin_unlock(&dtdevs_lock); + + return rc; +} + +int iommu_deassign_dt_device(struct domain *d, struct dt_device_node *dev) +{ + struct hvm_iommu *hd = domain_hvm_iommu(d); + int rc; + + if ( !iommu_enabled || !hd->platform_ops ) + return -EINVAL; + + if ( !dt_device_is_protected(dev) ) + return -EINVAL; + + spin_lock(&dtdevs_lock); + + rc = hd->platform_ops->reassign_dt_device(d, dom0, dev); + if ( rc ) + goto fail; + + dt_device_set_used_by(dev, dom0->domain_id); + + list_del(&dev->next_assigned); + +fail: + spin_unlock(&dtdevs_lock); + + return rc; +} + +int iommu_dt_domain_init(struct domain *d) +{ + struct hvm_iommu *hd = domain_hvm_iommu(d); + + INIT_LIST_HEAD(&hd->dt_devices); + + return 0; +} + +void iommu_dt_domain_destroy(struct domain *d) +{ + struct hvm_iommu *hd = domain_hvm_iommu(d); + struct dt_device_node *dev, *_dev; + int rc; + + list_for_each_entry_safe(dev, _dev, &hd->dt_devices, next_assigned) + { + rc = iommu_deassign_dt_device(d, dev); + if ( rc ) + dprintk(XENLOG_ERR, "Failed to deassign %s in domain %u\n", + dt_node_full_name(dev), d->domain_id); + } +} diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index e6a1839..6c951d0 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -123,6 +123,12 @@ int iommu_domain_init(struct domain *d) if ( ret ) return ret; +#if HAS_DEVICE_TREE + ret = iommu_dt_domain_init(d); + if ( ret ) + return ret; +#endif + if ( !iommu_enabled ) return 0; @@ -198,6 +204,10 @@ void iommu_domain_destroy(struct domain *d) if ( need_iommu(d) ) iommu_teardown(d); +#ifdef HAS_DEVICE_TREE + iommu_dt_domain_destroy(d); +#endif + arch_iommu_domain_destroy(d); } diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h index d429e60..2aae047 100644 --- a/xen/include/xen/device_tree.h +++ b/xen/include/xen/device_tree.h @@ -16,6 +16,7 @@ #include #include #include +#include #define DEVICE_TREE_MAX_DEPTH 16 @@ -110,6 +111,9 @@ struct dt_device_node { struct dt_device_node *next; /* TODO: Remove it. Only use to know the last children */ struct dt_device_node *allnext; + /* IOMMU specific fields */ + bool is_protected; /* Tell if the device is protected by an IOMMU */ + struct list_head next_assigned; }; #define MAX_PHANDLE_ARGS 16 @@ -325,6 +329,16 @@ static inline domid_t dt_device_used_by(const struct dt_device_node *device) return device->used_by; } +static inline void dt_device_set_protected(struct dt_device_node *device) +{ + device->is_protected = true; +} + +static inline bool dt_device_is_protected(const struct dt_device_node *device) +{ + return device->is_protected; +} + static inline bool_t dt_property_name_is_equal(const struct dt_property *pp, const char *name) { diff --git a/xen/include/xen/hvm/iommu.h b/xen/include/xen/hvm/iommu.h index f8f8a93..72002e1 100644 --- a/xen/include/xen/hvm/iommu.h +++ b/xen/include/xen/hvm/iommu.h @@ -21,6 +21,7 @@ #define __XEN_HVM_IOMMU_H__ #include +#include #include struct hvm_iommu { @@ -28,6 +29,11 @@ struct hvm_iommu { /* iommu_ops */ const struct iommu_ops *platform_ops; + + #ifdef HAS_DEVICE_TREE + /* List of DT devices assigned to this domain */ + struct list_head dt_devices; + #endif }; #endif /* __XEN_HVM_IOMMU_H__ */ diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h index 5a19c80..266cd6e 100644 --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -82,6 +82,16 @@ bool_t pt_irq_need_timer(uint32_t flags); #define PT_IRQ_TIME_OUT MILLISECS(8) #endif /* HAS_PCI */ +#ifdef HAS_DEVICE_TREE +#include + +int iommu_assign_dt_device(struct domain *d, struct dt_device_node *dev); +int iommu_deassign_dt_device(struct domain *d, struct dt_device_node *dev); +int iommu_dt_domain_init(struct domain *d); +void iommu_dt_domain_destroy(struct domain *d); + +#endif /* HAS_DEVICE_TREE */ + #ifdef CONFIG_X86 struct msi_desc; struct msi_msg; @@ -101,6 +111,12 @@ struct iommu_ops { u8 devfn, struct pci_dev *); int (*get_device_group_id)(u16 seg, u8 bus, u8 devfn); #endif /* HAS_PCI */ +#ifdef HAS_DEVICE_TREE + int (*assign_dt_device)(struct domain *d, const struct dt_device_node *dev); + int (*reassign_dt_device)(struct domain *s, struct domain *t, + const struct dt_device_node *dev); +#endif + void (*teardown)(struct domain *d); int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn, unsigned int flags);