From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52075) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YWGpd-0003YI-Kk for qemu-devel@nongnu.org; Fri, 13 Mar 2015 00:04:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YWGpT-0000h4-Nh for qemu-devel@nongnu.org; Fri, 13 Mar 2015 00:04:17 -0400 Received: from ozlabs.org ([2401:3900:2:1::2]:47200) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YWGpT-0000fj-2R for qemu-devel@nongnu.org; Fri, 13 Mar 2015 00:04:07 -0400 Date: Fri, 13 Mar 2015 12:23:46 +1100 From: David Gibson Message-ID: <20150313012346.GA11973@voom.redhat.com> References: <1424883128-9841-1-git-send-email-dgilbert@redhat.com> <1424883128-9841-23-git-send-email-dgilbert@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="Bixl4pq/MaomSJT0" Content-Disposition: inline In-Reply-To: <1424883128-9841-23-git-send-email-dgilbert@redhat.com> Subject: Re: [Qemu-devel] [PATCH v5 22/45] 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, amit.shah@redhat.com, pbonzini@redhat.com, yanghy@cn.fujitsu.com --Bixl4pq/MaomSJT0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Wed, Feb 25, 2015 at 04:51:45PM +0000, Dr. David Alan Gilbert (git) wrot= e: > From: "Dr. David Alan Gilbert" >=20 > Provide a check to see if the OS we're running on has all the bits > needed for postcopy. >=20 > Creates postcopy-ram.c which will get most of the other helpers we need. >=20 > Signed-off-by: Dr. David Alan Gilbert > --- > include/migration/postcopy-ram.h | 19 +++++ > migration/Makefile.objs | 2 +- > migration/postcopy-ram.c | 161 +++++++++++++++++++++++++++++++++= ++++++ > savevm.c | 5 ++ > 4 files changed, 186 insertions(+), 1 deletion(-) > create mode 100644 include/migration/postcopy-ram.h > create mode 100644 migration/postcopy-ram.c >=20 > diff --git a/include/migration/postcopy-ram.h b/include/migration/postcop= y-ram.h > new file mode 100644 > index 0000000..d81934f > --- /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 la= ter. > + * See the COPYING file in the top-level directory. > + * > + */ > +#ifndef QEMU_POSTCOPY_RAM_H > +#define QEMU_POSTCOPY_RAM_H > + > +/* Return true if the host supports everything we need to do postcopy-ra= m */ > +bool postcopy_ram_supported_by_host(void); > + > +#endif > diff --git a/migration/Makefile.objs b/migration/Makefile.objs > index d929e96..0cac6d7 100644 > --- a/migration/Makefile.objs > +++ b/migration/Makefile.objs > @@ -1,7 +1,7 @@ > common-obj-y +=3D migration.o tcp.o > common-obj-y +=3D vmstate.o > common-obj-y +=3D qemu-file.o qemu-file-buf.o qemu-file-unix.o qemu-file= -stdio.o > -common-obj-y +=3D xbzrle.o > +common-obj-y +=3D xbzrle.o postcopy-ram.o > =20 > common-obj-$(CONFIG_RDMA) +=3D rdma.o > common-obj-$(CONFIG_POSIX) +=3D exec.o unix.o fd.o > diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c > new file mode 100644 > index 0000000..a0e20b2 > --- /dev/null > +++ b/migration/postcopy-ram.c > @@ -0,0 +1,161 @@ > +/* > + * 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 la= ter. > + * 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" > +#include "sysemu/sysemu.h" > +#include "qemu/error-report.h" > +#include "trace.h" > + > +/* Postcopy needs to detect accesses to pages that haven't yet been copi= ed > + * across, and efficiently map new pages in, the techniques for doing th= is > + * are target OS specific. > + */ > +#if defined(__linux__) > + > +#include > +#include > +#include > +#include /* for __u64 */ > +#include > + > +#ifdef HOST_X86_64 > +#ifndef __NR_userfaultfd > +#define __NR_userfaultfd 323 Sholdn't this come from the kernel headers imported in the previous patch? Rather than having an arch-specific hack. > +#endif > +#endif > + > +#endif > + > +#if defined(__linux__) && defined(__NR_userfaultfd) > + > +static bool ufd_version_check(int ufd) > +{ > + struct uffdio_api api_struct; > + uint64_t feature_mask; > + > + api_struct.api =3D UFFD_API; > + if (ioctl(ufd, UFFDIO_API, &api_struct)) { > + perror("postcopy_ram_supported_by_host: UFFDIO_API failed"); This should be error_report() not, perror(), to match qemu conventions, shouldn't it? > + return false; > + } > + > + feature_mask =3D (__u64)1 << _UFFDIO_REGISTER | > + (__u64)1 << _UFFDIO_UNREGISTER; > + if ((api_struct.ioctls & feature_mask) !=3D feature_mask) { > + error_report("Missing userfault features: %" PRIu64, > + (uint64_t)(~api_struct.ioctls & feature_mask)); > + return false; > + } > + > + return true; > +} > + > +bool postcopy_ram_supported_by_host(void) > +{ > + long pagesize =3D getpagesize(); > + int ufd =3D -1; > + bool ret =3D false; /* Error unless we change it */ > + void *testarea =3D NULL; > + struct uffdio_register reg_struct; > + struct uffdio_range range_struct; > + uint64_t feature_mask; > + > + if ((1ul << qemu_target_page_bits()) > pagesize) { > + /* The PMI code doesn't yet deal with TPS>HPS */ > + error_report("Target page size bigger than host page size"); > + goto out; > + } > + > + ufd =3D syscall(__NR_userfaultfd, O_CLOEXEC); > + if (ufd =3D=3D -1) { > + perror("postcopy_ram_supported_by_host: userfaultfd not availabl= e"); And here as well? And several places below. > + goto out; > + } > + > + /* Version and features check */ > + if (!ufd_version_check(ufd)) { > + goto out; > + } > + > + /* > + * We need to check that the ops we need are supported on anon memo= ry > + * To do that we need to register a chunk and see the flags that > + * are returned. > + */ > + testarea =3D mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVAT= E | > + MAP_ANONYMOUS, -1, 0); > + if (!testarea) { This should be (testarea =3D=3D MAP_FAILED). Otherwise mmap() failures will always trip the assert below. > + perror("postcopy_ram_supported_by_host: Failed to map test area"= ); > + goto out; > + } > + g_assert(((size_t)testarea & (pagesize-1)) =3D=3D 0); > + > + reg_struct.range.start =3D (uint64_t)(uintptr_t)testarea; > + reg_struct.range.len =3D (uint64_t)pagesize; > + reg_struct.mode =3D UFFDIO_REGISTER_MODE_MISSING; > + > + if (ioctl(ufd, UFFDIO_REGISTER, ®_struct)) { > + perror("postcopy_ram_supported_by_host userfault register"); > + goto out; > + } > + > + range_struct.start =3D (uint64_t)(uintptr_t)testarea; > + range_struct.len =3D (uint64_t)pagesize; I don't think you need the (uint64_t) casts (though you do need the uintptr_t cast). I think the assignment will do an implicit conversion without probvlems. > + if (ioctl(ufd, UFFDIO_UNREGISTER, &range_struct)) { > + perror("postcopy_ram_supported_by_host userfault unregister"); > + goto out; > + } > + > + feature_mask =3D (__u64)1 << _UFFDIO_WAKE | > + (__u64)1 << _UFFDIO_COPY | > + (__u64)1 << _UFFDIO_ZEROPAGE; > + if ((reg_struct.ioctls & feature_mask) !=3D feature_mask) { > + error_report("Missing userfault map features: %" PRIu64, I'm guessing you want PRIx64, in order to make the feature mask at least semi-readable. > + (uint64_t)(~reg_struct.ioctls & feature_mask)); > + goto out; > + } > + > + /* Success! */ > + ret =3D true; > +out: > + if (testarea) { > + munmap(testarea, pagesize); > + } > + if (ufd !=3D -1) { > + close(ufd); > + } > + return ret; > +} > + > +#else > +/* No target OS support, stubs just fail */ > + > +bool postcopy_ram_supported_by_host(void) > +{ > + error_report("%s: No OS support", __func__); > + return false; > +} > + > +#endif > + > diff --git a/savevm.c b/savevm.c > index e301a0a..2ea4c76 100644 > --- a/savevm.c > +++ b/savevm.c > @@ -33,6 +33,7 @@ > #include "qemu/timer.h" > #include "audio/audio.h" > #include "migration/migration.h" > +#include "migration/postcopy-ram.h" > #include "qemu/sockets.h" > #include "qemu/queue.h" > #include "sysemu/cpus.h" > @@ -1109,6 +1110,10 @@ static int loadvm_postcopy_handle_advise(Migration= IncomingState *mis, > return -1; > } > =20 > + if (!postcopy_ram_supported_by_host()) { > + return -1; > + } > + > if (remote_hps !=3D getpagesize()) { > /* > * Some combinations of mismatch are probably possible but it ge= ts --=20 David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson --Bixl4pq/MaomSJT0 Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBAgAGBQJVAjwiAAoJEGw4ysog2bOSv+gP/iqgk78xAc5VB4RUau1jQ8O2 QdyUZvDutlUJS+Oq6r7/xLoD1rN2NdPnkYsDb5u3WnnZxUBTLkr5HSOaYACnoxL4 8E413MrDsF8uRU7ba+n10IKessR1vPNQmh8PihBYwhwGV8smplyXveaeFny5ZeVr r7WPPdTaJEWCoCmFfp8axuJfOR8JnuYCp9QTm/P9v4Zdq7p6Qfr2KlYIFIHsbLgU pXtbAztb8wSENB2cEb509UA2Uef7HNHtsOf2K7XC/c3hQGL/SYJFxwdo0nbVrqMw Ovk5V01WTSiXUuD0MAGvAfBr40/6HAfXVEY5zSTAI6cfcnFUdm1mTnBeoF1nWW+I vNvproHd2u4nSpjEh+PmYfeFR69ykyYHjHR2B7vAp8XAep1J3VHOTPy2eAdO9hoQ FUgazcGjistTLbcc9nIHjo8ngvaEcKZ72Q1Kerpp14k+WcZ+rc7hIKHF29iWnwgw ZPRV42B1RRrzRmkEbrQNHE1T8cSHBDY81r2H2EfRc40ods7Zen7N2PqY9849GqtP NKkai5yQyLDOoVR/2QzDPZVpSAcgAXbroUWulOzQPFIURyB9j2iPiRGptmHhya3u +4eHU9ze+Ipti1MGVLBD5bO7KMAtBmwLljHITdynzr6ESH0SFzrysGSJQu2UDuQI J7xIqGI5kJvh6F+XxtEp =ayFN -----END PGP SIGNATURE----- --Bixl4pq/MaomSJT0--