From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45401) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XH4i9-0001sg-LN for qemu-devel@nongnu.org; Tue, 12 Aug 2014 01:33:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XH4hx-00079i-HV for qemu-devel@nongnu.org; Tue, 12 Aug 2014 01:33:29 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:56166) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XH4hm-000787-J7 for qemu-devel@nongnu.org; Tue, 12 Aug 2014 01:33:17 -0400 Message-ID: <53E9A6F9.5010108@huawei.com> Date: Tue, 12 Aug 2014 13:32:41 +0800 From: zhanghailiang MIME-Version: 1.0 References: <1407767399-3030-1-git-send-email-dgilbert@redhat.com> <1407767399-3030-20-git-send-email-dgilbert@redhat.com> In-Reply-To: <1407767399-3030-20-git-send-email-dgilbert@redhat.com> Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v2 19/43] postcopy: OS support test List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: "Dr. David Alan Gilbert (git)" Cc: aarcange@redhat.com, yamahata@private.email.ne.jp, quintela@redhat.com, qemu-devel@nongnu.org, lilei@linux.vnet.ibm.com On 2014/8/11 22:29, Dr. David Alan Gilbert (git) wrote: > From: "Dr. David Alan Gilbert" > > Provide a check to see if the OS we're running on has all the bits > needed for postcopy. > > Creates postcopy-ram.c which will get most of the other helpers we need. > > Signed-off-by: Dr. David Alan Gilbert > --- > Makefile.objs | 2 +- > include/migration/postcopy-ram.h | 19 ++++++ > postcopy-ram.c | 129 +++++++++++++++++++++++++++++++++++++++ > 3 files changed, 149 insertions(+), 1 deletion(-) > create mode 100644 include/migration/postcopy-ram.h > create mode 100644 postcopy-ram.c > > diff --git a/Makefile.objs b/Makefile.objs > index 1f76cea..a7ad235 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -55,7 +55,7 @@ common-obj-y += qemu-file.o > common-obj-$(CONFIG_RDMA) += migration-rdma.o > common-obj-y += qemu-char.o #aio.o > common-obj-y += block-migration.o > -common-obj-y += page_cache.o xbzrle.o > +common-obj-y += page_cache.o xbzrle.o postcopy-ram.o > > common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o > > diff --git a/include/migration/postcopy-ram.h b/include/migration/postcopy-ram.h > new file mode 100644 > index 0000000..dcd1afa > --- /dev/null > +++ b/include/migration/postcopy-ram.h > @@ -0,0 +1,19 @@ > +/* > + * Postcopy migration for RAM > + * > + * Copyright 2013 Red Hat, Inc. and/or its affiliates > + * > + * Authors: > + * Dave Gilbert > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or later. > + * See the COPYING file in the top-level directory. > + * > + */ > +#ifndef QEMU_POSTCOPY_RAM_H > +#define QEMU_POSTCOPY_RAM_H > + > +/* Return 0 if the host supports everything we need to do postcopy-ram */ > +int postcopy_ram_hosttest(void); > + > +#endif > diff --git a/postcopy-ram.c b/postcopy-ram.c > new file mode 100644 > index 0000000..1f3e6ea > --- /dev/null > +++ b/postcopy-ram.c > @@ -0,0 +1,129 @@ > +/* > + * Postcopy migration for RAM > + * > + * Copyright 2013-2014 Red Hat, Inc. and/or its affiliates > + * > + * Authors: > + * Dave Gilbert > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or later. > + * See the COPYING file in the top-level directory. > + * > + */ > + > +/* > + * Postcopy is a migration technique where the execution flips from the > + * source to the destination before all the data has been copied. > + */ > + > +#include > +#include > +#include > + > +#include "qemu-common.h" > +#include "migration/migration.h" > +#include "migration/postcopy-ram.h" > + > +//#define DEBUG_POSTCOPY > + > +#ifdef DEBUG_POSTCOPY > +#define DPRINTF(fmt, ...) \ > + do { fprintf(stderr, "postcopy@%" PRId64 " " fmt "\n", \ > + qemu_clock_get_ms(QEMU_CLOCK_REALTIME), \ > + ## __VA_ARGS__); } while (0) > +#else > +#define DPRINTF(fmt, ...) \ > + do { } while (0) > +#endif > + > +/* Postcopy needs to detect accesses to pages that haven't yet been copied > + * across, and efficiently map new pages in, the techniques for doing this > + * are target OS specific. > + */ > +#if defined(__linux__) > + > +/* On Linux we use: > + * madvise MADV_USERFAULT - to mark an area of anonymous memory such > + * that userspace is notifed of accesses to > + * unallocated areas. > + * userfaultfd - opens a socket to receive USERFAULT messages > + * remap_anon_pages - to shuffle mapped pages into previously unallocated > + * areas without creating loads of VMAs. > + */ > + > +#include > +#include > + > +/* TODO remove once we have libc defs > + * NOTE: These are x86-64 numbers for Andrea's 3.15.0 world */ > +#ifndef MADV_USERFAULT > +#define MADV_USERFAULT 18 > +#define MADV_NOUSERFAULT 19 > +#endif > + > +#ifndef __NR_remap_anon_pages > +#define __NR_remap_anon_pages 317 > +#endif > + > +int postcopy_ram_hosttest(void) > +{ > + /* TODO: Needs guarding with CONFIG_ once we have libc's that have the defs > + * > + * Try each syscall we need, but this isn't a testbench, > + * just enough to see that we have the calls > + */ > + void *testarea, *testarea2; > + long pagesize = getpagesize(); > + > + testarea = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | > + MAP_ANONYMOUS, -1, 0); > + if (!testarea) { > + perror("postcopy_ram_hosttest: Failed to map test area"); > + return -1; > + } > + g_assert(((size_t)testarea& (pagesize-1)) == 0); > + > + if (madvise(testarea, pagesize, MADV_USERFAULT)) { > + perror("postcopy_ram_hosttest: MADV_USERFAULT not available"); > + munmap(testarea, pagesize); > + return -1; > + } > + > + if (madvise(testarea, pagesize, MADV_NOUSERFAULT)) { > + perror("postcopy_ram_hosttest: MADV_NOUSERFAULT not available"); > + munmap(testarea, pagesize); > + return -1; > + } > + > + testarea2 = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | > + MAP_ANONYMOUS, -1, 0); > + if (!testarea2) { > + perror("postcopy_ram_hosttest: Failed to map second test area"); Before return, should we munmap testarea? BTW, i think it is better to use goto statement, which we can handle the error cases together! Best regards, zhanghailiang > + return -1; > + } > + g_assert(((size_t)testarea2& (pagesize-1)) == 0); > + *(char *)testarea = 0; /* Force the map of the new page */ > + if (syscall(__NR_remap_anon_pages, testarea2, testarea, pagesize, 0) != > + pagesize) { > + perror("postcopy_ram_hosttest: remap_anon_pages not available"); > + munmap(testarea, pagesize); > + munmap(testarea2, pagesize); > + return -1; > + } > + > + munmap(testarea, pagesize); > + munmap(testarea2, pagesize); > + return 0; > +} > + > +#else > +/* No target OS support, stubs just fail */ > + > +int postcopy_ram_hosttest(void) > +{ > + error_report("postcopy_ram_hosttest: No OS support"); > + return -1; > +} > + > +#endif > +