From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jaeyong Yoo Subject: [PATCH] ARM: cache coherence problem in guestcopy.c Date: Tue, 18 Jun 2013 14:03:25 +0900 Message-ID: <1371531805-31438-1-git-send-email-jaeyong.yoo@samsung.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: Jaeyong Yoo List-Id: xen-devel@lists.xenproject.org I've encountered a rather unusual bug while I'm implementing live migration on arndale board. After resume, domU kernel starts invoking hypercalls and at some point the hypercall parameters delivered to xen are corrupted. After some debugging (with the help of HW debugger), I found that cache polution happens, and here is the detailed sequence. 1) DomU kernel allocates a local variable struct xen_add_to_physmap xatp and the GVA of xatp is 0xc785fe38 (note that not cache-line aligned) (see gnttab_map function in linux/drivers/xen/grant-table.c) 2) GVA of xatp is mapped in xen page table at raw_copy_from_guest function, and the VA of xen is 0xae48ee38 and its contents are cached. 3) DomU kernel reuses xatp to invoke the second hypercall with different parameters. 4) GVA of xatp is mapped again in the same VA of xen, and the cached data at step 2) (the first hypercall parameter) is loaded. The below patch prevents the above problem. I'm wondering, as a better solution, that does unmap_domain_page should invalidate the cache before unmap the page? Signed-off-by: Jaeyong Yoo --- xen/arch/arm/guestcopy.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xen/arch/arm/guestcopy.c b/xen/arch/arm/guestcopy.c index d146cd6..9c4a7e4 100644 --- a/xen/arch/arm/guestcopy.c +++ b/xen/arch/arm/guestcopy.c @@ -25,6 +25,7 @@ unsigned long raw_copy_to_guest(void *to, const void *from, unsigned len) p += offset; memcpy(p, from, size); + flush_xen_dcache_va_range(p, size); unmap_domain_page(p - offset); len -= size; from += size; @@ -55,6 +56,7 @@ unsigned long raw_clear_guest(void *to, unsigned len) p += offset; memset(p, 0x00, size); + flush_xen_dcache_va_range(p, size); unmap_domain_page(p - offset); len -= size; to += size; @@ -84,6 +86,7 @@ unsigned long raw_copy_from_guest(void *to, const void __user *from, unsigned le memcpy(to, p, size); + flush_xen_dcache_va_range(p, size); unmap_domain_page(p); len -= size; from += size; -- 1.7.9.5