From patchwork Tue Feb 11 14:11:02 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Campbell X-Patchwork-Id: 24458 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pb0-f71.google.com (mail-pb0-f71.google.com [209.85.160.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id DDD93206FF for ; Tue, 11 Feb 2014 14:13:11 +0000 (UTC) Received: by mail-pb0-f71.google.com with SMTP id jt11sf16791190pbb.2 for ; Tue, 11 Feb 2014 06:13:08 -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:mime-version:cc:subject:precedence:list-id :list-unsubscribe:list-post:list-help:list-subscribe:sender :errors-to:x-original-sender:x-original-authentication-results :mailing-list:list-archive:content-type:content-transfer-encoding; bh=WuJfaQFNzSYy2uSd2VIQ896NDHb5pndK7g1C1/+OFGc=; b=Vzq69Ij9yWl2Kg28sbQKIO772S5bs1o+etJkGP06hQQWugvSOVmyfqVtNpSsVBpdPA G1zj2vSL9yu03J2a2DdPL1irPFD/TOaLCJPhe5314HswmwPwroQBww8sBRlT2r1mbVpr RUUdnHB4NDLyY8e2+5AIxDBSkiWh3T5bcxEzoAW8ZegavWvXrzkE0TawmswubLNj1C7D Y3w3ePbimYTsC3ZUUqQ0UcCv6wVwL3UIcepOr5LvdtE7oLHMUEXT0mj1fyw9Dsj4Mo1k UhGJrHOz+akb7SVlXrPFGz8VRVNrBuhG9Wq3aklrPmG7mSNwgzY5+WyngjKzPXbzynvr bdGg== X-Gm-Message-State: ALoCoQl2urnZNTVPJxKj9luOb6JjZ6NNlOUoBjX6EesjyV/PWT84aKF5RCKI8bUD1wJpEauwXzKP X-Received: by 10.66.26.132 with SMTP id l4mr11599714pag.2.1392127988871; Tue, 11 Feb 2014 06:13:08 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.102.244 with SMTP id w107ls2409434qge.26.gmail; Tue, 11 Feb 2014 06:13:08 -0800 (PST) X-Received: by 10.52.121.113 with SMTP id lj17mr24247293vdb.21.1392127988650; Tue, 11 Feb 2014 06:13:08 -0800 (PST) Received: from mail-vb0-f46.google.com (mail-vb0-f46.google.com [209.85.212.46]) by mx.google.com with ESMTPS id x3si5944324vcn.84.2014.02.11.06.13.08 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 11 Feb 2014 06:13:08 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.46 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.46; Received: by mail-vb0-f46.google.com with SMTP id o19so5937357vbm.33 for ; Tue, 11 Feb 2014 06:13:08 -0800 (PST) X-Received: by 10.220.192.71 with SMTP id dp7mr254992vcb.45.1392127988543; Tue, 11 Feb 2014 06:13:08 -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 u4csp249349vcz; Tue, 11 Feb 2014 06:13:08 -0800 (PST) X-Received: by 10.58.133.15 with SMTP id oy15mr27620419veb.19.1392127987873; Tue, 11 Feb 2014 06:13:07 -0800 (PST) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id y6si5935262veb.139.2014.02.11.06.13.07 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 11 Feb 2014 06:13:07 -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 1WDE3P-0002al-NE; Tue, 11 Feb 2014 14:11:15 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1WDE3N-0002Yk-Pv for xen-devel@lists.xen.org; Tue, 11 Feb 2014 14:11:14 +0000 Received: from [85.158.137.68:26777] by server-15.bemta-3.messagelabs.com id F7/65-19263-18F2AF25; Tue, 11 Feb 2014 14:11:13 +0000 X-Env-Sender: Ian.Campbell@citrix.com X-Msg-Ref: server-15.tower-31.messagelabs.com!1392127868!1127751!2 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n X-StarScan-Received: X-StarScan-Version: 6.9.16; banners=-,-,- X-VirusChecked: Checked Received: (qmail 23277 invoked from network); 11 Feb 2014 14:11:11 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-15.tower-31.messagelabs.com with RC4-SHA encrypted SMTP; 11 Feb 2014 14:11:11 -0000 X-IronPort-AV: E=Sophos;i="4.95,825,1384300800"; d="scan'208";a="101601015" Received: from accessns.citrite.net (HELO FTLPEX01CL03.citrite.net) ([10.9.154.239]) by FTLPIPO01.CITRIX.COM with ESMTP; 11 Feb 2014 14:11:06 +0000 Received: from norwich.cam.xci-test.com (10.80.248.129) by smtprelay.citrix.com (10.13.107.80) with Microsoft SMTP Server id 14.2.342.4; Tue, 11 Feb 2014 09:11:04 -0500 Received: from drall.uk.xensource.com ([10.80.16.71] helo=drall.uk.xensource.com.) by norwich.cam.xci-test.com with esmtp (Exim 4.72) (envelope-from ) id 1WDE3E-00005n-H7; Tue, 11 Feb 2014 14:11:04 +0000 From: Ian Campbell To: Date: Tue, 11 Feb 2014 14:11:02 +0000 Message-ID: <1392127864-2605-3-git-send-email-ian.campbell@citrix.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1392127796.26657.130.camel@kazak.uk.xensource.com> References: <1392127796.26657.130.camel@kazak.uk.xensource.com> MIME-Version: 1.0 X-DLP: MIA2 Cc: keir@xen.org, Ian Campbell , stefano.stabellini@eu.citrix.com, ian.jackson@eu.citrix.com, julien.grall@linaro.org, tim@xen.org, jbeulich@suse.com Subject: [Xen-devel] [PATCH v5 3/5] xen/arm: clean and invalidate all guest caches by VMID after domain build. 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: , 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: ian.campbell@citrix.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.46 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: Guests are initially started with caches disabled and so we need to make sure they see consistent data in RAM (requiring a cache clean) but also that they do not have old stale data suddenly appear in the caches when they enable their caches (requiring the invalidate). This can be split into two halves. First we must flush each page as it is allocated to the guest. It is not sufficient to do the flush at scrub time since this will miss pages which are ballooned out by the guest (where the guest must scrub if it cares about not leaking the pagecontent). We need to clean as well as invalidate to make sure that any scrubbing which has occured gets committed to real RAM. To achieve this add a new cacheflush_page function, which is a stub on x86. Secondly we need to flush anything which the domain builder touches, which we do via a new domctl. Signed-off-by: Ian Campbell Acked-by: Ian Jackson Acked-by: Julien Grall Acked-by: Stefano Stabellini Cc: jbeulich@suse.com Cc: keir@xen.org Cc: ian.jackson@eu.citrix.com --- v5: avoid get_order_from_pages and just use 1<next = phys->next; else dom->phys_pages = phys->next; + + xc_domain_cacheflush(dom->xch, dom->guest_domid, phys->first, phys->count); } void xc_dom_unmap_all(struct xc_dom_image *dom) diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index e1d1bec..369c3f3 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -48,6 +48,16 @@ int xc_domain_create(xc_interface *xch, return 0; } +int xc_domain_cacheflush(xc_interface *xch, uint32_t domid, + xen_pfn_t start_pfn, xen_pfn_t nr_pfns) +{ + DECLARE_DOMCTL; + domctl.cmd = XEN_DOMCTL_cacheflush; + domctl.domain = (domid_t)domid; + domctl.u.cacheflush.start_pfn = start_pfn; + domctl.u.cacheflush.nr_pfns = nr_pfns; + return do_domctl(xch, &domctl); +} int xc_domain_pause(xc_interface *xch, uint32_t domid) diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 838fd21..33ed15b 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -628,6 +628,7 @@ int xc_copy_to_domain_page(xc_interface *xch, return -1; memcpy(vaddr, src_page, PAGE_SIZE); munmap(vaddr, PAGE_SIZE); + xc_domain_cacheflush(xch, domid, dst_pfn, 1); return 0; } @@ -641,6 +642,7 @@ int xc_clear_domain_page(xc_interface *xch, return -1; memset(vaddr, 0, PAGE_SIZE); munmap(vaddr, PAGE_SIZE); + xc_domain_cacheflush(xch, domid, dst_pfn, 1); return 0; } diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index 92271c9..a610f0c 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -304,6 +304,9 @@ void bitmap_byte_to_64(uint64_t *lp, const uint8_t *bp, int nbits); /* Optionally flush file to disk and discard page cache */ void discard_file_cache(xc_interface *xch, int fd, int flush); +int xc_domain_cacheflush(xc_interface *xch, uint32_t domid, + xen_pfn_t start_pfn, xen_pfn_t nr_pfns); + #define MAX_MMU_UPDATES 1024 struct xc_mmu { mmu_update_t updates[MAX_MMU_UPDATES]; diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c index 546e86b..45974e7 100644 --- a/xen/arch/arm/domctl.c +++ b/xen/arch/arm/domctl.c @@ -17,6 +17,20 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d, { switch ( domctl->cmd ) { + case XEN_DOMCTL_cacheflush: + { + unsigned long s = domctl->u.cacheflush.start_pfn; + unsigned long e = s + domctl->u.cacheflush.nr_pfns; + + if ( domctl->u.cacheflush.nr_pfns > (1U< #include #include +#include /* First level P2M is 2 consecutive pages */ #define P2M_FIRST_ORDER 1 @@ -228,6 +229,7 @@ enum p2m_operation { ALLOCATE, REMOVE, RELINQUISH, + CACHEFLUSH, }; static int apply_p2m_changes(struct domain *d, @@ -381,6 +383,15 @@ static int apply_p2m_changes(struct domain *d, count++; } break; + + case CACHEFLUSH: + { + if ( !pte.p2m.valid || !p2m_is_ram(pte.p2m.type) ) + break; + + flush_page_to_ram(pte.p2m.base); + } + break; } /* Preempt every 2MiB (mapped) or 32 MiB (unmapped) - arbitrary */ @@ -624,6 +635,20 @@ int relinquish_p2m_mapping(struct domain *d) MATTR_MEM, p2m_invalid); } +int p2m_cache_flush(struct domain *d, xen_pfn_t start_mfn, xen_pfn_t end_mfn) +{ + struct p2m_domain *p2m = &d->arch.p2m; + + start_mfn = MAX(start_mfn, p2m->lowest_mapped_gfn); + end_mfn = MIN(end_mfn, p2m->max_mapped_gfn); + + return apply_p2m_changes(d, CACHEFLUSH, + pfn_to_paddr(start_mfn), + pfn_to_paddr(end_mfn), + pfn_to_paddr(INVALID_MFN), + MATTR_MEM, p2m_invalid); +} + unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn) { paddr_t p = p2m_lookup(d, pfn_to_paddr(gpfn), NULL); diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index 5f484a2..601319c 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -710,6 +710,11 @@ static struct page_info *alloc_heap_pages( /* Initialise fields which have other uses for free pages. */ pg[i].u.inuse.type_info = 0; page_set_owner(&pg[i], NULL); + + /* Ensure cache and RAM are consistent for platforms where the + * guest can control its own visibility of/through the cache. + */ + flush_page_to_ram(page_to_mfn(&pg[i])); } spin_unlock(&heap_lock); diff --git a/xen/include/asm-arm/arm32/page.h b/xen/include/asm-arm/arm32/page.h index cf12a89..cb6add4 100644 --- a/xen/include/asm-arm/arm32/page.h +++ b/xen/include/asm-arm/arm32/page.h @@ -22,6 +22,10 @@ static inline void write_pte(lpae_t *p, lpae_t pte) /* Inline ASM to flush dcache on register R (may be an inline asm operand) */ #define __flush_xen_dcache_one(R) STORE_CP32(R, DCCMVAC) +/* Inline ASM to clean and invalidate dcache on register R (may be an + * inline asm operand) */ +#define __clean_and_invalidate_xen_dcache_one(R) STORE_CP32(R, DCCIMVAC) + /* * Flush all hypervisor mappings from the TLB and branch predictor. * This is needed after changing Xen code mappings. diff --git a/xen/include/asm-arm/arm64/page.h b/xen/include/asm-arm/arm64/page.h index 9551f90..baf8903 100644 --- a/xen/include/asm-arm/arm64/page.h +++ b/xen/include/asm-arm/arm64/page.h @@ -17,6 +17,10 @@ static inline void write_pte(lpae_t *p, lpae_t pte) /* Inline ASM to flush dcache on register R (may be an inline asm operand) */ #define __flush_xen_dcache_one(R) "dc cvac, %" #R ";" +/* Inline ASM to clean and invalidate dcache on register R (may be an + * inline asm operand) */ +#define __clean_and_invalidate_xen_dcache_one(R) "dc civac, %" #R ";" + /* * Flush all hypervisor mappings from the TLB * This is needed after changing Xen code mappings. diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h index e9c884a..3b39c45 100644 --- a/xen/include/asm-arm/p2m.h +++ b/xen/include/asm-arm/p2m.h @@ -78,6 +78,9 @@ void p2m_load_VTTBR(struct domain *d); /* Look up the MFN corresponding to a domain's PFN. */ paddr_t p2m_lookup(struct domain *d, paddr_t gpfn, p2m_type_t *t); +/* Clean & invalidate caches corresponding to a region of guest address space */ +int p2m_cache_flush(struct domain *d, xen_pfn_t start_mfn, xen_pfn_t end_mfn); + /* Setup p2m RAM mapping for domain d from start-end. */ int p2m_populate_ram(struct domain *d, paddr_t start, paddr_t end); /* Map MMIO regions in the p2m: start_gaddr and end_gaddr is the range diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h index 670d4e7..5a371da 100644 --- a/xen/include/asm-arm/page.h +++ b/xen/include/asm-arm/page.h @@ -253,6 +253,9 @@ static inline void flush_xen_dcache_va_range(void *p, unsigned long size) : : "r" (_p), "m" (*_p)); \ } while (0) +/* Flush the dcache for an entire page. */ +void flush_page_to_ram(unsigned long mfn); + /* Print a walk of an arbitrary page table */ void dump_pt_walk(lpae_t *table, paddr_t addr); diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 7a46af5..ccc268d 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -346,6 +346,9 @@ static inline uint32_t cacheattr_to_pte_flags(uint32_t cacheattr) return ((cacheattr & 4) << 5) | ((cacheattr & 3) << 3); } +/* No cache maintenance required on x86 architecture. */ +static inline void flush_page_to_ram(unsigned long mfn) {} + /* return true if permission increased */ static inline bool_t perms_strictly_increased(uint32_t old_flags, uint32_t new_flags) diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 91f01fa..f22fe2e 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -885,6 +885,17 @@ struct xen_domctl_set_max_evtchn { typedef struct xen_domctl_set_max_evtchn xen_domctl_set_max_evtchn_t; DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_max_evtchn_t); +/* + * ARM: Clean and invalidate caches associated with given region of + * guest memory. + */ +struct xen_domctl_cacheflush { + /* IN: page range to flush. */ + xen_pfn_t start_pfn, nr_pfns; +}; +typedef struct xen_domctl_cacheflush xen_domctl_cacheflush_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_cacheflush_t); + struct xen_domctl { uint32_t cmd; #define XEN_DOMCTL_createdomain 1 @@ -954,6 +965,7 @@ struct xen_domctl { #define XEN_DOMCTL_setnodeaffinity 68 #define XEN_DOMCTL_getnodeaffinity 69 #define XEN_DOMCTL_set_max_evtchn 70 +#define XEN_DOMCTL_cacheflush 71 #define XEN_DOMCTL_gdbsx_guestmemio 1000 #define XEN_DOMCTL_gdbsx_pausevcpu 1001 #define XEN_DOMCTL_gdbsx_unpausevcpu 1002 @@ -1012,6 +1024,7 @@ struct xen_domctl { struct xen_domctl_set_max_evtchn set_max_evtchn; struct xen_domctl_gdbsx_memio gdbsx_guest_memio; struct xen_domctl_set_broken_page_p2m set_broken_page_p2m; + struct xen_domctl_cacheflush cacheflush; struct xen_domctl_gdbsx_pauseunp_vcpu gdbsx_pauseunp_vcpu; struct xen_domctl_gdbsx_domstatus gdbsx_domstatus; uint8_t pad[128]; diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 50a35fc..d515702 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -737,6 +737,9 @@ static int flask_domctl(struct domain *d, int cmd) case XEN_DOMCTL_set_max_evtchn: return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SET_MAX_EVTCHN); + case XEN_DOMCTL_cacheflush: + return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__CACHEFLUSH); + default: printk("flask_domctl: Unknown op %d\n", cmd); return -EPERM; @@ -1617,3 +1620,13 @@ static __init int flask_init(void) } xsm_initcall(flask_init); + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors index 1fbe241..a0ed13d 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -196,6 +196,8 @@ class domain2 setclaim # XEN_DOMCTL_set_max_evtchn set_max_evtchn +# XEN_DOMCTL_cacheflush + cacheflush } # Similar to class domain, but primarily contains domctls related to HVM domains