From patchwork Thu Jul 26 15:34:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Stabellini X-Patchwork-Id: 1243801 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 79962DFFCE for ; Thu, 26 Jul 2012 16:28:55 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1SuQnn-000328-Pq; Thu, 26 Jul 2012 16:20:39 +0000 Received: from smtp02.citrix.com ([66.165.176.63]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1SuQR1-0006MW-Ru for linux-arm-kernel@lists.infradead.org; Thu, 26 Jul 2012 15:57:09 +0000 X-IronPort-AV: E=Sophos;i="4.77,659,1336363200"; d="scan'208";a="203311698" Received: from ftlpmailmx02.citrite.net ([10.13.107.66]) by FTLPIPO02.CITRIX.COM with ESMTP/TLS/RC4-MD5; 26 Jul 2012 11:56:43 -0400 Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com (10.13.107.66) with Microsoft SMTP Server id 8.3.213.0; Thu, 26 Jul 2012 11:56:43 -0400 Received: from kaball.uk.xensource.com ([10.80.2.59]) by ukmail1.uk.xensource.com with esmtp (Exim 4.69) (envelope-from ) id 1SuQ5N-0006qa-DT; Thu, 26 Jul 2012 16:34:45 +0100 From: Stefano Stabellini To: Subject: [PATCH 24/24] [HACK] xen/arm: implement xen_remap_domain_mfn_range Date: Thu, 26 Jul 2012 16:34:06 +0100 Message-ID: <1343316846-25860-24-git-send-email-stefano.stabellini@eu.citrix.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Note: CRM114 invocation failed X-Spam-Note: SpamAssassin invocation failed Cc: xen-devel@lists.xensource.com, linaro-dev@lists.linaro.org, Ian.Campbell@citrix.com, arnd@arndb.de, konrad.wilk@oracle.com, catalin.marinas@arm.com, Stefano Stabellini , tim@xen.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Ian Campbell Do not apply! This is a simple, hacky implementation of xen_remap_domain_mfn_range, using XENMAPSPACE_gmfn_foreign. It should use same interface as hybrid x86. Signed-off-by: Ian Campbell Signed-off-by: Stefano Stabellini --- arch/arm/xen/enlighten.c | 79 +++++++++++++++++++++++++++++++++++++++- drivers/xen/privcmd.c | 16 +++++---- drivers/xen/xenfs/super.c | 7 ++++ include/xen/interface/memory.h | 10 ++++-- 4 files changed, 101 insertions(+), 11 deletions(-) diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 1476b0b..7092015 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -16,6 +16,10 @@ #include #include #include +#include +#include + +#include struct start_info _xen_start_info; struct start_info *xen_start_info = &_xen_start_info; @@ -38,12 +42,85 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug); static __read_mostly int xen_events_irq = -1; +#define FOREIGN_MAP_BUFFER 0x90000000UL +#define FOREIGN_MAP_BUFFER_SIZE 0x10000000UL +struct resource foreign_map_resource = { + .start = FOREIGN_MAP_BUFFER, + .end = FOREIGN_MAP_BUFFER + FOREIGN_MAP_BUFFER_SIZE, + .name = "Xen foreign map buffer", + .flags = 0, +}; + +static unsigned long foreign_map_buffer_pfn = FOREIGN_MAP_BUFFER >> PAGE_SHIFT; + +struct remap_data { + struct mm_struct *mm; + unsigned long mfn; + pgprot_t prot; +}; + +static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token, + unsigned long addr, void *data) +{ + struct remap_data *rmd = data; + pte_t pte = pfn_pte(rmd->mfn, rmd->prot); + + if (rmd->mfn < 0x90010) + pr_crit("%s: ptep %p addr %#lx => %#x / %#lx\n", + __func__, ptep, addr, pte_val(pte), rmd->mfn); + + set_pte_at(rmd->mm, addr, ptep, pte); + + rmd->mfn++; + return 0; +} + int xen_remap_domain_mfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long mfn, int nr, pgprot_t prot, unsigned domid) { - return -ENOSYS; + int i, rc = 0; + struct remap_data rmd = { + .mm = vma->vm_mm, + .prot = prot, + }; + struct xen_add_to_physmap xatp = { + .domid = DOMID_SELF, + .space = XENMAPSPACE_gmfn_foreign, + + .foreign_domid = domid, + }; + + if (foreign_map_buffer_pfn + nr > ((FOREIGN_MAP_BUFFER + + FOREIGN_MAP_BUFFER_SIZE)>>PAGE_SHIFT)) { + pr_crit("RAM out of foreign map buffers...\n"); + return -EBUSY; + } + + for (i = 0; i < nr; i++) { + xatp.idx = mfn + i; + xatp.gpfn = foreign_map_buffer_pfn + i; + rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp); + if (rc != 0) { + pr_crit("foreign map add_to_physmap failed, err=%d\n", rc); + goto out; + } + } + + rmd.mfn = foreign_map_buffer_pfn; + rc = apply_to_page_range(vma->vm_mm, + addr, + (unsigned long)nr << PAGE_SHIFT, + remap_area_mfn_pte_fn, &rmd); + if (rc != 0) { + pr_crit("apply_to_page_range failed rc=%d\n", rc); + goto out; + } + + foreign_map_buffer_pfn += nr; +out: + return rc; } EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 85226cb..3e15c22 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -196,9 +198,6 @@ static long privcmd_ioctl_mmap(void __user *udata) LIST_HEAD(pagelist); struct mmap_mfn_state state; - if (!xen_initial_domain()) - return -EPERM; - if (copy_from_user(&mmapcmd, udata, sizeof(mmapcmd))) return -EFAULT; @@ -286,9 +285,6 @@ static long privcmd_ioctl_mmap_batch(void __user *udata) LIST_HEAD(pagelist); struct mmap_batch_state state; - if (!xen_initial_domain()) - return -EPERM; - if (copy_from_user(&m, udata, sizeof(m))) return -EFAULT; @@ -365,6 +361,11 @@ static long privcmd_ioctl(struct file *file, return ret; } +static void privcmd_close(struct vm_area_struct *vma) +{ + /* TODO: unmap VMA */ +} + static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n", @@ -375,7 +376,8 @@ static int privcmd_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } static struct vm_operations_struct privcmd_vm_ops = { - .fault = privcmd_fault + .fault = privcmd_fault, + .close = privcmd_close, }; static int privcmd_mmap(struct file *file, struct vm_area_struct *vma) diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c index a84b53c..edbe22f 100644 --- a/drivers/xen/xenfs/super.c +++ b/drivers/xen/xenfs/super.c @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -80,6 +81,8 @@ static const struct file_operations capabilities_file_ops = { .llseek = default_llseek, }; +extern struct resource foreign_map_resource; + static int xenfs_fill_super(struct super_block *sb, void *data, int silent) { static struct tree_descr xenfs_files[] = { @@ -100,6 +103,10 @@ static int xenfs_fill_super(struct super_block *sb, void *data, int silent) &xsd_kva_file_ops, NULL, S_IRUSR|S_IWUSR); xenfs_create_file(sb, sb->s_root, "xsd_port", &xsd_port_file_ops, NULL, S_IRUSR|S_IWUSR); + rc = request_resource(&iomem_resource, &foreign_map_resource); + if (rc < 0) + pr_crit("failed to register foreign map resource\n"); + rc = 0; /* ignore */ } return rc; diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h index d8e33a9..ec68945 100644 --- a/include/xen/interface/memory.h +++ b/include/xen/interface/memory.h @@ -167,9 +167,13 @@ struct xen_add_to_physmap { uint16_t size; /* Source mapping space. */ -#define XENMAPSPACE_shared_info 0 /* shared info page */ -#define XENMAPSPACE_grant_table 1 /* grant table page */ - unsigned int space; +#define XENMAPSPACE_shared_info 0 /* shared info page */ +#define XENMAPSPACE_grant_table 1 /* grant table page */ +#define XENMAPSPACE_gmfn 2 /* GMFN */ +#define XENMAPSPACE_gmfn_range 3 /* GMFN range */ +#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another guest */ + uint16_t space; + domid_t foreign_domid; /* IFF gmfn_foreign */ /* Index into source mapping space. */ unsigned long idx;