From patchwork Tue Dec 12 19:02:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 121636 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp4508560qgn; Tue, 12 Dec 2017 11:04:38 -0800 (PST) X-Google-Smtp-Source: ACJfBotIylIRzbhCwXFu3MDBC3y4pQbJEkejTQ7MjuKOelr2DmzYoe5rDkPLsCHBab5dPlpm6xcj X-Received: by 10.107.2.137 with SMTP id 131mr7072341ioc.186.1513105478056; Tue, 12 Dec 2017 11:04:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1513105478; cv=none; d=google.com; s=arc-20160816; b=vJH/YtFMngO/HXq6DPmgvuZtED/A7EQjqhX+8UyzONQWI/Z/n0zifzEZf+yuYd2iJx lXe9ydkwi2Grnz2CHjIoI6wtJqOAcSrDu6vdLKvM6LfFYIwVNmR/J2mvpSxGnVq9E/XI V1KlVOw+bziAkn+1UDP76q/hAVP0xgSwtaqL5CBAEfsQokIl8AeCSlgEv1L+Yb/7FQWW CoAo3CDcQtuRvuuRfiYBCwKCa7pPjoULj2Uf+umjtiDpGyq/Eabyrw5icG602UWbVPxf ef/xxEp701pe+OsAo7KePSAv5LtZbSVpFDiPqmwyMqSCmkKw7FbO2ycWHcGQE4w29/wH KzdQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version :list-subscribe:list-help:list-post:list-unsubscribe:list-id :precedence:subject:cc:references:in-reply-to:message-id:date:to :from:dkim-signature:arc-authentication-results; bh=WAFclMjRBQMH9zicDBCUKu8/yM70VLupqj1rtjwnwxM=; b=D2UzgSeq7wAxprGBalEPk1VylDRhtI6I/8VdLkKAN99QZpfIVifuAN1gcBCHNJWpBu d7WfhX0xo99uFZSGt8gfm7+8BjnLopOUx/3tGliaSIv28ep727Ui6LGP0X8tOT3wyg6j 55o9upgMiTfSKvRt601ZQ0xk2ziDHkMH9+VGE2X+O7oYZ+SCn9edYzT9Xd+2H2j7uC+0 P77jH8wxgAVesSvCoZtaMv2jCPTuSR1AtRSRZnKZFTh62yXKaX87KtZUmxg8vdMLl1va DnHMBgbkTVxA8NJv3l5jGKGDyMXd4L+ySCoW8xgYpXcR08HUjH1jJP9ZbqH/iEcDcXDb 2iig== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=Rorc8Wed; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org. [192.237.175.120]) by mx.google.com with ESMTPS id e81si179156itc.113.2017.12.12.11.04.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 12 Dec 2017 11:04:38 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=Rorc8Wed; spf=pass (google.com: best guess record for domain of xen-devel-bounces@lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eOpp3-0002W6-6T; Tue, 12 Dec 2017 19:02:33 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eOpp2-0002VH-7K for xen-devel@lists.xen.org; Tue, 12 Dec 2017 19:02:32 +0000 X-Inumbo-ID: ed45d09f-df6e-11e7-b4a6-bc764e045a96 Received: from mail-wm0-x243.google.com (unknown [2a00:1450:400c:c09::243]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id ed45d09f-df6e-11e7-b4a6-bc764e045a96; Tue, 12 Dec 2017 20:01:58 +0100 (CET) Received: by mail-wm0-x243.google.com with SMTP id i11so689311wmf.4 for ; Tue, 12 Dec 2017 11:02:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=23sZqACdcVyMz/9na7hwK8jKYk8KTNy3pXQpkHgAYxM=; b=Rorc8Wed+CKR6QuCqo+vBXG1XgFq39FGcsE23n09JAytXewCHUw34bJvVbW+2ybU96 3oV9rSZRAJkgm3WPwRJ/ihKB8LvcRd/Y+QcXRtz/sZZFqQMdgIodslPKWfyhtbK6QeJD SqJOaRIDnJVyUqu0F+XnABcnnzZnVhY+sQiLA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=23sZqACdcVyMz/9na7hwK8jKYk8KTNy3pXQpkHgAYxM=; b=NRNA5u5Vfpi72KM5ZSVU4VbjmwmrNh8GV19lyxFpH/VHVMZptlDIZLolRRuY4NcFri ym29SGZFcdB1Q0T+vsrYZYhrrY5ptWDM5PF1koz7eInC3dL1o3psLo9mLCYacUE2oH5m zH2zf7eLplZCQnPhviPiNnko9MdP3/se4alN107yGuT9bz1vj7YNRPjM1MNucLmQebI8 R+W6qAz8h2ObhBeJEtahpZplLj/3/0PmOWCn3LQoX94wIG8oL/l8BxWO+JFYisdqhvVC XAjIfOgN1zkuR5FXfzOUUAByAlICrFVyKlwZFyg8knds3sfsnkTKwXZCIR8cLWel56zw cBaw== X-Gm-Message-State: AKGB3mL7q1KGxZiEEll/9jwSZW7RGWcaVkPq6B2rbqFXbc6rw0LeJ2qB nJUGQtBAvUGZ17E1S628NAx2y7PmgqQ= X-Received: by 10.28.22.16 with SMTP id 16mr2829321wmw.138.1513105349032; Tue, 12 Dec 2017 11:02:29 -0800 (PST) Received: from e108454-lin.cambridge.arm.com ([2001:41d0:1:6c23::1]) by smtp.gmail.com with ESMTPSA id n14sm207508wmh.37.2017.12.12.11.02.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 12 Dec 2017 11:02:24 -0800 (PST) From: Julien Grall To: xen-devel@lists.xen.org Date: Tue, 12 Dec 2017 19:02:02 +0000 Message-Id: <20171212190212.5535-7-julien.grall@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171212190212.5535-1-julien.grall@linaro.org> References: <20171212190212.5535-1-julien.grall@linaro.org> Cc: sstabellini@kernel.org, Julien Grall , andre.przywara@linaro.org Subject: [Xen-devel] [v2 06/16] xen/arm: Extend copy_to_guest to support copying from/to guest physical address X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" The only differences between copy_to_guest and access_guest_memory_by_ipa are: - The latter does not support copying data crossing page boundary - The former is copying from/to guest VA whilst the latter from guest PA copy_to_guest can easily be extended to support copying from/to guest physical address. For that a new bit is used to tell whether linear address or ipa is been used. Lastly access_guest_memory_by_ipa is reimplemented using copy_to_guest. This also has the benefits to extend the use of it, it is now possible to copy data crossing page boundary. Signed-off-by: Julien Grall Reviewed-by: Stefano Stabellini --- Changes in v2: - Rework the patch after the interface changes in the previous patch. - Use uint64_t rather than paddr_t in translate_get_page - Add a BUILD_BUG_ON to check whether paddr_t fits in uint64_t --- xen/arch/arm/guestcopy.c | 91 +++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/xen/arch/arm/guestcopy.c b/xen/arch/arm/guestcopy.c index 7e92e27beb..93e4aa2d3f 100644 --- a/xen/arch/arm/guestcopy.c +++ b/xen/arch/arm/guestcopy.c @@ -8,6 +8,8 @@ #define COPY_flush_dcache (1U << 0) #define COPY_from_guest (0U << 1) #define COPY_to_guest (1U << 1) +#define COPY_ipa (0U << 2) +#define COPY_linear (1U << 2) typedef union { @@ -15,9 +17,39 @@ typedef union { struct vcpu *v; } gva; + + struct + { + struct domain *d; + } gpa; } copy_info_t; #define GVA_INFO(vcpu) ((copy_info_t) { .gva = { vcpu } }) +#define GPA_INFO(domain) ((copy_info_t) { .gpa = { domain } }) + +static struct page_info *translate_get_page(copy_info_t info, uint64_t addr, + bool linear, bool write) +{ + p2m_type_t p2mt; + struct page_info *page; + + if ( linear ) + return get_page_from_gva(info.gva.v, addr, + write ? GV2M_WRITE : GV2M_READ); + + page = get_page_from_gfn(info.gpa.d, paddr_to_pfn(addr), &p2mt, P2M_ALLOC); + + if ( !page ) + return NULL; + + if ( !p2m_is_ram(p2mt) ) + { + put_page(page); + return NULL; + } + + return page; +} static unsigned long copy_guest(void *buf, uint64_t addr, unsigned int len, copy_info_t info, unsigned int flags) @@ -26,6 +58,7 @@ static unsigned long copy_guest(void *buf, uint64_t addr, unsigned int len, unsigned offset = addr & ~PAGE_MASK; BUILD_BUG_ON((sizeof(addr)) < sizeof(vaddr_t)); + BUILD_BUG_ON((sizeof(addr)) < sizeof(paddr_t)); while ( len ) { @@ -33,8 +66,8 @@ static unsigned long copy_guest(void *buf, uint64_t addr, unsigned int len, unsigned size = min(len, (unsigned)PAGE_SIZE - offset); struct page_info *page; - page = get_page_from_gva(info.gva.v, addr, - (flags & COPY_to_guest) ? GV2M_WRITE : GV2M_READ); + page = translate_get_page(info, addr, flags & COPY_linear, + flags & COPY_to_guest); if ( page == NULL ) return len; @@ -75,75 +108,39 @@ static unsigned long copy_guest(void *buf, uint64_t addr, unsigned int len, unsigned long raw_copy_to_guest(void *to, const void *from, unsigned len) { return copy_guest((void *)from, (vaddr_t)to, len, - GVA_INFO(current), COPY_to_guest); + GVA_INFO(current), COPY_to_guest | COPY_linear); } unsigned long raw_copy_to_guest_flush_dcache(void *to, const void *from, unsigned len) { return copy_guest((void *)from, (vaddr_t)to, len, GVA_INFO(current), - COPY_to_guest | COPY_flush_dcache); + COPY_to_guest | COPY_flush_dcache | COPY_linear); } unsigned long raw_clear_guest(void *to, unsigned len) { return copy_guest(NULL, (vaddr_t)to, len, GVA_INFO(current), - COPY_to_guest); + COPY_to_guest | COPY_linear); } unsigned long raw_copy_from_guest(void *to, const void __user *from, unsigned len) { return copy_guest(to, (vaddr_t)from, len, GVA_INFO(current), - COPY_from_guest); + COPY_from_guest | COPY_linear); } -/* - * Temporarily map one physical guest page and copy data to or from it. - * The data to be copied cannot cross a page boundary. - */ int access_guest_memory_by_ipa(struct domain *d, paddr_t gpa, void *buf, uint32_t size, bool is_write) { - struct page_info *page; - uint64_t offset = gpa & ~PAGE_MASK; /* Offset within the mapped page */ - p2m_type_t p2mt; - void *p; - - /* Do not cross a page boundary. */ - if ( size > (PAGE_SIZE - offset) ) - { - printk(XENLOG_G_ERR "d%d: guestcopy: memory access crosses page boundary.\n", - d->domain_id); - return -EINVAL; - } - - page = get_page_from_gfn(d, paddr_to_pfn(gpa), &p2mt, P2M_ALLOC); - if ( !page ) - { - printk(XENLOG_G_ERR "d%d: guestcopy: failed to get table entry.\n", - d->domain_id); - return -EINVAL; - } + unsigned long left; + int flags = COPY_ipa; - if ( !p2m_is_ram(p2mt) ) - { - put_page(page); - printk(XENLOG_G_ERR "d%d: guestcopy: guest memory should be RAM.\n", - d->domain_id); - return -EINVAL; - } - - p = __map_domain_page(page); + flags |= is_write ? COPY_to_guest : COPY_from_guest; - if ( is_write ) - memcpy(p + offset, buf, size); - else - memcpy(buf, p + offset, size); + left = copy_guest(buf, gpa, size, GPA_INFO(d), flags); - unmap_domain_page(p); - put_page(page); - - return 0; + return (!left) ? 0 : -EINVAL; } /*